/* 
 | 
 * 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. 
 | 
 */ 
 | 
  
 | 
package com.bulletphysics.collision.shapes; 
 | 
  
 | 
import com.bulletphysics.linearmath.AabbUtil2; 
 | 
import com.bulletphysics.linearmath.Transform; 
 | 
import com.bulletphysics.linearmath.VectorUtil; 
 | 
import cz.advel.stack.Stack; 
 | 
import javax.vecmath.Vector3f; 
 | 
  
 | 
/** 
 | 
 * PolyhedralConvexShape is an internal interface class for polyhedral convex shapes. 
 | 
 *  
 | 
 * @author jezek2 
 | 
 */ 
 | 
public abstract class PolyhedralConvexShape extends ConvexInternalShape { 
 | 
  
 | 
    private static Vector3f[] _directions = new Vector3f[] { 
 | 
        new Vector3f( 1f,  0f,  0f), 
 | 
        new Vector3f( 0f,  1f,  0f), 
 | 
        new Vector3f( 0f,  0f,  1f), 
 | 
        new Vector3f(-1f,  0f,  0f), 
 | 
        new Vector3f( 0f, -1f,  0f), 
 | 
        new Vector3f( 0f,  0f, -1f) 
 | 
    }; 
 | 
  
 | 
    private static Vector3f[] _supporting = new Vector3f[] { 
 | 
        new Vector3f(0f, 0f, 0f), 
 | 
        new Vector3f(0f, 0f, 0f), 
 | 
        new Vector3f(0f, 0f, 0f), 
 | 
        new Vector3f(0f, 0f, 0f), 
 | 
        new Vector3f(0f, 0f, 0f), 
 | 
        new Vector3f(0f, 0f, 0f) 
 | 
    }; 
 | 
     
 | 
    protected final Vector3f localAabbMin = new Vector3f(1f, 1f, 1f); 
 | 
    protected final Vector3f localAabbMax = new Vector3f(-1f, -1f, -1f); 
 | 
    protected boolean isLocalAabbValid = false; 
 | 
  
 | 
//    /** optional Hull is for optional Separating Axis Test Hull collision detection, see Hull.cpp */ 
 | 
//    public Hull optionalHull = null; 
 | 
     
