Package com.bulletphysics.extras.gimpact

Source Code of com.bulletphysics.extras.gimpact.BoxCollision$AABB

/*
* Java port of Bullet (c) 2008 Martin Dvorak <jezek2@advel.cz>
*
* This source file is part of GIMPACT Library.
*
* For the latest info, see http://gimpact.sourceforge.net/
*
* Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
* email: projectileman@yahoo.com
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
*    claim that you wrote the original software. If you use this software
*    in a product, an acknowledgment in the product documentation would be
*    appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
*    misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/

package com.bulletphysics.extras.gimpact;

import com.bulletphysics.BulletGlobals;
import com.bulletphysics.linearmath.Transform;
import com.bulletphysics.linearmath.VectorUtil;
import cz.advel.stack.Stack;
import javax.vecmath.Matrix3f;
import javax.vecmath.Vector3f;
import javax.vecmath.Vector4f;

/**
*
* @author jezek2
*/
class BoxCollision {
 
  public static final float BOX_PLANE_EPSILON = 0.000001f;

  public static boolean BT_GREATER(float x, float y) {
    return Math.abs(x) > y;
  }

  public static float BT_MAX3(float a, float b, float c) {
    return Math.max(a, Math.max(b, c));
  }

  public static float BT_MIN3(float a, float b, float c) {
    return Math.min(a, Math.min(b, c));
  }
 
  public static boolean TEST_CROSS_EDGE_BOX_MCR(Vector3f edge, Vector3f absolute_edge, Vector3f pointa, Vector3f pointb, Vector3f _extend, int i_dir_0, int i_dir_1, int i_comp_0, int i_comp_1) {
    float dir0 = -VectorUtil.getCoord(edge, i_dir_0);
    float dir1 = VectorUtil.getCoord(edge, i_dir_1);
    float pmin = VectorUtil.getCoord(pointa, i_comp_0) * dir0 + VectorUtil.getCoord(pointa, i_comp_1) * dir1;
    float pmax = VectorUtil.getCoord(pointb, i_comp_0) * dir0 + VectorUtil.getCoord(pointb, i_comp_1) * dir1;
    if (pmin > pmax) {
      //BT_SWAP_NUMBERS(pmin,pmax);
      pmin = pmin + pmax;
      pmax = pmin - pmax;
      pmin = pmin - pmax;
    }
    float abs_dir0 = VectorUtil.getCoord(absolute_edge, i_dir_0);
    float abs_dir1 = VectorUtil.getCoord(absolute_edge, i_dir_1);
    float rad = VectorUtil.getCoord(_extend, i_comp_0) * abs_dir0 + VectorUtil.getCoord(_extend, i_comp_1) * abs_dir1;
    if (pmin > rad || -rad > pmax) {
      return false;
    }
    return true;
  }

