/* * Java port of Bullet (c) 2008 Martin Dvorak * * ShapeHull implemented by John McCutchan. * * 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.MiscUtil; import com.bulletphysics.linearmath.convexhull.*; import com.bulletphysics.util.IntArrayList; import com.bulletphysics.util.ObjectArrayList; import cz.advel.stack.Stack; import javax.vecmath.Vector3f; import javax.vecmath.Vector3d; /** * ShapeHull takes a {@link ConvexShape}, builds the convex hull using {@link HullLibrary} * and provides triangle indices and vertices. * * @author jezek2 */ public class ShapeHull implements java.io.Serializable { static final long serialVersionUID = -1102208318940158328L; protected ObjectArrayList vertices = new ObjectArrayList(); protected ObjectArrayList normals = new ObjectArrayList(); protected IntArrayList indices = new IntArrayList(); protected int numIndices; protected ConvexShape shape; protected ObjectArrayList unitSpherePoints = new ObjectArrayList(); public ShapeHull(ConvexShape shape) { this.shape = shape; this.vertices.clear(); this.normals.clear(); this.indices.clear(); this.numIndices = 0; // MiscUtil.resize(unitSpherePoints, NUM_UNITSPHERE_POINTS+ConvexShape.MAX_PREFERRED_PENETRATION_DIRECTIONS*2, Vector3f.class); //// for (int i=constUnitSpherePoints.size(); --i>=0;) { //// unitSpherePoints.getQuick(i).set(constUnitSpherePoints.getQuick(i)); //// } // int lines = (int)Math.sqrt(NUM_UNITSPHERE_POINTS); // int rows = lines; // Vector3f vec = new Vector3f(); // Superellipsoid supere = new Superellipsoid(); // for (int i=lines; --i>=0;) // { // for (int j=rows; --j>=0;) // { // double u = i; u /= lines-1; // double v = j; v /= rows-1; // // supere.biparamFunction(u, v, vec); // // unitSpherePoints.getQuick(i*rows + j).set(vec); // } // } } public boolean buildHull(float margin) { int lines = (int)Math.sqrt(NUM_UNITSPHERE_POINTS); int rows = lines; MiscUtil.resize(vertices, NUM_UNITSPHERE_POINTS*2, Vector3f.class); MiscUtil.resize(normals, NUM_UNITSPHERE_POINTS*2, Vector3f.class); Vector3f vec = new Vector3f(); Vector3f norm = new Vector3f(); Vector3f normout = new Vector3f(); Vector3f vec2 = new Vector3f(); Superellipsoid supere = new Superellipsoid(); CapsuleShape capsule = (CapsuleShape)shape; int loops = 1; if (capsule.anchor) loops++; for (int loop=loops; --loop>=0;) for (int j=rows; --j>=0;) { int k=0; for (int i=lines; --i>=0;) { double u = i; u /= lines-1; double v = j; v /= rows-1; supere.biparamFunction(u, v, vec, norm); capsule.localGetSupportingVertexWithNorm(vec, vec2, norm, normout); if (loop == 1) { //vec2.scale(0.5f); switch (capsule.getUpAxis()) { case 0: vec2.x /= capsule.getHalfHeight(); vec2.x *= capsule.getRadius()/2; vec2.x -= capsule.getHalfHeight(); break; case 1: vec2.y /= capsule.getHalfHeight(); vec2.y *= capsule.getRadius()/2; vec2.y -= capsule.getHalfHeight(); break; case 2: vec2.z /= capsule.getHalfHeight(); vec2.z *= capsule.getRadius()/2; vec2.z -= capsule.getHalfHeight(); break; } } vertices.getQuick(loop*NUM_UNITSPHERE_POINTS + i*rows + j).set(vec2); normals.getQuick(loop*NUM_UNITSPHERE_POINTS + i*rows + j).set(normout); } } numIndices = (lines*(rows-1) * 6) * loops; int i = 0; int j = 0; MiscUtil.resize(indices, numIndices, 0); for (int in=0; in= rows-1) { j = 0; i++; } } i = 0; j = 0; for (int in=numIndices/loops; in= rows-1) { j = 0; i++; } } return true; } public boolean buildHull0(float margin) { Vector3f norm = Stack.alloc(Vector3f.class); int numSampleDirections = NUM_UNITSPHERE_POINTS; { int numPDA = shape.getNumPreferredPenetrationDirections(); if (numPDA != 0) { for (int i=0; i supportPoints = new ObjectArrayList(); MiscUtil.resize(supportPoints, NUM_UNITSPHERE_POINTS + ConvexShape.MAX_PREFERRED_PENETRATION_DIRECTIONS * 2, Vector3f.class); for (int i=0; i getVertexPointer() { return vertices; } public ObjectArrayList getNormalPointer() { return normals; } public IntArrayList getIndexPointer() { return indices; } //////////////////////////////////////////////////////////////////////////// private static int NUM_UNITSPHERE_POINTS = 15*15; // 420; private static ObjectArrayList constUnitSpherePoints = new ObjectArrayList(); static { constUnitSpherePoints.add(new Vector3f(0.000000f, -0.000000f, -1.000000f)); constUnitSpherePoints.add(new Vector3f(0.723608f, -0.525725f, -0.447219f)); constUnitSpherePoints.add(new Vector3f(-0.276388f, -0.850649f, -0.447219f)); constUnitSpherePoints.add(new Vector3f(-0.894426f, -0.000000f, -0.447216f)); constUnitSpherePoints.add(new Vector3f(-0.276388f, 0.850649f, -0.447220f)); constUnitSpherePoints.add(new Vector3f(0.723608f, 0.525725f, -0.447219f)); constUnitSpherePoints.add(new Vector3f(0.276388f, -0.850649f, 0.447220f)); constUnitSpherePoints.add(new Vector3f(-0.723608f, -0.525725f, 0.447219f)); constUnitSpherePoints.add(new Vector3f(-0.723608f, 0.525725f, 0.447219f)); constUnitSpherePoints.add(new Vector3f(0.276388f, 0.850649f, 0.447219f)); constUnitSpherePoints.add(new Vector3f(0.894426f, 0.000000f, 0.447216f)); constUnitSpherePoints.add(new Vector3f(-0.000000f, 0.000000f, 1.000000f)); constUnitSpherePoints.add(new Vector3f(0.425323f, -0.309011f, -0.850654f)); constUnitSpherePoints.add(new Vector3f(-0.162456f, -0.499995f, -0.850654f)); constUnitSpherePoints.add(new Vector3f(0.262869f, -0.809012f, -0.525738f)); constUnitSpherePoints.add(new Vector3f(0.425323f, 0.309011f, -0.850654f)); constUnitSpherePoints.add(new Vector3f(0.850648f, -0.000000f, -0.525736f)); constUnitSpherePoints.add(new Vector3f(-0.525730f, -0.000000f, -0.850652f)); constUnitSpherePoints.add(new Vector3f(-0.688190f, -0.499997f, -0.525736f)); constUnitSpherePoints.add(new Vector3f(-0.162456f, 0.499995f, -0.850654f)); constUnitSpherePoints.add(new Vector3f(-0.688190f, 0.499997f, -0.525736f)); constUnitSpherePoints.add(new Vector3f(0.262869f, 0.809012f, -0.525738f)); constUnitSpherePoints.add(new Vector3f(0.951058f, 0.309013f, 0.000000f)); constUnitSpherePoints.add(new Vector3f(0.951058f, -0.309013f, 0.000000f)); constUnitSpherePoints.add(new Vector3f(0.587786f, -0.809017f, 0.000000f)); constUnitSpherePoints.add(new Vector3f(0.000000f, -1.000000f, 0.000000f)); constUnitSpherePoints.add(new Vector3f(-0.587786f, -0.809017f, 0.000000f)); constUnitSpherePoints.add(new Vector3f(-0.951058f, -0.309013f, -0.000000f)); constUnitSpherePoints.add(new Vector3f(-0.951058f, 0.309013f, -0.000000f)); constUnitSpherePoints.add(new Vector3f(-0.587786f, 0.809017f, -0.000000f)); constUnitSpherePoints.add(new Vector3f(-0.000000f, 1.000000f, -0.000000f)); constUnitSpherePoints.add(new Vector3f(0.587786f, 0.809017f, -0.000000f)); constUnitSpherePoints.add(new Vector3f(0.688190f, -0.499997f, 0.525736f)); constUnitSpherePoints.add(new Vector3f(-0.262869f, -0.809012f, 0.525738f)); constUnitSpherePoints.add(new Vector3f(-0.850648f, 0.000000f, 0.525736f)); constUnitSpherePoints.add(new Vector3f(-0.262869f, 0.809012f, 0.525738f)); constUnitSpherePoints.add(new Vector3f(0.688190f, 0.499997f, 0.525736f)); constUnitSpherePoints.add(new Vector3f(0.525730f, 0.000000f, 0.850652f)); constUnitSpherePoints.add(new Vector3f(0.162456f, -0.499995f, 0.850654f)); constUnitSpherePoints.add(new Vector3f(-0.425323f, -0.309011f, 0.850654f)); constUnitSpherePoints.add(new Vector3f(-0.425323f, 0.309011f, 0.850654f)); constUnitSpherePoints.add(new Vector3f(0.162456f, 0.499995f, 0.850654f)); } static int tablelength = 257; static double power1 = -1; static double[] powtable1 = new double[tablelength]; static double power2 = -1; static double[] powtable2 = new double[tablelength]; class Superellipsoid //extends Biparam /*Sphere*/ implements java.io.Serializable { Superellipsoid() { // inPnt = new cVector(); du = new Vector3f(); dv = new Vector3f(); // // name = "Superellipsoid"; east = 0.75; north = 1; //uDivs = vDivs = 32; // uDivs = 35; // vDivs = 34; // minUDivs = 3; // minVDivs = 2; } double signPower(double base, double pow) { //if (base == 0) // base = 0.0000001; if (base == 0 && pow == 0 || base == 1) return 1; if (base == 0) return 0; if (base == -1) return -1; if (base >= 0) return (double)Mathpow(base, pow); else return -(double)Mathpow(-base, pow); } double Mathpow(double base, double pow) { int basei = (int) (base * (tablelength - 1)); double[] table = null; if (pow == power1) { table = powtable1; } else if (pow == power2) { table = powtable2; } else { if (power2 == -1) { power2 = pow; table = powtable2 = new double[tablelength]; } else { power1 = pow; table = powtable1 = new double[tablelength]; power2 = -1; } } if (basei != 0 && table[basei] == 0) { table[basei] = Math.pow(basei/(tablelength - 1.0), pow); //if (table[basei] == 0) // System.out.println("POW == 0 : " + basei); } if (table[basei+1] == 0) { table[basei+1] = Math.pow((basei+1.0)/(tablelength - 1.0), pow); //if (table[basei+1] == 0) // System.out.println("POW == 0"); } double offset = base * (tablelength - 1) - basei; //System.out.println("offset = " + offset); return table[basei] * (1 - offset) + table[basei+1] * offset; } double DsignPower(double base, double pow) { if (base == 0) base = 0.0000000001; if (base == 1 || base == -1) return pow; if (base > 0) return pow * (double)(Mathpow(base, pow) / base); // - 1); else // if (base < 0) return pow * (double)(Mathpow(-base, pow) / -base); // - 1); //else //{ // if (pow == 1) // return 1; // else // return 0; //} } Vector3f du; Vector3f dv; //Vertex void biparamFunction(double u, double v, Vector3f out, Vector3f norm) { //System.out.println("U = " + u + "; V = " + v); double uAng = u * 2 * Math.PI; // LA.toRadians(u * 360); double vAng = v * Math.PI - Math.PI/2; // LA.toRadians(v * 180 - 90); double mcu = Math.cos(uAng); double msu = Math.sin(uAng); double mcv = Math.cos(vAng); double msv = Math.sin(vAng); if (u == 1) { mcu = 1; msu = 0; } if (v == 1) { mcv = 0; msv = 1; } if (v == 0) { mcv = 0; msv = -1; } double cu = signPower(mcu, north); double su = signPower(msu, north); double cv = signPower(mcv, east); double sv = signPower(msv, east); double z = radius * cv * cu; double x = radius * cv * su; double y = radius * sv; double dcu = DsignPower(mcu, north) * -msu; double dsu = DsignPower(msu, north) * mcu; double dcv = DsignPower(mcv, east) * -msv; double dsv = DsignPower(msv, east) * mcv; du.z = (float)(cv * dcu); du.x = (float)(cv * dsu); du.y = (float)(0); dv.z = (float)(dcv * cu); dv.x = (float)(dcv * su); dv.y = (float)(dsv); //if (du.length() == 0) // System.out.println("DU is null"); //if (dv.length() == 0) // System.out.println("DV is null"); out./*pos.*/x = (float)x; // = LA.newVector(x, y, z); out./*pos.*/y = (float)y; out./*pos.*/z = (float)z; if (du.dot(du) == 0) { norm.set(out); } else { du.normalize(); dv.normalize(); norm.cross(du, dv); // if (norm.dot(norm) == 0) // norm.z = 1; } norm.normalize(); // Vertex temp = new Vertex(); // // temp.norm = LA.newVector(x, y, z); // LA.vecCross(du,dv, temp.norm); // if (temp.norm.length() == 0) // temp.norm.y = 2*v - 1; // else // LA.vecNormalize(temp.norm); //if (temp.norm.dot(temp/*.pos*/) < 0) //temp.norm.mul(-1); //LA.vecAdd(temp/*.pos*/, center, temp/*.pos*/); // return temp; } double east; double north; double radius = 1; // private cVector inPnt; } }