Package advanced.physics.physicsShapes

Source Code of advanced.physics.physicsShapes.PhysicsRectangle

package advanced.physics.physicsShapes;

import java.util.List;

import javax.media.opengl.glu.GLU;

import org.jbox2d.collision.shapes.PolygonDef;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.World;
import org.mt4j.MTApplication;
import org.mt4j.components.MTComponent;
import org.mt4j.components.bounds.BoundsArbitraryPlanarPolygon;
import org.mt4j.components.bounds.IBoundingShape;
import org.mt4j.components.visibleComponents.GeometryInfo;
import org.mt4j.components.visibleComponents.shapes.MTRectangle;
import org.mt4j.input.inputProcessors.componentProcessors.rotateProcessor.RotateProcessor;
import org.mt4j.input.inputProcessors.componentProcessors.scaleProcessor.ScaleProcessor;
import org.mt4j.util.math.Vector3D;
import org.mt4j.util.math.Vertex;
import org.mt4j.util.opengl.GluTrianglulator;

import processing.core.PApplet;
import processing.core.PGraphics;
import processing.core.PImage;
import advanced.physics.util.PhysicsHelper;

public class PhysicsRectangle extends MTRectangle implements IPhysicsComponent{
  private float angle;
  private boolean drawBounds;
 
  private World world;
  private Body body;
  private float density;
  private float friction;
  private float restituion;
 
  /*
  PhysicsRectangle rect = new PhysicsRectangle(new Vector3D(400,200), 100,150, app, world, 0.6f, 0.4f, 0.2f, scale);
  rect.setNoStroke(true);
  PhysicsHelper.addDragJoint(world, rect, rect.getBody().isDynamic(), scale);
  physObjGroup.addChild(rect);
  */
 
