/examples/advanced/physics/physicsShapes/PhysicsPolygon.java

http://mt4j.googlecode.com/ · Java · 268 lines · 156 code · 58 blank · 54 comment · 16 complexity · 65712194b5b256d49ff66d1efe1ccacd MD5 · raw file

  1. package advanced.physics.physicsShapes;
  2. import java.util.List;
  3. import javax.media.opengl.glu.GLU;
  4. import org.jbox2d.collision.shapes.PolygonDef;
  5. import org.jbox2d.common.Vec2;
  6. import org.jbox2d.dynamics.Body;
  7. import org.jbox2d.dynamics.BodyDef;
  8. import org.jbox2d.dynamics.World;
  9. import org.mt4j.MTApplication;
  10. import org.mt4j.components.visibleComponents.shapes.GeometryInfo;
  11. import org.mt4j.components.visibleComponents.shapes.mesh.MTTriangleMesh;
  12. import org.mt4j.input.inputProcessors.componentProcessors.rotateProcessor.RotateProcessor;
  13. import org.mt4j.input.inputProcessors.componentProcessors.scaleProcessor.ScaleProcessor;
  14. import org.mt4j.util.math.Vector3D;
  15. import org.mt4j.util.math.Vertex;
  16. import org.mt4j.util.opengl.GluTrianglulator;
  17. import processing.core.PApplet;
  18. public class PhysicsPolygon extends MTTriangleMesh implements IPhysicsComponent {
  19. private float angle;
  20. private World world;
  21. private Body body;
  22. private float density;
  23. private float friction;
  24. private float restituion;
  25. public PhysicsPolygon(Vertex[] vertices, Vector3D position, PApplet applet,
  26. World world, float density, float friction, float restitution, float worldScale
  27. ) {
  28. super(applet, new GeometryInfo(applet, new Vertex[]{}), false);
  29. this.angle = 0;
  30. this.world = world;
  31. this.density = density;
  32. this.friction = friction;
  33. this.restituion = restitution;
  34. this.setGestureAllowance(ScaleProcessor.class, false);
  35. this.setGestureAllowance(RotateProcessor.class, false);
  36. Vertex.scaleVectorArray(vertices, Vector3D.ZERO_VECTOR, 1f/worldScale, 1f/worldScale, 1);
  37. position.scaleLocal(1f/worldScale); //FIXME REALLY?
  38. GluTrianglulator triangulator = new GluTrianglulator(applet);
  39. List<Vertex> physicsTris = triangulator.tesselate(vertices, GLU.GLU_TESS_WINDING_NONZERO);
  40. Vertex[] triangulatedBodyVerts = physicsTris.toArray(new Vertex[physicsTris.size()]);
  41. triangulator.deleteTess();
  42. //Set the triangulated vertices as the polygons (mesh's) vertices
  43. this.setGeometryInfo(new GeometryInfo(applet, triangulatedBodyVerts));
  44. this.translate(position);
  45. Vector3D realBodyCenter = this.getCenterPointGlobal(); //FIXME geht nur if detached from world //rename futurebodycenter?
  46. //Reset position
  47. this.translate(position.getScaled(-1));
  48. //Now get the position where the global center will be after setting the shape at the desired position
  49. this.setPositionGlobal(position);
  50. Vector3D meshCenterAtPosition = this.getCenterPointGlobal();
  51. //Compute the distance we would have to move the vertices for the body creation
  52. //so that the body.position(center) is at the same position as our mesh center
  53. Vector3D realBodyCenterToMeshCenter = meshCenterAtPosition.getSubtracted(realBodyCenter);
  54. //System.out.println("Diff:" + realBodyCenterToMeshCenter);
  55. //Move the vertices so the body position is at the center of the shape
  56. Vertex.translateVectorArray(triangulatedBodyVerts, realBodyCenterToMeshCenter);
  57. this.setGeometryInfo(new GeometryInfo(applet, triangulatedBodyVerts));
  58. // MTPolygon p = new MTPolygon(vertices, applet);
  59. // p.translate(position);
  60. //// p.setPositionGlobal(position);
  61. // Vector3D realBodyCenter = p.getCenterPointGlobal(); //FIXME geht nur if detached from world //rename futurebodycenter?
  62. // //Reset position
  63. // p.translate(position.getScaled(-1));
  64. //
  65. // //Now get the position where the global center will be after setting the shape at the desired position
  66. // p.setPositionGlobal(position);
  67. // Vector3D meshCenterAtPosition = p.getCenterPointGlobal();
  68. //
  69. // //Compute the distance we would have to move the vertices for the body creation
  70. // //so that the body.position(center) is at the same position as our mesh center
  71. // Vector3D realBodyCenterToMeshCenter = meshCenterAtPosition.getSubtracted(realBodyCenter);
  72. // //System.out.println("Diff:" + realBodyCenterToMeshCenter);
  73. //
  74. // //Move the vertices so the body position is at the center of the shape
  75. // Vertex.translateVectorArray(vertices, realBodyCenterToMeshCenter);
  76. Vertex.translateVectorArray(vertices, realBodyCenterToMeshCenter);
  77. //Create vertex structure for creation of decomposition polygon (use the translated vertices)
  78. float xArr[] = new float[vertices.length];
  79. float yArr[] = new float[vertices.length];
  80. for (int i = 0; i < vertices.length; i++) {
  81. Vertex v = vertices[i];
  82. xArr[i] = v.x;
  83. yArr[i] = v.y;
  84. }
  85. //Create a polygon too see if its simple and eventually decompose it
  86. org.jbox2d.util.nonconvex.Polygon myPoly = new org.jbox2d.util.nonconvex.Polygon(xArr, yArr);
  87. PolygonDef pd = new PolygonDef();
  88. if (density != 0.0f){
  89. pd.density = density;
  90. pd.friction = friction;
  91. pd.restitution = restituion;
  92. }
  93. //Create polygon body
  94. BodyDef dymBodyDef = new BodyDef();
  95. // dymBodyDef.position = new Vec2(position.x /worldScale, position.y /worldScale);
  96. dymBodyDef.position = new Vec2(position.x , position.y );
  97. this.bodyDefB4CreationCallback(dymBodyDef);
  98. this.body = world.createBody(dymBodyDef);
  99. // GluTrianglulator triangulator = new GluTrianglulator(applet);
  100. // List<Vertex> physicsTris = triangulator.tesselate(vertices, GLU.GLU_TESS_WINDING_NONZERO);
  101. // Vertex[] triangulatedBodyVerts = physicsTris.toArray(new Vertex[physicsTris.size()]);
  102. // triangulator.deleteTess();
  103. // //Set the triangulated vertices as the polygons (mesh's) vertices
  104. // this.setGeometryInfo(new GeometryInfo(applet, triangulatedBodyVerts));
  105. //Decompose poly and add verts to phys body if possible
  106. int success = org.jbox2d.util.nonconvex.Polygon.decomposeConvexAndAddTo(myPoly, this.body, pd);
  107. if (success != -1){
  108. System.out.println("-> Ear clipping SUCCESSFUL -> Using triangulated and polygonized shape for b2d.");
  109. this.body.setMassFromShapes();
  110. this.body.setUserData(this);
  111. this.setUserData("box2d", this.body); //TODO rename userData
  112. //Performance hit! but prevents object from sticking to another sometimes
  113. // theBody.setBullet(true);
  114. }else{
  115. System.out.println("-> Ear clipping had an ERROR - trying again by triangulating shape for b2d with GLU-Triangulator");
  116. // GluTrianglulator triangulator = new GluTrianglulator(app);
  117. // List<Vertex> physicsTris = triangulator.tesselate(bodyVerts, GLU.GLU_TESS_WINDING_NONZERO);
  118. // Vertex[] triangulatedBodyVerts = physicsTris.toArray(new Vertex[physicsTris.size()]);
  119. //System.out.println("GLU tris created: " + triangulatedBodyVerts.length);
  120. //Cap the max triangles - dont use anymore triangles for the physics body..
  121. int cap = 400;
  122. if (triangulatedBodyVerts.length > cap){
  123. //System.err.println("OVER cap! -> capping!");
  124. Vertex[] tmp = new Vertex[cap];
  125. System.arraycopy(triangulatedBodyVerts, 0, tmp, 0, cap);
  126. triangulatedBodyVerts = tmp;
  127. }
  128. //Create polygon body
  129. world.destroyBody(this.body);
  130. dymBodyDef = new BodyDef();
  131. dymBodyDef.position = new Vec2(position.x, position.y);
  132. this.bodyDefB4CreationCallback(dymBodyDef);
  133. this.body = world.createBody(dymBodyDef);
  134. for (int i = 0; i < triangulatedBodyVerts.length/3; i++) {
  135. //Create polygon definition
  136. PolygonDef polyDef = new PolygonDef();
  137. if (density != 0.0f){
  138. polyDef.density = density;
  139. polyDef.friction = friction;
  140. polyDef.restitution = restituion;
  141. }
  142. this.polyDefB4CreationCallback(polyDef); //FIXME TEST
  143. //Add triangle vertices
  144. Vertex vertex1 = triangulatedBodyVerts[i*3];
  145. Vertex vertex2 = triangulatedBodyVerts[i*3+1];
  146. Vertex vertex3 = triangulatedBodyVerts[i*3+2];
  147. polyDef.addVertex(new Vec2(vertex1.x, vertex1.y));
  148. polyDef.addVertex(new Vec2(vertex2.x, vertex2.y));
  149. polyDef.addVertex(new Vec2(vertex3.x, vertex3.y));
  150. //Add poly to body
  151. this.body.createShape(polyDef);
  152. }
  153. this.body.setMassFromShapes();
  154. //FIXME TEST - performance hit!?
  155. //theBody.setBullet(true);
  156. this.body.setUserData(this);
  157. this.setUserData("box2d", this.body); //TODO rename userData
  158. }
  159. // p.destroy();
  160. }
  161. protected void polyDefB4CreationCallback(PolygonDef def){
  162. }
  163. protected void bodyDefB4CreationCallback(BodyDef def){
  164. }
  165. //@Override
  166. public void rotateZGlobal(Vector3D rotationPoint, float degree) {
  167. angle += degree;
  168. super.rotateZGlobal(rotationPoint, degree);
  169. }
  170. public float getAngle() {
  171. return angle;
  172. }
  173. public void setCenterRotation(float angle){
  174. float degreeAngle = MTApplication.degrees(angle);
  175. float oldAngle = this.getAngle();
  176. float diff = degreeAngle-oldAngle;
  177. //System.out.println("Old angle: " + oldAngle + " new angle:" + degreeAngle + " diff->" + diff);
  178. this.rotateZGlobal(this.getCenterPointGlobal(), diff);
  179. }
  180. //@Override
  181. protected void destroyComponent() {
  182. Object o = this.getUserData("box2d");
  183. if (o != null && o instanceof Body){
  184. Body box2dBody = (Body)o;
  185. boolean exists = false;
  186. for (Body body = world.getBodyList(); body != null; body = body.getNext()) {
  187. if (body.equals(this.body))
  188. exists = true;//Delete later to avoid concurrent modification
  189. }
  190. if (exists)
  191. box2dBody.getWorld().destroyBody(box2dBody);
  192. }
  193. super.destroyComponent();
  194. }
  195. public World getWorld() {
  196. return world;
  197. }
  198. public Body getBody() {
  199. return body;
  200. }
  201. public float getDensity() {
  202. return density;
  203. }
  204. public float getFriction() {
  205. return friction;
  206. }
  207. public float getRestituion() {
  208. return restituion;
  209. }
  210. }