Package advanced.physics.util

Source Code of advanced.physics.util.PhysicsHelper

/***********************************************************************
* mt4j Copyright (c) 2008 - 2009 Christopher Ruff, Fraunhofer-Gesellschaft All rights reserved.
*   This program is free software: you can redistribute it and/or modify
*   it under the terms of the GNU General Public License as published by
*   the Free Software Foundation, either version 3 of the License, or
*   (at your option) any later version.
*
*   This program is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details.
*
*   You should have received a copy of the GNU General Public License
*   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
***********************************************************************/
package advanced.physics.util;

import java.util.ArrayList;
import java.util.List;

import javax.media.opengl.glu.GLU;

import org.jbox2d.collision.AABB;
import org.jbox2d.collision.shapes.CircleShape;
import org.jbox2d.collision.shapes.EdgeChainDef;
import org.jbox2d.collision.shapes.EdgeShape;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.collision.shapes.Shape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.World;
import org.jbox2d.dynamics.joints.Joint;
import org.jbox2d.dynamics.joints.JointType;
import org.jbox2d.dynamics.joints.MouseJoint;
import org.jbox2d.dynamics.joints.MouseJointDef;
import org.jbox2d.util.nonconvex.Polygon;
import org.mt4j.MTApplication;
import org.mt4j.components.MTComponent;
import org.mt4j.input.inputProcessors.IGestureEventListener;
import org.mt4j.input.inputProcessors.MTGestureEvent;
import org.mt4j.input.inputProcessors.componentProcessors.AbstractComponentProcessor;
import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragEvent;
import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragProcessor;
import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.MultipleDragProcessor;
import org.mt4j.util.math.Tools3D;
import org.mt4j.util.math.Vector3D;
import org.mt4j.util.math.Vertex;
import org.mt4j.util.opengl.GLMaterial;
import org.mt4j.util.opengl.GluTrianglulator;

import advanced.physics.physicsShapes.PhysicsRectangle;


import processing.core.PApplet;

public class PhysicsHelper {
 
 
  public static MouseJoint createDragJoint(World world, Body body, float x, float y){
    MouseJointDef mjd = new MouseJointDef();
    mjd.body1 = body; // Not used, avoid a NPE
    mjd.body2 = body;
    mjd.target = new Vec2(x, y);
//    mjd.target = new Vec2(x/scale, y/scale);
//    mjd.maxForce = 8000.0f * body.m_mass;
//    mjd.maxForce = 99000.0f * body.m_mass;
//    mjd.maxForce = 99000.0f * body.m_mass;
//    mjd.maxForce = Float.MAX_VALUE; //Too big values will result in erratic behaviour with more than 1 mousejoint on a component
    mjd.maxForce = 90000.0f * body.m_mass;
    return (MouseJoint) world.createJoint(mjd);
  }
 
//  /*
  public static void removeDragJoints(Body body){
//    MouseJoint mouseJoint = (MouseJoint) comp.getUserData("mouseJoint");
//    if (mouseJoint != null){
//    world.destroyJoint(mouseJoint); 
//    }
    //FIXME this doesent remove the userData that pointed to the mousejoint!
    for (Joint joint = body.getWorld().getJointList(); joint != null; joint = joint.getNext()) {
      JointType type = joint.getType();
      switch (type) {
      case MOUSE_JOINT:
        MouseJoint mj = (MouseJoint)joint;
        if (body.equals(mj.getBody1()) || body.equals(mj.getBody2())){
          body.getWorld().destroyJoint(mj);
        }
        break;
      default:
        break;
      }
    }
  }
//  */
 