  public PhysicsRectangle(
      Vector3D centerPosition,
      float width, float height, PApplet applet,
      World world, float density, float friction, float restitution, float scale
  ) {
    super(0, 0, PhysicsHelper.scaleDown(width, scale), PhysicsHelper.scaleDown(height, scale), applet);
    this.angle = 0;
    this.drawBounds = false;
    this.world = world;
    this.density = density;
    this.friction = friction;
    this.restituion = restitution;
   
    Vector3D scaledPos = PhysicsHelper.scaleDown(centerPosition.getCopy(), scale);
//    PhysicsHelper.scaleDown(centerPosition, scale);
//    centerPosition.scaleLocal(1f/scale);
   
    BodyDef dymBodyDef = new BodyDef();
//    dymBodyDef.position = new Vec2(pos.x, pos.y);
    dymBodyDef.position = new Vec2(scaledPos.x, scaledPos.y);//FIXME WORKS?
    this.bodyDefB4CreationCallback(dymBodyDef);
    this.body = world.createBody(dymBodyDef);
   
    PolygonDef dymShapeDef = new PolygonDef();
    dymShapeDef.setAsBox( (width/2f)/scale, (height/2f)/scale);
//    dymShapeDef.setAsBox( (width/2f), (height/2f));
    if (density != 0.0f){
      dymShapeDef.density     = density;
      dymShapeDef.friction     = friction;
      dymShapeDef.restitution   = restitution;
    }
   
    this.polyDefB4CreationCallback(dymShapeDef); //FIXME TEST
   
    body.createShape(dymShapeDef);
    body.setMassFromShapes();
   
    //TEST
//    theBody.setBullet(true);
   
    this.setPositionGlobal(scaledPos);
    body.setUserData(this);
    this.setUserData("box2d", body);
    this.setGestureAllowance(ScaleProcessor.class, false);
    this.setGestureAllowance(RotateProcessor.class, false);
  }
 
 
 
 
  public PhysicsRectangle(PImage texture,
      Vector3D pos,
      PApplet applet,
      Vertex[] physicsVertices,
      World world, float density, float friction, float restitution, float scale
  ) {
    super(texture, applet);
    this.angle = 0;
    this.drawBounds = false;
    this.world = world;
    this.density = density;
    this.friction = friction;
    this.restituion = restitution;
   
    this.setGestureAllowance(ScaleProcessor.class, false);
    this.setGestureAllowance(RotateProcessor.class, false);
   
    //Scale shape vertices
//    this.setGeometryInfo(new GeometryInfo(applet, Vertex.scaleVectorArray(this.getGeometryInfo().getVertices(), Vector3D.ZERO_VECTOR, 1f/scale, 1f/scale, 1)));
//    this.setGeometryInfo(new GeometryInfo(applet, PhysicsHelper.scaleDown(this.getGeometryInfo().getVertices(), scale)));
    this.setGeometryInfo(new GeometryInfo(applet, PhysicsHelper.scaleDown(Vertex.getDeepVertexArrayCopy(this.getGeometryInfo().getVertices()), scale)));
   
    //Scale physics vertics
//    Vertex.scaleVectorArray(bodyVerts, Vector3D.ZERO_VECTOR, 1f/scale, 1f/scale, 1);
    PhysicsHelper.scaleDown(physicsVertices, scale);
   
    Vector3D scaledPos = PhysicsHelper.scaleDown(pos.getCopy(), scale);
    //Scale position
//    pos.scaleLocal(1f/scale); //FIXME REALLY?
//    PhysicsHelper.scaleDown(pos, scale);
   
    this.setGestureAllowance(ScaleProcessor.class, false);
    this.setGestureAllowance(RotateProcessor.class, false);
   
    //Temporarily move the mesh so that we know where the calculated center of the body
    //would be (the body takes the body.position as the center reference instead of a calculated center)
//    //FIXME welchen centerpoint nehmen? -> kommt auch drauf an ob shape schon auf canvas war!?
    //We have to do this because the anchor point ("position") of the pyhsics shape is the body.position
    //but the anchor point of our shapes is the point returned from getCenterpoint..()
    this.translate(scaledPos);
    Vector3D realBodyCenter = this.getCenterPointGlobal(); //FIXME geht nur if detached from world //rename futurebodycenter?
    //Reset position
    this.translate(scaledPos.getScaled(-1));
   
    //Now get the position where the global center will be after setting the shape at the desired position
    this.setPositionGlobal(scaledPos);
    Vector3D meshCenterAtPosition = this.getCenterPointGlobal();

    //Compute the distance we would have to move the vertices for the body creation
    //so that the body.position(center) is at the same position as our mesh center
    Vector3D realBodyCenterToMeshCenter = meshCenterAtPosition.getSubtracted(realBodyCenter);
    //System.out.println("Diff:" +  realBodyCenterToMeshCenter);
   
    //FIXME TEST Needed for level saving the local vertices at the right position
    this.setUserData("realBodyCenterToMeshCenter", realBodyCenterToMeshCenter);

    //Move the vertices so the body position is at the center of the shape
    Vertex.translateVectorArray(physicsVertices, realBodyCenterToMeshCenter);

    //Create vertex structure for creation of decomposition polygon (use the translated vertices)
    float xArr[] = new float[physicsVertices.length];
    float yArr[] = new float[physicsVertices.length];
    for (int i = 0; i < physicsVertices.length; i++) {
      Vertex v = physicsVertices[i];
      xArr[i] = v.x;
      yArr[i] = v.y;
    }

    //Create a polygon too see if its simple and eventually decompose it
    org.jbox2d.util.nonconvex.Polygon myPoly = new org.jbox2d.util.nonconvex.Polygon(xArr, yArr);

    //System.out.println("Polygon is simple! -> Using convex decomposition for physics shape and glu triangulated mesh for display!");
    PolygonDef pd = new PolygonDef();
    if (density != 0.0f){
      pd.density     = density;
      pd.friction   = friction;
      pd.restitution   = restituion;
    }

    //Create polygon body
    BodyDef dymBodyDef = new BodyDef();
    dymBodyDef.position = new Vec2(scaledPos.x, scaledPos.y);
    this.bodyDefB4CreationCallback(dymBodyDef);
    this.body = world.createBody(dymBodyDef);

    this.polyDefB4CreationCallback(pd); //FIXME TEST
   
    int success = org.jbox2d.util.nonconvex.Polygon.decomposeConvexAndAddTo(myPoly, body, pd);
    if (success != -1){
      System.out.println("-> Ear clipping SUCCESSFUL -> Using triangulated and polygonized shape for b2d.");
      body.setMassFromShapes();
      body.setUserData(this);
      this.setUserData("box2d", body);
      //Performance hit! but prevents object from sticking to another sometimes
//      theBody.setBullet(true);
    }else{
      System.out.println("-> Ear clipping had an ERROR - trying again by triangulating shape for b2d with GLU-Triangulator");
      GluTrianglulator triangulator = new GluTrianglulator(applet);
      List<Vertex> physicsTris = triangulator.tesselate(physicsVertices, GLU.GLU_TESS_WINDING_NONZERO);
      Vertex[] triangulatedBodyVerts = physicsTris.toArray(new Vertex[physicsTris.size()]);
      //System.out.println("GLU tris created: " + triangulatedBodyVerts.length);

      //Cap the max triangles - dont use anymore triangles for the physics body..
      int cap = 400;
      if (triangulatedBodyVerts.length > cap){
        //System.err.println("OVER cap! -> capping!");
        Vertex[] tmp = new Vertex[cap];
        System.arraycopy(triangulatedBodyVerts, 0, tmp, 0, cap);
        triangulatedBodyVerts = tmp;
      }

      //Create polygon body
      world.destroyBody(body);
      dymBodyDef = new BodyDef();
      dymBodyDef.position = new Vec2(scaledPos.x, scaledPos.y);
      this.bodyDefB4CreationCallback(dymBodyDef);
      body = world.createBody(dymBodyDef);
      for (int i = 0; i < triangulatedBodyVerts.length/3; i++) {
        //Create polygon definition
        PolygonDef polyDef = new PolygonDef();
        if (density != 0.0f){
          polyDef.density     = density;
          polyDef.friction     = friction;
          polyDef.restitution   = restituion;
        }
        //Add triangle vertices
        Vertex vertex1 = triangulatedBodyVerts[i*3];
        Vertex vertex2 = triangulatedBodyVerts[i*3+1];
        Vertex vertex3 = triangulatedBodyVerts[i*3+2];
        polyDef.addVertex(new Vec2(vertex1.x, vertex1.y));
        polyDef.addVertex(new Vec2(vertex2.x, vertex2.y));
        polyDef.addVertex(new Vec2(vertex3.x, vertex3.y));
       
        this.polyDefB4CreationCallback(pd); //FIXME TEST
       
        //Add poly to body
        body.createShape(polyDef);
      }
      body.setMassFromShapes();
      //performance hit!?
      //theBody.setBullet(true);
      body.setUserData(this);
      this.setUserData("box2d", body);
      triangulator.deleteTess();
    }
   

  }

 
 
