/* 
 | 
 * Java port of Bullet (c) 2008 Martin Dvorak <jezek2@advel.cz> 
 | 
 *  
 | 
 * 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<Vector3f> vertices = new ObjectArrayList<Vector3f>(); 
 | 
    protected ObjectArrayList<Vector3f> normals = new ObjectArrayList<Vector3f>(); 
 | 
    protected IntArrayList indices = new IntArrayList(); 
 | 
    protected int numIndices; 
 | 
    protected ConvexShape shape; 
 | 
  
 | 
    protected ObjectArrayList<Vector3f> unitSpherePoints = new ObjectArrayList<Vector3f>(); 
 | 
  
 | 
    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); 
 | 
                             
 | 
                            // Nodes are bigger 
 | 
                            vec2.x *= 5; 
 | 
                            vec2.y *= 5; 
 | 
                            vec2.z *= 5; 
 | 
                             
 | 
                            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<numIndices/loops;) 
 | 
            { 
 | 
                indices.set(in++, i*(rows-1) + j); 
 | 
                indices.set(in++, (i+1)*(rows-1) + j+1); 
 | 
                indices.set(in++, i*(rows-1) + j+1); 
 | 
                indices.set(in++, i*(rows-1) + j); 
 | 
                indices.set(in++, (i+1)*(rows-1) + j); 
 | 
                indices.set(in++, (i+1)*(rows-1) + j+1); 
 | 
                 
 | 
                j++; 
 | 
                if (j >= rows-1) 
 | 
                { 
 | 
                    j = 0; 
 | 
                    i++; 
 | 
                } 
 | 
            } 
 | 
             
 | 
            i = 0; 
 | 
            j = 0; 
 | 
             
 | 
            for (int in=numIndices/loops; in<numIndices;) 
 | 
            { 
 | 
                indices.set(in++, NUM_UNITSPHERE_POINTS + i*(rows-1) + j); 
 | 
                indices.set(in++, NUM_UNITSPHERE_POINTS + (i+1)*(rows-1) + j+1); 
 | 
                indices.set(in++, NUM_UNITSPHERE_POINTS + i*(rows-1) + j+1); 
 | 
                indices.set(in++, NUM_UNITSPHERE_POINTS + i*(rows-1) + j); 
 | 
                indices.set(in++, NUM_UNITSPHERE_POINTS + (i+1)*(rows-1) + j); 
 | 
                indices.set(in++, NUM_UNITSPHERE_POINTS + (i+1)*(rows-1) + j+1); 
 | 
                 
 | 
                j++; 
 | 
                if (j >= 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<numPDA; i++) { 
 | 
                    shape.getPreferredPenetrationDirection(i, norm); 
 | 
                    unitSpherePoints.getQuick(numSampleDirections).set(norm); 
 | 
                    numSampleDirections++; 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
  
 | 
        ObjectArrayList<Vector3f> supportPoints = new ObjectArrayList<Vector3f>(); 
 | 
        MiscUtil.resize(supportPoints, NUM_UNITSPHERE_POINTS + ConvexShape.MAX_PREFERRED_PENETRATION_DIRECTIONS * 2, Vector3f.class); 
 | 
  
 | 
        for (int i=0; i<numSampleDirections; i++) { 
 | 
            shape.localGetSupportingVertex(unitSpherePoints.getQuick(i), supportPoints.getQuick(i)); 
 | 
        } 
 | 
  
 | 
        HullDesc hd = new HullDesc(); 
 | 
        hd.flags = HullFlags.TRIANGLES; 
 | 
        hd.vcount = numSampleDirections; 
 | 
  
 | 
        //#ifdef BT_USE_DOUBLE_PRECISION 
 | 
        //hd.mVertices = &supportPoints[0]; 
 | 
        //hd.mVertexStride = sizeof(btVector3); 
 | 
        //#else 
 | 
        hd.vertices = supportPoints; 
 | 
        //hd.vertexStride = 3 * 4; 
 | 
        //#endif 
 | 
  
 | 
        HullLibrary hl = new HullLibrary(); 
 | 
        HullResult hr = new HullResult(); 
 | 
        if (!hl.createConvexHull(hd, hr)) { 
 | 
            return false; 
 | 
        } 
 | 
  
 | 
        MiscUtil.resize(vertices, hr.numOutputVertices, Vector3f.class); 
 | 
        MiscUtil.resize(normals, hr.numOutputVertices, Vector3f.class); 
 | 
  
 | 
        for (int i=0; i<hr.numOutputVertices; i++) { 
 | 
            vertices.getQuick(i).set(hr.outputVertices.getQuick(i)); 
 | 
        } 
 | 
        numIndices = hr.numIndices; 
 | 
        MiscUtil.resize(indices, numIndices, 0); 
 | 
        for (int i=0; i<numIndices; i++) { 
 | 
            indices.set(i, hr.indices.get(i)); 
 | 
        } 
 | 
  
 | 
        // free temporary hull result that we just copied 
 | 
        hl.releaseResult(hr); 
 | 
  
 | 
        return true; 
 | 
    } 
 | 
  
 | 
    public int numTriangles() { 
 | 
        return numIndices / 3; 
 | 
    } 
 | 
  
 | 
    public int numVertices() { 
 | 
        return vertices.size(); 
 | 
    } 
 | 
  
 | 
    public int numIndices() { 
 | 
        return numIndices; 
 | 
    } 
 | 
  
 | 
    public ObjectArrayList<Vector3f> getVertexPointer() { 
 | 
        return vertices; 
 | 
    } 
 | 
  
 | 
    public ObjectArrayList<Vector3f> getNormalPointer() { 
 | 
        return normals; 
 | 
    } 
 | 
  
 | 
    public IntArrayList getIndexPointer() { 
 | 
        return indices; 
 | 
    } 
 | 
  
 | 
    //////////////////////////////////////////////////////////////////////////// 
 | 
     
 | 
    private static int NUM_UNITSPHERE_POINTS = 15*15; // 420; 
 | 
     
 | 
    private static ObjectArrayList<Vector3f> constUnitSpherePoints = new ObjectArrayList<Vector3f>(); 
 | 
     
 | 
    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; 
 | 
} 
 | 
} 
 |