  public static boolean TEST_CROSS_EDGE_BOX_X_AXIS_MCR(Vector3f edge, Vector3f absolute_edge, Vector3f pointa, Vector3f pointb, Vector3f _extend) {
    return TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 2, 1, 1, 2);
  }

  public static boolean TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(Vector3f edge, Vector3f absolute_edge, Vector3f pointa, Vector3f pointb, Vector3f _extend) {
    return TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 0, 2, 2, 0);
  }

  public static boolean TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(Vector3f edge, Vector3f absolute_edge, Vector3f pointa, Vector3f pointb, Vector3f _extend) {
    return TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 1, 0, 0, 1);
  }
 
  /**
   * Returns the dot product between a vec3f and the col of a matrix.
   */
  public static float bt_mat3_dot_col(Matrix3f mat, Vector3f vec3, int colindex) {
    return vec3.x*mat.getElement(0, colindex) + vec3.y*mat.getElement(1, colindex) + vec3.z*mat.getElement(2, colindex);
  }

  /**
   * Compairison of transformation objects.
   */
  public static boolean compareTransformsEqual(Transform t1, Transform t2) {
    return t1.equals(t2);
  }
 
  ////////////////////////////////////////////////////////////////////////////

  public static class BoxBoxTransformCache {
    public final Vector3f T1to0 = new Vector3f(); // Transforms translation of model1 to model 0
    public final Matrix3f R1to0 = new Matrix3f(); // Transforms Rotation of model1 to model 0, equal  to R0' * R1
    public final Matrix3f AR = new Matrix3f();    // Absolute value of m_R1to0
   
    public void set(BoxBoxTransformCache cache) {
      throw new UnsupportedOperationException();
    }
   
    public void calc_absolute_matrix() {
      //static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
      //m_AR[0] = vepsi + m_R1to0[0].absolute();
      //m_AR[1] = vepsi + m_R1to0[1].absolute();
      //m_AR[2] = vepsi + m_R1to0[2].absolute();

      for (int i=0; i<3; i++) {
        for (int j=0; j<3; j++) {
          AR.setElement(i, j, 1e-6f + Math.abs(R1to0.getElement(i, j)));
        }
      }
    }

    /**
     * Calc the transformation relative  1 to 0. Inverts matrics by transposing.
     */
    public void calc_from_homogenic(Transform trans0, Transform trans1) {
      Transform temp_trans = Stack.alloc(Transform.class);
      temp_trans.inverse(trans0);
      temp_trans.mul(trans1);

      T1to0.set(temp_trans.origin);
      R1to0.set(temp_trans.basis);

      calc_absolute_matrix();
    }
   
    /**
     * Calcs the full invertion of the matrices. Useful for scaling matrices.
     */
    public void calc_from_full_invert(Transform trans0, Transform trans1) {
      R1to0.invert(trans0.basis);
      T1to0.negate(trans0.origin);
      R1to0.transform(T1to0);

      Vector3f tmp = Stack.alloc(Vector3f.class);
      tmp.set(trans1.origin);
      R1to0.transform(tmp);
      T1to0.add(tmp);

      R1to0.mul(trans1.basis);

      calc_absolute_matrix();
    }
   
    public Vector3f transform(Vector3f point, Vector3f out) {
      if (point == out) {
        point = Stack.alloc(point);
      }
     
      Vector3f tmp = Stack.alloc(Vector3f.class);
      R1to0.getRow(0, tmp);
      out.x = tmp.dot(point) + T1to0.x;
      R1to0.getRow(1, tmp);
      out.y = tmp.dot(point) + T1to0.y;
      R1to0.getRow(2, tmp);
      out.z = tmp.dot(point) + T1to0.z;
      return out;
    }
  }
 
  ////////////////////////////////////////////////////////////////////////////
 
  public static class AABB {
    public final Vector3f min = new Vector3f();
    public final Vector3f max = new Vector3f();
   
    public AABB() {
    }

    public AABB(Vector3f V1, Vector3f V2, Vector3f V3) {
      calc_from_triangle(V1, V2, V3);
    }

    public AABB(Vector3f V1, Vector3f V2, Vector3f V3, float margin) {
      calc_from_triangle_margin(V1, V2, V3, margin);
    }

    public AABB(AABB other) {
      set(other);
    }

    public AABB(AABB other, float margin) {
      this(other);
      min.x -= margin;
      min.y -= margin;
      min.z -= margin;
      max.x += margin;
      max.y += margin;
      max.z += margin;
    }

    public void init(Vector3f V1, Vector3f V2, Vector3f V3, float margin) {
      calc_from_triangle_margin(V1, V2, V3, margin);
    }

    public void set(AABB other) {
      min.set(other.min);
      max.set(other.max);
    }

    public void invalidate() {
      min.set(BulletGlobals.SIMD_INFINITY, BulletGlobals.SIMD_INFINITY, BulletGlobals.SIMD_INFINITY);
      max.set(-BulletGlobals.SIMD_INFINITY, -BulletGlobals.SIMD_INFINITY, -BulletGlobals.SIMD_INFINITY);
    }

    public void increment_margin(float margin) {
      min.x -= margin;
      min.y -= margin;
      min.z -= margin;
      max.x += margin;
      max.y += margin;
      max.z += margin;
    }

    public void copy_with_margin(AABB other, float margin) {
      min.x = other.min.x - margin;
      min.y = other.min.y - margin;
      min.z = other.min.z - margin;

      max.x = other.max.x + margin;
      max.y = other.max.y + margin;
      max.z = other.max.z + margin;
    }
   
    public void calc_from_triangle(Vector3f V1, Vector3f V2, Vector3f V3) {
      min.x = BT_MIN3(V1.x, V2.x, V3.x);
      min.y = BT_MIN3(V1.y, V2.y, V3.y);
      min.z = BT_MIN3(V1.z, V2.z, V3.z);

      max.x = BT_MAX3(V1.x, V2.x, V3.x);
      max.y = BT_MAX3(V1.y, V2.y, V3.y);
      max.z = BT_MAX3(V1.z, V2.z, V3.z);
    }

    public void calc_from_triangle_margin(Vector3f V1, Vector3f V2, Vector3f V3, float margin) {
      calc_from_triangle(V1, V2, V3);
      min.x -= margin;
      min.y -= margin;
      min.z -= margin;
      max.x += margin;
      max.y += margin;
      max.z += margin;
    }
   
    /**
     * Apply a transform to an AABB.
     */
    public void appy_transform(Transform trans) {
      Vector3f tmp = Stack.alloc(Vector3f.class);

      Vector3f center = Stack.alloc(Vector3f.class);
      center.add(max, min);
      center.scale(0.5f);

      Vector3f extends_ = Stack.alloc(Vector3f.class);
      extends_.sub(max, center);

      // Compute new center
      trans.transform(center);

      Vector3f textends = Stack.alloc(Vector3f.class);

      trans.basis.getRow(0, tmp);
      tmp.absolute();
      textends.x = extends_.dot(tmp);

      trans.basis.getRow(1, tmp);
      tmp.absolute();
      textends.y = extends_.dot(tmp);

      trans.basis.getRow(2, tmp);
      tmp.absolute();
      textends.z = extends_.dot(tmp);

      min.sub(center, textends);
      max.add(center, textends);
    }

    /**
     * Apply a transform to an AABB.
     */
    public void appy_transform_trans_cache(BoxBoxTransformCache trans) {
      Vector3f tmp = Stack.alloc(Vector3f.class);

      Vector3f center = Stack.alloc(Vector3f.class);
      center.add(max, min);
      center.scale(0.5f);

      Vector3f extends_ = Stack.alloc(Vector3f.class);
      extends_.sub(max, center);

      // Compute new center
      trans.transform(center, center);

      Vector3f textends = Stack.alloc(Vector3f.class);

      trans.R1to0.getRow(0, tmp);
      tmp.absolute();
      textends.x = extends_.dot(tmp);

      trans.R1to0.getRow(1, tmp);
      tmp.absolute();
      textends.y = extends_.dot(tmp);

      trans.R1to0.getRow(2, tmp);
      tmp.absolute();
      textends.z = extends_.dot(tmp);

      min.sub(center, textends);
      max.add(center, textends);
    }
   
    /**
     * Merges a Box.
     */
    public void merge(AABB box) {
      min.x = Math.min(min.x, box.min.x);
      min.y = Math.min(min.y, box.min.y);
      min.z = Math.min(min.z, box.min.z);

      max.x = Math.max(max.x, box.max.x);
      max.y = Math.max(max.y, box.max.y);
      max.z = Math.max(max.z, box.max.z);
    }

    /**
     * Merges a point.
     */
    public void merge_point(Vector3f point) {
      min.x = Math.min(min.x, point.x);
      min.y = Math.min(min.y, point.y);
      min.z = Math.min(min.z, point.z);

      max.x = Math.max(max.x, point.x);
      max.y = Math.max(max.y, point.y);
      max.z = Math.max(max.z, point.z);
    }
   
    /**
     * Gets the extend and center.
     */
    public void get_center_extend(Vector3f center, Vector3f extend) {
      center.add(max, min);
      center.scale(0.5f);

      extend.sub(max, center);
    }
   
    /**
     * Finds the intersecting box between this box and the other.
     */
    public void find_intersection(AABB other, AABB intersection) {
      intersection.min.x = Math.max(other.min.x, min.x);
      intersection.min.y = Math.max(other.min.y, min.y);
      intersection.min.z = Math.max(other.min.z, min.z);

      intersection.max.x = Math.min(other.max.x, max.x);
      intersection.max.y = Math.min(other.max.y, max.y);
      intersection.max.z = Math.min(other.max.z, max.z);
    }

    public boolean has_collision(AABB other) {
      if (min.x > other.max.x ||
          max.x < other.min.x ||
          min.y > other.max.y ||
          max.y < other.min.y ||
          min.z > other.max.z ||
          max.z < other.min.z) {
        return false;
      }
      return true;
    }
   
    /**
     * Finds the Ray intersection parameter.
     *
     * @param aabb     aligned box
     * @param vorigin  a vec3f with the origin of the ray
     * @param vdir     a vec3f with the direction of the ray
     */
    public boolean collide_ray(Vector3f vorigin, Vector3f vdir) {
      Vector3f extents = Stack.alloc(Vector3f.class), center = Stack.alloc(Vector3f.class);
      get_center_extend(center, extents);

      float Dx = vorigin.x - center.x;
      if (BT_GREATER(Dx, extents.x) && Dx * vdir.x >= 0.0f) return false;
     
      float Dy = vorigin.y - center.y;
      if (BT_GREATER(Dy, extents.y) && Dy * vdir.y >= 0.0f) return false;
     
      float Dz = vorigin.z - center.z;
      if (BT_GREATER(Dz, extents.z) && Dz * vdir.z >= 0.0f) return false;
     
      float f = vdir.y * Dz - vdir.z * Dy;
      if (Math.abs(f) > extents.y * Math.abs(vdir.z) + extents.z * Math.abs(vdir.y)) return false;
     
      f = vdir.z * Dx - vdir.x * Dz;
      if (Math.abs(f) > extents.x * Math.abs(vdir.z) + extents.z * Math.abs(vdir.x)) return false;
     
      f = vdir.x * Dy - vdir.y * Dx;
      if (Math.abs(f) > extents.x * Math.abs(vdir.y) + extents.y * Math.abs(vdir.x)) return false;
     
      return true;
    }
 
    public void projection_interval(Vector3f direction, float[] vmin, float[] vmax) {
      Vector3f tmp = Stack.alloc(Vector3f.class);

      Vector3f center = Stack.alloc(Vector3f.class);
      Vector3f extend = Stack.alloc(Vector3f.class);
      get_center_extend(center, extend);

      float _fOrigin = direction.dot(center);
      tmp.absolute(direction);
      float _fMaximumExtent = extend.dot(tmp);
      vmin[0] = _fOrigin - _fMaximumExtent;
      vmax[0] = _fOrigin + _fMaximumExtent;
    }

    public PlaneIntersectionType plane_classify(Vector4f plane) {
      Vector3f tmp = Stack.alloc(Vector3f.class);

      float[] _fmin = new float[1], _fmax = new float[1];
      tmp.set(plane.x, plane.y, plane.z);
      projection_interval(tmp, _fmin, _fmax);

      if (plane.w > _fmax[0] + BOX_PLANE_EPSILON) {
        return PlaneIntersectionType.BACK_PLANE; // 0
      }

      if (plane.w + BOX_PLANE_EPSILON >= _fmin[0]) {
        return PlaneIntersectionType.COLLIDE_PLANE; //1
      }
     
      return PlaneIntersectionType.FRONT_PLANE; //2
    }
   
    public boolean overlapping_trans_conservative(AABB box, Transform trans1_to_0) {
      AABB tbox = Stack.alloc(box);
      tbox.appy_transform(trans1_to_0);
      return has_collision(tbox);
    }

    public boolean overlapping_trans_conservative2(AABB box, BoxBoxTransformCache trans1_to_0) {
      AABB tbox = Stack.alloc(box);
      tbox.appy_transform_trans_cache(trans1_to_0);
      return has_collision(tbox);
    }

    /**
     * transcache is the transformation cache from box to this AABB.
     */
    public boolean overlapping_trans_cache(AABB box, BoxBoxTransformCache transcache, boolean fulltest) {
      Vector3f tmp = Stack.alloc(Vector3f.class);

      // Taken from OPCODE
      Vector3f ea = Stack.alloc(Vector3f.class), eb = Stack.alloc(Vector3f.class); //extends
      Vector3f ca = Stack.alloc(Vector3f.class), cb = Stack.alloc(Vector3f.class); //extends
      get_center_extend(ca, ea);
      box.get_center_extend(cb, eb);

      Vector3f T = Stack.alloc(Vector3f.class);
      float t, t2;

      // Class I : A's basis vectors
      for (int i=0; i<3; i++) {
        transcache.R1to0.getRow(i, tmp);
        VectorUtil.setCoord(T, i, tmp.dot(cb) + VectorUtil.getCoord(transcache.T1to0, i) - VectorUtil.getCoord(ca, i));

        transcache.AR.getRow(i, tmp);
        t = tmp.dot(eb) + VectorUtil.getCoord(ea, i);
        if (BT_GREATER(VectorUtil.getCoord(T, i), t)) {
          return false;
        }
      }
      // Class II : B's basis vectors
      for (int i=0; i<3; i++) {
        t = bt_mat3_dot_col(transcache.R1to0, T, i);
        t2 = bt_mat3_dot_col(transcache.AR, ea, i) + VectorUtil.getCoord(eb, i);
        if (BT_GREATER(t, t2)) {
          return false;
        }
      }
      // Class III : 9 cross products
      if (fulltest) {
        int m, n, o, p, q, r;
        for (int i = 0; i < 3; i++) {
          m = (i+1) % 3;
          n = (i+2) % 3;
          o = (i == 0)? 1:0;
          p = (i == 2)? 1:2;
          for (int j=0; j<3; j++) {
            q = j == 2 ? 1 : 2;
            r = j == 0 ? 1 : 0;
            t = VectorUtil.getCoord(T, n) * transcache.R1to0.getElement(m, j) - VectorUtil.getCoord(T, m) * transcache.R1to0.getElement(n, j);
            t2 = VectorUtil.getCoord(ea, o) * transcache.AR.getElement(p, j) + VectorUtil.getCoord(ea, p) * transcache.AR.getElement(o, j) +
                VectorUtil.getCoord(eb, r) * transcache.AR.getElement(i, q) + VectorUtil.getCoord(eb, q) * transcache.AR.getElement(i, r);
            if (BT_GREATER(t, t2)) {
              return false;
            }
          }
        }
      }
      return true;
    }
   
    /**
     * Simple test for planes.
     */
    public boolean collide_plane(Vector4f plane) {
      PlaneIntersectionType classify = plane_classify(plane);
      return (classify == PlaneIntersectionType.COLLIDE_PLANE);
    }
   
    /**
     * Test for a triangle, with edges.
     */
    public boolean collide_triangle_exact(Vector3f p1, Vector3f p2, Vector3f p3, Vector4f triangle_plane) {
      if (!collide_plane(triangle_plane)) {
        return false;
      }
      Vector3f center = Stack.alloc(Vector3f.class), extends_ = Stack.alloc(Vector3f.class);
      get_center_extend(center, extends_);

      Vector3f v1 = Stack.alloc(Vector3f.class);
      v1.sub(p1, center);
      Vector3f v2 = Stack.alloc(Vector3f.class);
      v2.sub(p2, center);
      Vector3f v3 = Stack.alloc(Vector3f.class);
      v3.sub(p3, center);

      // First axis
      Vector3f diff = Stack.alloc(Vector3f.class);
      diff.sub(v2, v1);
      Vector3f abs_diff = Stack.alloc(Vector3f.class);
      abs_diff.absolute(diff);

      // Test With X axis
      TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v1, v3, extends_);
      // Test With Y axis
      TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v1, v3, extends_);
      // Test With Z axis
      TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v1, v3, extends_);

      diff.sub(v3, v2);
      abs_diff.absolute(diff);

      // Test With X axis
      TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v2, v1, extends_);
      // Test With Y axis
      TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v2, v1, extends_);
      // Test With Z axis
      TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v2, v1, extends_);

      diff.sub(v1, v3);
      abs_diff.absolute(diff);

      // Test With X axis
      TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v3, v2, extends_);
      // Test With Y axis
      TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v3, v2, extends_);
      // Test With Z axis
      TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v3, v2, extends_);

      return true;
    }
  }
 
}
TOP

Related Classes of com.bulletphysics.extras.gimpact.BoxCollision$AABB

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.