  public static void addDragJoint(World world, MTComponent comp, boolean isDynamic, float scale){
    final float worldScale = scale;
    final World theWorld = world;
   
    if (isDynamic){
      //DYNAMIC BODIES MAKE MOUSEJOINTS
      comp.removeAllGestureEventListeners(DragProcessor.class);

      comp.registerInputProcessor(new MultipleDragProcessor(comp.getRenderer()));
      comp.addGestureListener(MultipleDragProcessor.class, new IGestureEventListener() {

//        comp.addGestureListener(DragProcessor.class, new IGestureEventListener() {
        //@Override
        public boolean processGestureEvent(MTGestureEvent ge) {
          DragEvent de = (DragEvent)ge;
          try{
            MTComponent comp = (MTComponent)de.getTargetComponent();
            Body body = (Body)comp.getUserData("box2d");
            MouseJoint mouseJoint;
            Vector3D to = new Vector3D(de.getTo());
            //Un-scale position from mt4j to box2d
            PhysicsHelper.scaleDown(to, worldScale);
            //System.out.println("MouseJoint To: " + to);
            long cursorID =  de.getDragCursor().getId();

            switch (de.getId()) {
            case DragEvent.GESTURE_DETECTED:
              comp.sendToFront();
              body.wakeUp();
              mouseJoint = createDragJoint(theWorld, body, to.x, to.y);
              comp.setUserData("mouseJoint" + cursorID, mouseJoint);
              break;
            case DragEvent.GESTURE_UPDATED:
              mouseJoint = (MouseJoint) comp.getUserData("mouseJoint" + cursorID);
              if (mouseJoint != null){
                mouseJoint.setTarget(new Vec2(to.x, to.y));
              }
              break;
            case DragEvent.GESTURE_ENDED:
              mouseJoint = (MouseJoint) comp.getUserData("mouseJoint" + cursorID);
              if (mouseJoint != null){
                comp.setUserData("mouseJoint" + cursorID, null);
//                theWorld.destroyJoint(mouseJoint); 
                //Only destroy the joint if it isnt already (go through joint list and check)
                for (Joint joint = theWorld.getJointList(); joint != null; joint = joint.getNext()) {
                  JointType type = joint.getType();
                  switch (type) {
                  case MOUSE_JOINT:
                    MouseJoint mj = (MouseJoint)joint;
                    if (body.equals(mj.getBody1()) || body.equals(mj.getBody2())){
//                      theWorld.destroyJoint(mj);
                      if (mj.equals(mouseJoint)) {
                        theWorld.destroyJoint(mj);
                      }
                    }
                    break;
                  default:
                    break;
                  }
                }
              }
              mouseJoint = null;
              break;
            default:
              break;
            }
          }catch (Exception e) {
            System.err.println(e.getMessage());
          }
          return true;
        }
      });
    }else{
      comp.removeAllGestureEventListeners(DragProcessor.class);
     
      boolean hasDragProcessor = false;
      AbstractComponentProcessor[] p = comp.getInputProcessors();
      for (int i = 0; i < p.length; i++) {
        AbstractComponentProcessor abstractComponentProcessor = p[i];
        if (abstractComponentProcessor instanceof DragProcessor) {
          hasDragProcessor = true;
        }
      }
      if (!hasDragProcessor){
        comp.registerInputProcessor(new DragProcessor(comp.getRenderer()));
      }
     
      //For static bodies just alter the transform of the body
      comp.addGestureListener(DragProcessor.class, new IGestureEventListener() {
        //@Override
        public boolean processGestureEvent(MTGestureEvent ge) {
          DragEvent de = (DragEvent)ge;
          Vector3D dir = PhysicsHelper.scaleDown(new Vector3D(de.getTranslationVect()), worldScale);
          try{
            MTComponent comp = (MTComponent)de.getTargetComponent();
            Body body = (Body)comp.getUserData("box2d");
            body.setXForm(
                new Vec2(body.getPosition().x + dir.x, body.getPosition().y + dir.y),
                body.getAngle());
            switch (de.getId()) {
            case DragEvent.GESTURE_DETECTED:
              comp.sendToFront();
              body.wakeUp();
              break;
            case DragEvent.GESTURE_UPDATED:
            case DragEvent.GESTURE_ENDED:
            default:
              break;
            }
          }catch (Exception e) {
            System.err.println(e.getMessage());
          }
          return true;
        }
      });
    }
  }

   
 
