/* 
 | 
 * Java port of Bullet (c) 2008 Martin Dvorak <jezek2@advel.cz> 
 | 
 * 
 | 
 * Bullet Continuous Collision Detection and Physics Library 
 | 
 * Copyright (c) 2003-2008 Erwin Coumans  http://www.bulletphysics.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. 
 | 
 */ 
 | 
  
 | 
// Dbvt implementation by Nathanael Presson 
 | 
  
 | 
package com.bulletphysics.collision.broadphase; 
 | 
  
 | 
import com.bulletphysics.linearmath.MatrixUtil; 
 | 
import com.bulletphysics.linearmath.Transform; 
 | 
import com.bulletphysics.linearmath.VectorUtil; 
 | 
import cz.advel.stack.Stack; 
 | 
import javax.vecmath.Vector3f; 
 | 
  
 | 
/** 
 | 
 * 
 | 
 * @author jezek2 
 | 
 */ 
 | 
public class DbvtAabbMm  implements java.io.Serializable { 
 | 
  
 | 
    private final Vector3f mi = new Vector3f(); 
 | 
    private final Vector3f mx = new Vector3f(); 
 | 
  
 | 
    public DbvtAabbMm() { 
 | 
    } 
 | 
  
 | 
    public DbvtAabbMm(DbvtAabbMm o) { 
 | 
        set(o); 
 | 
    } 
 | 
     
 | 
    public void set(DbvtAabbMm o) { 
 | 
        mi.set(o.mi); 
 | 
        mx.set(o.mx); 
 | 
    } 
 | 
     
 | 
    public static void swap(DbvtAabbMm p1, DbvtAabbMm p2) { 
 | 
        Vector3f tmp = Stack.alloc(Vector3f.class); 
 | 
         
 | 
        tmp.set(p1.mi); 
 | 
        p1.mi.set(p2.mi); 
 | 
        p2.mi.set(tmp); 
 | 
  
 | 
        tmp.set(p1.mx); 
 | 
        p1.mx.set(p2.mx); 
 | 
        p2.mx.set(tmp); 
 | 
    } 
 | 
  
 | 
    public Vector3f Center(Vector3f out) { 
 | 
        out.add(mi, mx); 
 | 
        out.scale(0.5f); 
 | 
        return out; 
 | 
    } 
 | 
     
 | 
    public Vector3f Lengths(Vector3f out) { 
 | 
        out.sub(mx, mi); 
 | 
        return out; 
 | 
    } 
 | 
     
 | 
    public Vector3f Extents(Vector3f out) { 
 | 
        out.sub(mx, mi); 
 | 
        out.scale(0.5f); 
 | 
        return out; 
 | 
    } 
 | 
     
 | 
    public Vector3f Mins() { 
 | 
        return mi; 
 | 
    } 
 | 
  
 | 
    public Vector3f Maxs() { 
 | 
        return mx; 
 | 
    } 
 | 
     
 | 
    public static DbvtAabbMm FromCE(Vector3f c, Vector3f e, DbvtAabbMm out) { 
 | 
        DbvtAabbMm box = out; 
 | 
        box.mi.sub(c, e); 
 | 
        box.mx.add(c, e); 
 | 
        return box; 
 | 
    } 
 | 
  
 | 
    public static DbvtAabbMm FromCR(Vector3f c, float r, DbvtAabbMm out) { 
 | 
        Vector3f tmp = Stack.alloc(Vector3f.class); 
 | 
        tmp.set(r, r, r); 
 | 
        return FromCE(c, tmp, out); 
 | 
    } 
 | 
  
 | 
    public static DbvtAabbMm FromMM(Vector3f mi, Vector3f mx, DbvtAabbMm out) { 
 | 
        DbvtAabbMm box = out; 
 | 
        box.mi.set(mi); 
 | 
        box.mx.set(mx); 
 | 
        return box; 
 | 
    } 
 | 
     
 | 
    //public static  DbvtAabbMm    FromPoints( btVector3* pts,int n); 
 | 
    //public static  DbvtAabbMm    FromPoints( btVector3** ppts,int n); 
 | 
     
 | 
    public void Expand(Vector3f e) { 
 | 
        mi.sub(e); 
 | 
        mx.add(e); 
 | 
    } 
 | 
  