  public void setPhysicsVertices(Vertex[] bodyVerts,
      Vector3D pos,
      float scale
    ){
    if (this.body != null && this.world != null){
      world.destroyBody(this.body);
    }
   
    //Scale physics vertics
//    Vertex.scaleVectorArray(bodyVerts, Vector3D.ZERO_VECTOR, 1f/scale, 1f/scale, 1);
    PhysicsHelper.scaleDown(bodyVerts, scale);
   
    //Scale position
//    pos.scaleLocal(1f/scale); //FIXME REALLY?
//    PhysicsHelper.scaleDown(pos, scale);
    Vector3D scaledPos = PhysicsHelper.scaleDown(pos.getCopy(), scale);
   
    MTComponent parent = this.getParent();
    this.removeFromParent();
   
    //Temporarily move the mesh so that we know where the calculated center of the body
    //would be (the body takes the body.position as the center reference instead of a calculated center)
//    //FIXME welchen centerpoint nehmen? -> kommt auch drauf an ob shape schon auf canvas war!?
    //We have to do this because the anchor point ("position") of the pyhsics shape is the body.position
    //but the anchor point of our shapes is the point returned from getCenterpoint..()
    this.translate(scaledPos);
    Vector3D realBodyCenter = this.getCenterPointGlobal(); //FIXME geht nur if detached from world //rename futurebodycenter?
    //Reset position
    this.translate(scaledPos.getScaled(-1));
   
    //Now get the position where the global center will be after setting the shape at the desired position
    this.setPositionGlobal(scaledPos);
    Vector3D meshCenterAtPosition = this.getCenterPointGlobal();
   
    if (parent != null){
      parent.addChild(this);//TODO add at same index
    }

    //Compute the distance we would have to move the vertices for the body creation
    //so that the body.position(center) is at the same position as our mesh center
    Vector3D realBodyCenterToMeshCenter = meshCenterAtPosition.getSubtracted(realBodyCenter);
    //System.out.println("Diff:" +  realBodyCenterToMeshCenter);

    //Move the vertices so the body position is at the center of the shape
    Vertex.translateVectorArray(bodyVerts, realBodyCenterToMeshCenter);
   
    //FIXME TEST
    this.setUserData("realBodyCenterToMeshCenter", realBodyCenterToMeshCenter);

    //Create vertex structure for creation of decomposition polygon (use the translated vertices)
    float xArr[] = new float[bodyVerts.length];
    float yArr[] = new float[bodyVerts.length];
    for (int i = 0; i < bodyVerts.length; i++) {
      Vertex v = bodyVerts[i];
      xArr[i] = v.x;
      yArr[i] = v.y;
    }

    //Create a polygon too see if its simple and eventually decompose it
    org.jbox2d.util.nonconvex.Polygon myPoly = new org.jbox2d.util.nonconvex.Polygon(xArr, yArr);

    //System.out.println("Polygon is simple! -> Using convex decomposition for physics shape and glu triangulated mesh for display!");
    PolygonDef pd = new PolygonDef();
    if (density != 0.0f){
      pd.density     = density;
      pd.friction   = friction;
      pd.restitution   = restituion;
    }

    //Create polygon body
    BodyDef dymBodyDef = new BodyDef();
    dymBodyDef.position = new Vec2(scaledPos.x, scaledPos.y);
    this.bodyDefB4CreationCallback(dymBodyDef);
    this.body = world.createBody(dymBodyDef);
   
    this.polyDefB4CreationCallback(pd); //FIXME TEST
   
    int success = org.jbox2d.util.nonconvex.Polygon.decomposeConvexAndAddTo(myPoly, body, pd);
    if (success != -1){
      System.out.println("-> Ear clipping SUCCESSFUL -> Using triangulated and polygonized shape for b2d.");
      body.setMassFromShapes();
      body.setUserData(this);
      this.setUserData("box2d", body);
      //Performance hit! but prevents object from sticking to another sometimes
//      theBody.setBullet(true);
    }else{
      System.out.println("-> Ear clipping had an ERROR - trying again by triangulating shape for b2d with GLU-Triangulator");
      GluTrianglulator triangulator = new GluTrianglulator(this.getRenderer());
      List<Vertex> physicsTris = triangulator.tesselate(bodyVerts, GLU.GLU_TESS_WINDING_NONZERO);
      Vertex[] triangulatedBodyVerts = physicsTris.toArray(new Vertex[physicsTris.size()]);
      //System.out.println("GLU tris created: " + triangulatedBodyVerts.length);

      //Cap the max triangles - dont use anymore triangles for the physics body..
      int cap = 400;
      if (triangulatedBodyVerts.length > cap){
        //System.err.println("OVER cap! -> capping!");
        Vertex[] tmp = new Vertex[cap];
        System.arraycopy(triangulatedBodyVerts, 0, tmp, 0, cap);
        triangulatedBodyVerts = tmp;
      }

      //Create polygon body
      world.destroyBody(body);
      dymBodyDef = new BodyDef();
      dymBodyDef.position = new Vec2(scaledPos.x, scaledPos.y);
      this.bodyDefB4CreationCallback(dymBodyDef);
      body = world.createBody(dymBodyDef);
      for (int i = 0; i < triangulatedBodyVerts.length/3; i++) {
        //Create polygon definition
        PolygonDef polyDef = new PolygonDef();
        if (density != 0.0f){
          polyDef.density     = density;
          polyDef.friction     = friction;
          polyDef.restitution   = restituion;
        }
        //Add triangle vertices
        Vertex vertex1 = triangulatedBodyVerts[i*3];
        Vertex vertex2 = triangulatedBodyVerts[i*3+1];
        Vertex vertex3 = triangulatedBodyVerts[i*3+2];
        polyDef.addVertex(new Vec2(vertex1.x, vertex1.y));
        polyDef.addVertex(new Vec2(vertex2.x, vertex2.y));
        polyDef.addVertex(new Vec2(vertex3.x, vertex3.y));
       
        this.polyDefB4CreationCallback(polyDef); //FIXME TEST
        //Add poly to body
        body.createShape(polyDef);
      }
      body.setMassFromShapes();
      //FIXME TEST - performance hit!?
      //theBody.setBullet(true);
      body.setUserData(this);
      this.setUserData("box2d", body);
      triangulator.deleteTess();
    }
  }
 