  public static List<Vertex> triangulateEarClips(List<Vertex> vertices){
    org.jbox2d.util.nonconvex.Triangle[] tri = getEarClipTriangles(vertices);
    List<Vertex> tris = new ArrayList<Vertex>();
    for (int i = 0; i < tri.length; i++) {
      org.jbox2d.util.nonconvex.Triangle triangle = tri[i];
      tris.add(new Vertex(triangle.x[0], triangle.y[0],0));
      tris.add(new Vertex(triangle.x[1], triangle.y[1],0));
      tris.add(new Vertex(triangle.x[2], triangle.y[2],0));
    }
    return tris;
  }
 
 
  public static org.jbox2d.util.nonconvex.Triangle[] getEarClipTriangles(List<Vertex> vertices){
    org.jbox2d.util.nonconvex.Triangle[] tri = null;
    float[] xCoords = new float[vertices.size()];
    float[] yCoords = new float[vertices.size()];
   
    for (int i = 0; i < vertices.size(); i++) {
      xCoords[i] = vertices.get((vertices.size()-1)-i).x;
      yCoords[i] = vertices.get((vertices.size()-1)-i).y;
    }
    //tri = earClipper.triangulatePolygon(xCoords, yCoords, vertices.size());
   
    org.jbox2d.util.nonconvex.Triangle[] triangulated = new org.jbox2d.util.nonconvex.Triangle[vertices.size() - 2];
        for (int i=0; i<triangulated.length; ++i) {
          triangulated[i] = new org.jbox2d.util.nonconvex.Triangle();
        }
       
    Polygon.triangulatePolygon(xCoords, yCoords, vertices.size(), triangulated);
   
    //Try reversed order
    if (tri == null){
      System.err.println("Null! trying reversed!");
      for (int i = 0; i < vertices.size(); i++) {
        xCoords[i] = vertices.get(i).x;
        yCoords[i] = vertices.get(i).y;
      }
//      tri = earClipper.triangulatePolygon(xCoords, yCoords, vertices.size());
      Polygon.triangulatePolygon(xCoords, yCoords, vertices.size(), triangulated);
    }
    return tri;
  }
 
 
  public static List<Vertex> triangulateGLU(MTApplication app, List<Vertex> vertices){
    System.err.println("Trying glu triangulation..");
    GluTrianglulator triangulator = new GluTrianglulator(app);
    Vertex[] vertexArray = vertices.toArray(new Vertex[vertices.size()]);
    List<Vertex> triVerts = triangulator.tesselate(vertexArray, GLU.GLU_TESS_WINDING_NONZERO);
    return triVerts;
  }
 
 
  public static float scaleDown(float distance, float physicsScale){
    return distance /physicsScale;
  }
 
  public static float scaleUp(float distance, float physicsScale){
    return distance * physicsScale;
  }
 
  public static Vertex[] scaleDown(Vertex[] vertices, float physicsScale){
    return Vertex.scaleVectorArray(vertices, Vector3D.ZERO_VECTOR, 1f/physicsScale, 1f/physicsScale, 1);
  }
 
  public static Vertex[] scaleUp(Vertex[] vertices, float physicsScale){
    return Vertex.scaleVectorArray(vertices, Vector3D.ZERO_VECTOR, physicsScale, physicsScale, 1);
  }
 
  public static Vector3D[] scaleDown(Vector3D[] vertices, float physicsScale){
    return Vector3D.scaleVectorArray(vertices, Vector3D.ZERO_VECTOR, 1f/physicsScale, 1f/physicsScale, 1);
  }
 
  public static Vector3D[] scaleUp(Vector3D[] vertices, float physicsScale){
    return Vector3D.scaleVectorArray(vertices, Vector3D.ZERO_VECTOR, physicsScale, physicsScale, 1);
  }
 
  public static Vector3D scaleDown(Vector3D vec, float physicsScale){
    return vec.scaleLocal(1f/physicsScale);
  }
 