 | 
    public void SignedExpand(Vector3f e) { 
 | 
        if (e.x > 0) { 
 | 
            mx.x += e.x; 
 | 
        } 
 | 
        else { 
 | 
            mi.x += e.x; 
 | 
        } 
 | 
         
 | 
        if (e.y > 0) { 
 | 
            mx.y += e.y; 
 | 
        } 
 | 
        else { 
 | 
            mi.y += e.y; 
 | 
        } 
 | 
         
 | 
        if (e.z > 0) { 
 | 
            mx.z += e.z; 
 | 
        } 
 | 
        else { 
 | 
            mi.z += e.z; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    public boolean Contain(DbvtAabbMm a) { 
 | 
        return ((mi.x <= a.mi.x) && 
 | 
                (mi.y <= a.mi.y) && 
 | 
                (mi.z <= a.mi.z) && 
 | 
                (mx.x >= a.mx.x) && 
 | 
                (mx.y >= a.mx.y) && 
 | 
                (mx.z >= a.mx.z)); 
 | 
    } 
 | 
  
 | 
    public int Classify(Vector3f n, float o, int s) { 
 | 
        Vector3f pi = Stack.alloc(Vector3f.class); 
 | 
        Vector3f px = Stack.alloc(Vector3f.class); 
 | 
  
 | 
        switch (s) { 
 | 
            case (0 + 0 + 0): 
 | 
                px.set(mi.x, mi.y, mi.z); 
 | 
                pi.set(mx.x, mx.y, mx.z); 
 | 
                break; 
 | 
            case (1 + 0 + 0): 
 | 
                px.set(mx.x, mi.y, mi.z); 
 | 
                pi.set(mi.x, mx.y, mx.z); 
 | 
                break; 
 | 
            case (0 + 2 + 0): 
 | 
                px.set(mi.x, mx.y, mi.z); 
 | 
                pi.set(mx.x, mi.y, mx.z); 
 | 
                break; 
 | 
            case (1 + 2 + 0): 
 | 
                px.set(mx.x, mx.y, mi.z); 
 | 
                pi.set(mi.x, mi.y, mx.z); 
 | 
                break; 
 | 
            case (0 + 0 + 4): 
 | 
                px.set(mi.x, mi.y, mx.z); 
 | 
                pi.set(mx.x, mx.y, mi.z); 
 | 
                break; 
 | 
            case (1 + 0 + 4): 
 | 
                px.set(mx.x, mi.y, mx.z); 
 | 
                pi.set(mi.x, mx.y, mi.z); 
 | 
                break; 
 | 
            case (0 + 2 + 4): 
 | 
                px.set(mi.x, mx.y, mx.z); 
 | 
                pi.set(mx.x, mi.y, mi.z); 
 | 
                break; 
 | 
            case (1 + 2 + 4): 
 | 
                px.set(mx.x, mx.y, mx.z); 
 | 
                pi.set(mi.x, mi.y, mi.z); 
 | 
                break; 
 | 
        } 
 | 
         
 | 
        if ((n.dot(px) + o) < 0) { 
 | 
            return -1; 
 | 
        } 
 | 
        if ((n.dot(pi) + o) >= 0) { 
 | 
            return +1; 
 | 
        } 
 | 
        return 0; 
 | 
    } 
 | 
  
 | 
    public float ProjectMinimum(Vector3f v, int signs) { 
 | 
        Vector3f[] b = new Vector3f[] { mx, mi }; 
 | 
        Vector3f p = Stack.alloc(Vector3f.class); 
 | 
        p.set(b[(signs >> 0) & 1].x, 
 | 
              b[(signs >> 1) & 1].y, 
 | 
              b[(signs >> 2) & 1].z); 
 | 
        return p.dot(v); 
 | 
    } 
 | 
      
 | 
    public static boolean Intersect(DbvtAabbMm a, DbvtAabbMm b) { 
 | 
        return ((a.mi.x <= b.mx.x) && 
 | 
                (a.mx.x >= b.mi.x) && 
 | 
                (a.mi.y <= b.mx.y) && 
 | 
                (a.mx.y >= b.mi.y) && 
 | 
                (a.mi.z <= b.mx.z) && 
 | 
                (a.mx.z >= b.mi.z)); 
 | 
    } 
 | 
  
 | 
    public static boolean Intersect(DbvtAabbMm a, DbvtAabbMm b, Transform xform) { 
 | 
        Vector3f d0 = Stack.alloc(Vector3f.class); 
 | 
        Vector3f d1 = Stack.alloc(Vector3f.class); 
 | 
        Vector3f tmp = Stack.alloc(Vector3f.class); 
 | 
  
 | 
        // JAVA NOTE: check 
 | 
        b.Center(d0); 
 | 
        xform.transform(d0); 
 | 
        d0.sub(a.Center(tmp)); 
 | 
  
 | 
        MatrixUtil.transposeTransform(d1, d0, xform.basis); 
 | 
  
 | 
        float[] s0 = new float[] { 0, 0 }; 
 | 
        float[] s1 = new float[2]; 
 | 
        s1[0] = xform.origin.dot(d0); 
 | 
        s1[1] = s1[0]; 
 | 
  
 | 
        a.AddSpan(d0, s0, 0, s0, 1); 
 | 
        b.AddSpan(d1, s1, 0, s1, 1); 
 | 
        if (s0[0] > (s1[1])) { 
 | 
            return false; 
 | 
        } 
 | 
        if (s0[1] < (s1[0])) { 
 | 
            return false; 
 | 
        } 
 | 
        return true; 
 | 
    } 
 | 
  
 | 
    public static boolean Intersect(DbvtAabbMm a, Vector3f b) { 
 | 
        return ((b.x >= a.mi.x) && 
 | 
                (b.y >= a.mi.y) && 
 | 
                (b.z >= a.mi.z) && 
 | 
                (b.x <= a.mx.x) && 
 | 
                (b.y <= a.mx.y) && 
 | 
                (b.z <= a.mx.z)); 
 | 
    } 
 | 
  
 | 
    public static boolean Intersect(DbvtAabbMm a, Vector3f org, Vector3f invdir, int[] signs) { 
 | 
        Vector3f[] bounds = new Vector3f[]{a.mi, a.mx}; 
 | 
        float txmin = (bounds[signs[0]].x - org.x) * invdir.x; 
 | 
        float txmax = (bounds[1 - signs[0]].x - org.x) * invdir.x; 
 | 
        float tymin = (bounds[signs[1]].y - org.y) * invdir.y; 
 | 
        float tymax = (bounds[1 - signs[1]].y - org.y) * invdir.y; 
 | 
        if ((txmin > tymax) || (tymin > txmax)) { 
 | 
            return false; 
 | 
        } 
 | 
         
 | 
        if (tymin > txmin) { 
 | 
            txmin = tymin; 
 | 
        } 
 | 
        if (tymax < txmax) { 
 | 
            txmax = tymax; 
 | 
        } 
 | 
        float tzmin = (bounds[signs[2]].z - org.z) * invdir.z; 
 | 
        float tzmax = (bounds[1 - signs[2]].z - org.z) * invdir.z; 
 | 
        if ((txmin > tzmax) || (tzmin > txmax)) { 
 | 
            return false; 
 | 
        } 
 | 
         
 | 
        if (tzmin > txmin) { 
 | 
            txmin = tzmin; 
 | 
        } 
 | 
        if (tzmax < txmax) { 
 | 
            txmax = tzmax; 
 | 
        } 
 | 
        return (txmax > 0); 
 | 
    } 
 | 
  
 | 
    public static float Proximity(DbvtAabbMm a, DbvtAabbMm b) { 
 | 
        Vector3f d = Stack.alloc(Vector3f.class); 
 | 
        Vector3f tmp = Stack.alloc(Vector3f.class); 
 | 
  
 | 
        d.add(a.mi, a.mx); 
 | 
        tmp.add(b.mi, b.mx); 
 | 
        d.sub(tmp); 
 | 
        return Math.abs(d.x) + Math.abs(d.y) + Math.abs(d.z); 
 | 
    } 
 | 
  
 | 
    public static void Merge(DbvtAabbMm a, DbvtAabbMm b, DbvtAabbMm r) { 
 | 
        for (int i=0; i<3; i++) { 
 | 
            if (VectorUtil.getCoord(a.mi, i) < VectorUtil.getCoord(b.mi, i)) { 
 | 
                VectorUtil.setCoord(r.mi, i, VectorUtil.getCoord(a.mi, i)); 
 | 
            } 
 | 
            else { 
 | 
                VectorUtil.setCoord(r.mi, i, VectorUtil.getCoord(b.mi, i)); 
 | 
            } 
 | 
             
 | 
            if (VectorUtil.getCoord(a.mx, i) > VectorUtil.getCoord(b.mx, i)) { 
 | 
                VectorUtil.setCoord(r.mx, i, VectorUtil.getCoord(a.mx, i)); 
 | 
            } 
 | 
            else { 
 | 
                VectorUtil.setCoord(r.mx, i, VectorUtil.getCoord(b.mx, i)); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    public static boolean NotEqual(DbvtAabbMm a, DbvtAabbMm b) { 
 | 
        return ((a.mi.x != b.mi.x) || 
 | 
                (a.mi.y != b.mi.y) || 
 | 
                (a.mi.z != b.mi.z) || 
 | 
                (a.mx.x != b.mx.x) || 
 | 
                (a.mx.y != b.mx.y) || 
 | 
                (a.mx.z != b.mx.z)); 
 | 
    } 
 | 
     
 | 
    private void AddSpan(Vector3f d, float[] smi, int smi_idx, float[] smx, int smx_idx) { 
 | 
        for (int i=0; i<3; i++) { 
 | 
            if (VectorUtil.getCoord(d, i) < 0) { 
 | 
                smi[smi_idx] += VectorUtil.getCoord(mx, i) * VectorUtil.getCoord(d, i); 
 | 
                smx[smx_idx] += VectorUtil.getCoord(mi, i) * VectorUtil.getCoord(d, i); 
 | 
            } 
 | 
            else { 
 | 
                smi[smi_idx] += VectorUtil.getCoord(mi, i) * VectorUtil.getCoord(d, i); 
 | 
                smx[smx_idx] += VectorUtil.getCoord(mx, i) * VectorUtil.getCoord(d, i); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
     
 | 
} 
 |