  protected void polyDefB4CreationCallback(PolygonDef def){
   
  }
 
  protected void bodyDefB4CreationCallback(BodyDef def){
   
  }
 
//  private Vertex[] physicsVertices;
// 
//  private Vertex[] getPhysicsVertices(){
//    return this.physicsVertices;
//  }
 
 
 
 
  //@Override
  public void drawComponent(PGraphics g) {
    super.drawComponent(g);

    if (drawBounds){
      IBoundingShape bounds = this.getBounds();
      if (bounds instanceof BoundsArbitraryPlanarPolygon){
        BoundsArbitraryPlanarPolygon bound = (BoundsArbitraryPlanarPolygon)bounds;

        Vector3D[] boundVecs = bound.getVectorsLocal();
//        app.noFill();
        g.fill(100);
        g.stroke(50);
        g.beginShape();
        for (int i = 0; i < boundVecs.length; i++) {
          Vector3D v = boundVecs[i];
//          app.vertex(v.x*scale, v.y*scale, v.z);
          g.vertex(v.x, v.y, v.z);
        }
        g.endShape();
      }
    }
  }
 
  //@Override
  public void rotateZGlobal(Vector3D rotationPoint, float degree) {
    angle += degree;
    super.rotateZGlobal(rotationPoint, degree);
  }  

  public float getAngle() {
    return angle;
  }
 
  public void setCenterRotation(float angle){
    float degreeAngle = MTApplication.degrees(angle);
    float oldAngle = this.getAngle();
    float diff = degreeAngle-oldAngle;
    //System.out.println("Old angle: " + oldAngle + " new angle:" + degreeAngle + " diff->" +  diff);
    this.rotateZGlobal(this.getCenterPointGlobal(), diff);
  }
 
  //@Override
  protected void destroyComponent() {
    super.destroyComponent();
    boolean exists = false;
    for (Body body = world.getBodyList(); body != null; body = body.getNext()) {
      if (body.equals(this.body))
        exists = true;//Delete later to avoid concurrent modification
    }
    if (exists)
      world.destroyBody(body);
  }




  public World getWorld() {
    return world;
  }




  public Body getBody() {
    return body;
  }




  public float getDensity() {
    return density;
  }




  public float getFriction() {
    return friction;
  }




  public float getRestituion() {
    return restituion;
  }
 
 

}
TOP

Related Classes of advanced.physics.physicsShapes.PhysicsRectangle

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.