Package game.util

Source Code of game.util.Physics

package game.util;

import math.Matrix;
import math.Vector;

public class Physics {

  private static final double G = 7e-7f; // real world: 6.67384e-11f;
  private static double SPHERE_VOLUME_FACTOR = (double) (4f / 3f * Math.PI);
  public static final Matrix DEFAULT_TENSOR = Physics
      .getSphereInertialTensor(1, 1);

  /**
   * Translates an object defined by its position, velocity and mass, using a
   * translational force and a passing time interval to calculate the
   * afterwards position and velocity.
   */
  public static void translateObjectEuler(Vector pos, Vector v, double m,
      Vector force, double timeDelta) {
    // a*t = (F/m)*t
    // pos = 0.5at� + vt + pos_0
    // v = at + v_0
    Vector at = force.clone().scale(timeDelta / m);
    pos.add(at.clone().scale(0.5f).add(v).scale(timeDelta));
    v.add(at);
  }
 
  /**
   * Translates an object defined by its position, velocity and mass, using a
   * translational force and a passing time interval to calculate the
   * afterwards position and velocity.
   * This method uses the two-step Leapfrog method instead of the instable Euler method.
   */
  public static Vector translateObject(Vector pos, Vector v, double m,
      Vector force, double timeDelta, Vector oldAcc) {   
    Vector acc = force.clone().scale(1 / m)
    v.add(oldAcc.add(acc).scale(0.5f * timeDelta));
    pos.add(acc.clone().scale(0.5f * timeDelta).add(v).scale(timeDelta));
    return oldAcc = acc;
  }

  /**
   * Rotates an object defined by its direction, rotation and momentum of
   * inertia, using a rotational momentum and a passing time interval to
   * calculate the afterwards direction and rotation.
   */
  public static void rotateObject(Matrix dir, Vector rot, double inertia,
      Vector momentum, double timeDelta) {
    // angular acceleration = M / J (like in F = m*a)
    Vector rotAt = momentum.clone().scale(
        (inertia < 0.0005f) ? 0 : (timeDelta / inertia));
    Vector deltaDir = rotAt.clone().scale(0.5f).add(rot).scale(timeDelta);
    dir.set(Matrix.mult(dir, Matrix.getRotationalMatrix(deltaDir)));
    rot.add(rotAt);
  }
 
  public static void applyTranslationalImpulse(Vector vel, double m, Vector impulse, Vector forceArm) {
    if (forceArm == null) {
      vel.add(impulse.scale(1 / m));
      return;
   
    vel.add(Physics.getTranslationalForce(impulse, forceArm).scale(1 / m));
  }
 
  public static void applyRotationalImpulse(Vector rot, Matrix tensor, Vector impulse, Vector forceArm) {
    if (forceArm != null) {
      Vector rotImpulse = Physics.getRotationalMomentum(impulse, forceArm);
      double inertia = Physics.getMomentumOfInertia(tensor, rotImpulse);
      rot.add(rotImpulse.scale((inertia < 0.0005f) ? 0 : 1 / inertia));
    }     
  }

  /**
   * Calculates the specific momentum of inertia for a given axis from the
   * general momentum of inertia tensor.
   */
  public static double getMomentumOfInertia(Matrix tensor, Vector axis) {
    // J = n^T * (I * n); (n: normalized rotation axis, I: inertial momentum
    // tensor)
    double len = axis.getLength();
    axis = axis.clone().scale(1 / len);
    return (len < 0.005f) ? 0 : Vector.applyMatrix(tensor, axis).dot(axis);
  }

  /**
   * Calculates the part of the given force that is parallel to the given
   * lever and thus inducing a translation.
   */
  public static Vector getTranslationalForce(Vector totalForce, Vector forceArm) {
    return (forceArm.isZero()) ? totalForce
      : forceArm.clone().scale(totalForce.dot(forceArm) / forceArm.dot(forceArm));
  }

  /**
   * Calculates the rotational momentum induced by the given force. If the
   * force arm has length zero, no rotational momentum is induced.
   */
  public static Vector getRotationalMomentum(Vector totalForce, Vector forceArm) {
    return (forceArm.isZero()) ? new Vector(0, 0, 0)
      : Vector.cross(forceArm, totalForce);
  }

  /**
   * Returns the momentum of inertia tensor corresponding to a homgenuously
   * filled sphere of the given radius and mass.
   */
  public static Matrix getSphereInertialTensor(double m, double r) {
    double momentum = 0.4f * m * r * r;
    return new Matrix(new double[][] { { momentum, 0, 0 },
        { 0, momentum, 0 }, { 0, 0, momentum } });
  }

  public static double getSphereVolume(double r) {
    return SPHERE_VOLUME_FACTOR * r * r * r;
  }

  public static Vector getGForce(double m1, double m2, Vector pos1, Vector pos2) {
    Vector dir = pos1.clone().invert().add(pos2);
    double r = dir.getLength();
    return (r < 0.0005f) ? dir.reset()
      : dir.scale(G * m1 * m2 / (r * r * r));
  }
 
  /**
   * Simulates a collision between two objects. As result of the simulation,
   * the given linear and angular velocities (v1, v2, rot1, rot2) of the bodies
   * are modified.
   * @param e coefficient of restitution (0 for plastic, 1 for elastic)
   * @param n mesh surface normal at the point of collision
   * @param m1 mass of object 1
   * @param m2 mass of object 2
   * @param tensor1 tensor of inertia of object 1
   * @param tensor2 tensor of inertia of object 2
   * @param arm1 point of collision relative to the center of mass of object 1
   * @param arm2 point of collision relative to the center of mass of object 2
   */
  public static void resolveCollision(double e, Vector n, double m1, double m2, Matrix tensor1,
      Matrix tensor2, Vector arm1, Vector arm2, Vector v1, Vector v2, Vector rot1, Vector rot2) {
    // see http://www.euclideanspace.com/physics/dynamics/collision/threed/index.htm
    Vector dRot1 = Vector.applyMatrix(tensor1.clone().invert(), Vector.cross(n, arm1));
    Vector dRot2 = Vector.applyMatrix(tensor2.clone().invert(), Vector.cross(n, arm2));
    double impulse = (e + 1) * Vector.getDistance(v1, v2) / (1 / m1 + 1 / m2 
        + Vector.cross(dRot1, arm1).dot(n) + Vector.cross(dRot2, arm2).dot(n));
    v1.add(n.clone().scale(- impulse / m1));
    v2.add(n.clone().scale(impulse / m2));
    rot1.add(dRot1.invert());
    rot2.add(dRot2.invert());
  }
}
TOP

Related Classes of game.util.Physics

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.