  public static Vector3D scaleUp(Vector3D vec, float physicsScale){
    return vec.scaleLocal(physicsScale);
  }
 
 
  public static GLMaterial createDefaultGLMaterial(PApplet app){
    //Set up a material
    GLMaterial material = new GLMaterial(Tools3D.getGL(app));
    material.setAmbient(new float[]{ .2f, .2f, .2f, 1f });
    material.setDiffuse(new float[]{ .8f, .8f, .8f, 1f } );
    material.setEmission(new float[]{ .0f, .0f, .0f, 1f });
    material.setSpecular(new float[]{ 1.0f, 1.0f, 1.0f, 1f })// almost white: very reflective
    material.setShininess(110);// 0=no shine,  127=max shine
    return material;
  }
 
 
 
 
  /**
   * Draw physics debug.
   */
  public static void drawDebugPhysics(PApplet app, World world, float scale){
    app.fill(180, 190);
    app.stroke(140, 190);
    app.strokeWeight(1);
    app.pushMatrix();
//    this.getSceneCam().update();
    app.scale(scale, scale);
    for (Body body = world.getBodyList(); body != null; body = body.getNext()) {
      Shape shape;
      for (shape = body.getShapeList(); shape != null; shape = shape.getNext()) {
        switch (shape.getType()) {
        case POLYGON_SHAPE:
          app.beginShape();
          PolygonShape poly = (PolygonShape)shape;
          int count = poly.getVertexCount();
          Vec2[] verts = poly.getVertices();
          for(int i = 0; i < count; i++) {
            Vec2 vert = body.getWorldLocation(verts[i]);
            app.vertex(vert.x , vert.y );
          }
          app.endShape();
          break;
        case EDGE_SHAPE:
          EdgeShape edge = (EdgeShape)shape;
          Vec2 v1 = body.getWorldLocation(edge.getVertex1());
          Vec2 v2 = body.getWorldLocation(edge.getVertex2());
         
          app.beginShape();
          app.vertex(v1.x , v1.y );
          app.vertex(v2.x , v2.y );
          app.endShape();
//          app.line(v1.x , v1.y ,v2.x , v2.y );
         
          /*
          EdgeShape next = edge;
          while (next.getNextEdge() != null){
            next = edge.getNextEdge();
            Vec2 v11 = body.getWorldLocation(next.getVertex1());
            Vec2 v22 = body.getWorldLocation(next.getVertex2());
           
            app.beginShape();
            app.vertex(v11.x , v11.y );
            app.vertex(v22.x , v22.y );
            app.endShape();
          }
          */
         
          break;
        case CIRCLE_SHAPE:
          CircleShape circle = (CircleShape)shape;
          float radius = circle.getRadius();
          Vec2 c = body.getWorldLocation(circle.getLocalPosition());
          app.ellipseMode(PApplet.CENTER);
          app.ellipse(c.x, c.y, radius+2, radius+2);
          break;
        default:
          break;
        }
      }
    }
    app.popMatrix();
  }
 
 
  public static void addScreenBoundaries(PApplet app, World world, MTComponent futureParent, float scale){
    // CREATE SCREEN BORDERS \\
    //Left border
    float borderWidth = 50f;
    float borderHeight = app.height;
    Vector3D pos = new Vector3D(-(borderWidth/2f) , app.height/2f);
    PhysicsRectangle borderLeft = new PhysicsRectangle(pos, borderWidth, borderHeight, app, world, 0,0,0, scale);
    borderLeft.setName("borderLeft");
    futureParent.addChild(borderLeft);
    //Right border
    pos = new Vector3D(app.width + (borderWidth/2), app.height/2);
    PhysicsRectangle borderRight = new PhysicsRectangle(pos, borderWidth, borderHeight, app, world, 0,0,0, scale);
    borderRight.setName("borderRight");
    futureParent.addChild(borderRight);
    //Top border
    borderWidth = app.width;
    borderHeight = 50f;
    pos = new Vector3D(app.width/2, -(borderHeight/2));
    PhysicsRectangle borderTop = new PhysicsRectangle(pos, borderWidth, borderHeight, app, world, 0,0,0, scale);
    borderTop.setName("borderTop");
    futureParent.addChild(borderTop);
    //Bottom border
    pos = new Vector3D(app.width/2 , app.height + (borderHeight/2));
    PhysicsRectangle borderBottom = new PhysicsRectangle(pos, borderWidth, borderHeight, app, world, 0,0,0, scale);
    borderBottom.setName("borderBottom");
    futureParent.addChild(borderBottom);
  }
 
 
  /**
   * Adds an edgeShape around the world with a slight offset so
   * that every shape hits the edge first before hitting the world boundaries.
   *
   * @param app the app
   * @param world the world
   * @param scale the scale
   *
   * @return the edge body
   */
  public static Body addWorldEdgeBoundaries(PApplet app, World world, float scale){
    AABB wAABB = world.getWorldAABB();
    Vec2 l = new Vec2(wAABB.lowerBound);
    Vec2 u = new Vec2(wAABB.upperBound);
   
    float worldWidth = u.x - l.x;
    float worldHeight = u.y - l.y;
   
    float offset = 1f; //kleiner als world machen
   
    BodyDef dymBodyDef = new BodyDef();
    dymBodyDef.position = new Vec2(0 , 0 );
//    dymBodyDef.position = new Vec2(worldWidth*0.5f , worldHeight*0.5f);
    Body theBody = world.createBody(dymBodyDef);

    EdgeChainDef myEdges = new EdgeChainDef();
    //CCW so edge points inwards
    myEdges.addVertex(new Vec2(l.x + offset , l.y + worldHeight - offset*2));
   
    myEdges.addVertex(new Vec2(l.x + worldWidth  - offset*2, l.y + worldHeight - offset*2));
   
    myEdges.addVertex(new Vec2(l.x + worldWidth - offset*2, l.y + offset));
   
    myEdges.addVertex(new Vec2(l.x + offset , l.y + offset));

    myEdges.setIsLoop(true);
    myEdges.friction = 2.0f;
//    myEdges.density = 1.0f;
    myEdges.density = 0.0f;
   
    myEdges.isSensor = true;

    theBody.createShape(myEdges);
    theBody.setMassFromShapes();
   
    return theBody;
  }
 
}
TOP

Related Classes of advanced.physics.util.PhysicsHelper

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.