 | 
    @Override 
 | 
    public Vector3f localGetSupportingVertexWithoutMargin(Vector3f vec0, Vector3f out) { 
 | 
        int i; 
 | 
        Vector3f supVec = out; 
 | 
        supVec.set(0f, 0f, 0f); 
 | 
  
 | 
        float maxDot = -1e30f; 
 | 
  
 | 
        Vector3f vec = (Vector3f) Stack.alloc(vec0); 
 | 
        float lenSqr = vec.lengthSquared(); 
 | 
        if (lenSqr < 0.0001f) { 
 | 
            vec.set(1f, 0f, 0f); 
 | 
        } 
 | 
        else { 
 | 
            float rlen = 1f / (float) Math.sqrt(lenSqr); 
 | 
            vec.scale(rlen); 
 | 
        } 
 | 
  
 | 
        Vector3f vtx = Stack.alloc(Vector3f.class); 
 | 
        float newDot; 
 | 
  
 | 
        for (i = 0; i < getNumVertices(); i++) { 
 | 
            getVertex(i, vtx); 
 | 
            newDot = vec.dot(vtx); 
 | 
            if (newDot > maxDot) { 
 | 
                maxDot = newDot; 
 | 
                supVec = vtx; 
 | 
            } 
 | 
        } 
 | 
  
 | 
        return out; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public void batchedUnitVectorGetSupportingVertexWithoutMargin(Vector3f[] vectors, Vector3f[] supportVerticesOut, int numVectors) { 
 | 
        int i; 
 | 
  
 | 
        Vector3f vtx = Stack.alloc(Vector3f.class); 
 | 
        float newDot; 
 | 
  
 | 
        // JAVA NOTE: rewritten as code used W coord for temporary usage in Vector3 
 | 
        // TODO: optimize it 
 | 
        float[] wcoords = new float[numVectors]; 
 | 
  
 | 
        for (i = 0; i < numVectors; i++) { 
 | 
            // TODO: used w in vector3: 
 | 
            //supportVerticesOut[i].w = -1e30f; 
 | 
            wcoords[i] = -1e30f; 
 | 
        } 
 | 
  
 | 
        for (int j = 0; j < numVectors; j++) { 
 | 
            Vector3f vec = vectors[j]; 
 | 
  
 | 
            for (i = 0; i < getNumVertices(); i++) { 
 | 
                getVertex(i, vtx); 
 | 
                newDot = vec.dot(vtx); 
 | 
                //if (newDot > supportVerticesOut[j].w) 
 | 
                if (newDot > wcoords[j]) { 
 | 
                    //WARNING: don't swap next lines, the w component would get overwritten! 
 | 
                    supportVerticesOut[j].set(vtx); 
 | 
                    //supportVerticesOut[j].w = newDot; 
 | 
                    wcoords[j] = newDot; 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public void calculateLocalInertia(float mass, Vector3f inertia) { 
 | 
        // not yet, return box inertia 
 | 
  
 | 
        float margin = getMargin(); 
 | 
  
 | 
        Transform ident = Stack.alloc(Transform.class); 
 | 
        ident.setIdentity(); 
 | 
        Vector3f aabbMin = Stack.alloc(Vector3f.class), aabbMax = Stack.alloc(Vector3f.class); 
 | 
        getAabb(ident, aabbMin, aabbMax); 
 | 
  
 | 
        Vector3f halfExtents = Stack.alloc(Vector3f.class); 
 | 
        halfExtents.sub(aabbMax, aabbMin); 
 | 
        halfExtents.scale(0.5f); 
 | 
  
 | 
        float lx = 2f * (halfExtents.x + margin); 
 | 
        float ly = 2f * (halfExtents.y + margin); 
 | 
        float lz = 2f * (halfExtents.z + margin); 
 | 
        float x2 = lx * lx; 
 | 
        float y2 = ly * ly; 
 | 
        float z2 = lz * lz; 
 | 
        float scaledmass = mass * 0.08333333f; 
 | 
  
 | 
        inertia.set(y2 + z2, x2 + z2, x2 + y2); 
 | 
        inertia.scale(scaledmass); 
 | 
    } 
 | 
  
 | 
    private void getNonvirtualAabb(Transform trans, Vector3f aabbMin, Vector3f aabbMax, float margin) { 
 | 
        // lazy evaluation of local aabb 
 | 
        assert (isLocalAabbValid); 
 | 
  
 | 
        AabbUtil2.transformAabb(localAabbMin, localAabbMax, margin, trans, aabbMin, aabbMax); 
 | 
    } 
 | 
     
 | 
    @Override 
 | 
    public void getAabb(Transform trans, Vector3f aabbMin, Vector3f aabbMax) { 
 | 
        getNonvirtualAabb(trans, aabbMin, aabbMax, getMargin()); 
 | 
    } 
 | 
  
 | 
    protected final void _PolyhedralConvexShape_getAabb(Transform trans, Vector3f aabbMin, Vector3f aabbMax) { 
 | 
        getNonvirtualAabb(trans, aabbMin, aabbMax, getMargin()); 
 | 
    } 
 | 
  
 | 
    public void recalcLocalAabb() { 
 | 
        isLocalAabbValid = true; 
 | 
  
 | 
        //#if 1 
 | 
  
 | 
        batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6); 
 | 
  
 | 
        for (int i=0; i<3; i++) { 
 | 
            VectorUtil.setCoord(localAabbMax, i, VectorUtil.getCoord(_supporting[i], i) + collisionMargin); 
 | 
            VectorUtil.setCoord(localAabbMin, i, VectorUtil.getCoord(_supporting[i + 3], i) - collisionMargin); 
 | 
        } 
 | 
         
 | 
        //#else 
 | 
        //for (int i=0; i<3; i++) { 
 | 
        //    Vector3f vec = Stack.alloc(Vector3f.class); 
 | 
        //    vec.set(0f, 0f, 0f); 
 | 
        //    VectorUtil.setCoord(vec, i, 1f); 
 | 
        //    Vector3f tmp = localGetSupportingVertex(vec, Stack.alloc(Vector3f.class)); 
 | 
        //    VectorUtil.setCoord(localAabbMax, i, VectorUtil.getCoord(tmp, i) + collisionMargin); 
 | 
        //    VectorUtil.setCoord(vec, i, -1f); 
 | 
        //    localGetSupportingVertex(vec, tmp); 
 | 
        //    VectorUtil.setCoord(localAabbMin, i, VectorUtil.getCoord(tmp, i) - collisionMargin); 
 | 
        //} 
 | 
        //#endif 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public void setLocalScaling(Vector3f scaling) { 
 | 
        super.setLocalScaling(scaling); 
 | 
        recalcLocalAabb(); 
 | 
    } 
 | 
  
 | 
    public abstract int getNumVertices(); 
 | 
  
 | 
    public abstract int getNumEdges(); 
 | 
  
 | 
    public abstract void getEdge(int i, Vector3f pa, Vector3f pb); 
 | 
  
 | 
    public abstract void getVertex(int i, Vector3f vtx); 
 | 
  
 | 
    public abstract int getNumPlanes(); 
 | 
  
 | 
    public abstract void getPlane(Vector3f planeNormal, Vector3f planeSupport, int i); 
 | 
     
 | 
//    public abstract  int getIndex(int i) const = 0 ;  
 | 
     
 | 
    public abstract boolean isInside(Vector3f pt, float tolerance); 
 | 
     
 | 
} 
 |