From e24558ddeacfc945b9e9ba0a32b552d04e2ed4dd Mon Sep 17 00:00:00 2001
From: Normand Briere <nbriere@noware.ca>
Date: Sun, 02 Jun 2019 20:11:20 -0400
Subject: [PATCH] Selectable mode + new mesh reduction.

---
 ObjEditor.java    |   13 
 LA.java           |    3 
 Grid.java         |    2 
 Vertex.java       |   25 +
 Merge.java        |   80 +++--
 Composite.java    |    9 
 GenericJoint.java |   11 
 Grafreed.java     |    2 
 iCameraPane.java  |    4 
 BoundaryRep.java  |  423 ++++++++++++++++++++++++++++------
 CameraPane.java   |   45 ++
 Globals.java      |    3 
 GroupEditor.java  |   25 +
 Face.java         |    2 
 Object3D.java     |   43 ++
 cVector.java      |   18 +
 16 files changed, 544 insertions(+), 164 deletions(-)

diff --git a/BoundaryRep.java b/BoundaryRep.java
index 1781a47..3583aa0 100644
--- a/BoundaryRep.java
+++ b/BoundaryRep.java
@@ -161,6 +161,7 @@
                 || FaceCount() != other.FaceCount()
                 || !(indices == null ^ other.indices != null)) // july 2014
         {
+            // The meshes have different structures.
             //new Exception().printStackTrace();
             trimmed = other.trimmed;
             stripified = other.stripified;
@@ -239,9 +240,16 @@
         }
     }
 
-    Support[] InitConnections(BoundaryRep other)
+    transient Support[] cachesupports = null;
+    
+    Support[] InitConnections()
     {
-        int n = other.startvertices.length-1;
+        if (cachesupports != null)
+        {
+            return cachesupports;
+        }
+        
+        int n = this.startvertices.length-1;
         
         Support[] supports = new Support[n];
         
@@ -253,38 +261,60 @@
         
         for (int object=1; object<=n; object++)
         {
-            int start = other.startvertices[object-1];
-            int end = other.startvertices[object];
+            int start = this.startvertices[object-1];
+            int end = this.startvertices[object];
 
             if (start == end)
                 continue; // ??
             
+            /**
+        Vertex v2 = vertextemp;
+        v2.x = averagepoints[object*3];
+        v2.y = averagepoints[object*3+1];
+        v2.z = averagepoints[object*3+2];
+        
+        //v2.set(GetVertex(this.startvertices[subsupport]));
+        
+        // projected point
+        Vertex v3 = vertextemp2;
+        //GetVertex(this.startvertices[subsupport]);
+        v3.x = extremepoints[object*3];
+        v3.y = extremepoints[object*3+1];
+        v3.z = extremepoints[object*3+2];
+
+        vect3.set(v3); // "X" axis apex
+        vect3.sub(v2); // origin (center)
+        vect3.normalize();
+            /**/
+            
             int linkcount = 0;
 
             int objectinlist = -1;
+            
+            Support subsupport = supports[object-1];
 
             for (int object2=1; object2<=n; object2++)
             {
                 for (int i = start; i < end; i++)
                 {
-                    Vertex v = other.GetVertex(i);
+                    Vertex v = this.GetVertex(i);
 
-                    // 
-                    if (other.Contains(v, object2))
+                    // Check if v is close enough from any vertex of the given subobject.
+                    if (this.Contains(v, object2))
                     {
-                        if (linkcount == supports[object-1].links.length)
+                        if (linkcount == subsupport.links.length)
                             break;
 
                         if (object2 == object)
                             objectinlist = linkcount;
                         
-                        supports[object-1].links[linkcount++] = object2;
+                        subsupport.links[linkcount++] = object2;
                         break;
                     }
                 }
             }
                 
-            supports[object-1].links[linkcount] = -1;
+            subsupport.links[linkcount] = -1;
 
             if (objectinlist == -1)
                 assert(objectinlist != -1);
@@ -293,9 +323,9 @@
 //                assert(linkcount > 1);
 
             // show main support as blue
-            int first = supports[object-1].links[0];
-            supports[object-1].links[0] = supports[object-1].links[objectinlist];
-            supports[object-1].links[objectinlist] = first;
+            int first = subsupport.links[0];
+            subsupport.links[0] = subsupport.links[objectinlist];
+            subsupport.links[objectinlist] = first;
         }
 
         for (int loop = 0; --loop>=0;)
@@ -353,7 +383,7 @@
             supports = supports2;
         }
         
-        return supports;
+        return cachesupports = supports;
     }
     
     double Distance2(Vertex v, Vertex v2, double dist2beat, double[][] toRoot, int k)
@@ -598,7 +628,7 @@
 //                ;
         //
 
-        supportsize = supportsizes[subsupport];
+        supportsize = supportminsize[subsupport];
         
         double K = supportsize / distmax;
         
@@ -650,7 +680,8 @@
     //    if (supportsize * fadefactor > 1)
     //        return 1;
         
-        return supportsize * fadefactor;
+        return //supportsize *
+                supportsize * fadefactor;
     }
     
     void RecomputeBasis(BoundaryRep other, double[][] toRoot, Vertex v)
@@ -952,7 +983,7 @@
         
         // sept 2017 SEUIL = 0.1; // aout 2013
         
-        supports = InitConnections(other);
+        supports = other.InitConnections();
         
         other.supports = supports; // should be the other way around...
         
@@ -1895,7 +1926,7 @@
             return;
         }
         
-    //    System.exit(0);
+        // System.exit(0);
         
         cVector vect = new cVector();
         cVector normal = new cVector();
@@ -1966,7 +1997,7 @@
                 if (v.vertexlinks == null)
                     continue;
                 
-                if (v.weights != null && v.weights[j] == 0) // < 0.01 * v.totalweight) // == 0)
+                if (v.weights != null && v.weights[j] < 0.001 * v.totalweight) // == 0)
                 {
                     //testweight += v.weights[j-1];
                     continue;
@@ -2247,6 +2278,8 @@
     
     transient int lastsoundtime;
     
+    transient boolean once = false;
+    
     void setMasterThis0(BoundaryRep other, double[][] toRoot, boolean smooth, boolean marked)
     {
         if (LA.isIdentity(toRoot))
@@ -2302,7 +2335,11 @@
 
             if (v.totalweight == 0)
             {
-                System.err.println("v.totalweight == 0! --> " + this + " : " + other);
+                if (!once)
+                {
+                    System.err.println("v.totalweight == 0! --> " + this + " : " + other);
+                    once = true;
+                }
                 continue;
             }
                 
@@ -3098,6 +3135,7 @@
 //    
 //    transient VertexCompare[] vertexcompare = null;
     
+    // Check if v0 is close enough from any vertex of the given subobject of this.
     boolean Contains(Vertex v0, int object)
     {
         int start = startvertices[object-1];
@@ -3696,6 +3734,111 @@
      */
     }
 
+    void GenerateNormals2(boolean crease)
+    {
+        cVector tempVector = new cVector();
+        
+//        java.util.HashMap<cVector, cVector> tableBase = new java.util.HashMap<cVector, cVector>();
+//        
+//        
+//        for (int i=0; i<this.VertexCount(); i++)
+//        {
+//            Vertex v = this.GetVertex(i);
+//            
+//            tempVector.set(v);
+//            
+//            cVector n = tableBase.get(tempVector.ToFloat());
+//            
+//            if (n != null)
+//            {
+//                continue;
+//            }
+//            
+//            tableBase.put(new cVector(tempVector), new cVector(v.norm));
+//        }
+        
+        BoundaryRep tempSupport = this.support;
+        
+        this.support = null;
+        
+        BoundaryRep tempRep = (BoundaryRep)Grafreed.clone(this);
+        
+        this.support = tempSupport;
+        
+        //tempRep.Unstripify();
+        
+        tempRep.GenerateNormals2(crease);
+        
+        boolean keepnormal = Vertex.normalmode;
+        boolean epsequal = Grafreed.epsequal;
+        
+        Vertex.normalmode = false;
+        Grafreed.epsequal = false; // A bit strange
+
+        // No need to have a match for vertex counts.
+        
+        java.util.HashMap<cVector, cVector> table = new java.util.HashMap<cVector, cVector>();
+        
+        for (int i=0; i<tempRep.VertexCount(); i++)
+        {
+            Vertex v = tempRep.GetVertex(i);
+            
+            cVector n = table.get(tempVector.ToFloat());
+            
+            if (v.norm.x == 1 && v.norm.y == 0 && v.norm.z == 0)
+            {
+                //continue;
+            }
+            
+            tempVector.set(v);
+            
+            //cVector nBase = tableBase.get(tempVector);
+            
+            //if (v.norm.dot(nBase) < 0.9)
+            //{
+            //    continue;
+            //}
+            
+            if (n != null && n.x == 1 && n.y == 0 && n.z == 0)
+            {
+                //continue;
+            }
+            
+            if (n != null)
+            {
+//                if (n.dot(v.norm) < 0)
+//                    n.sub(v.norm);
+//                else
+//                    n.add(v.norm);
+//                
+//                n.normalize();
+                continue;
+            }
+            
+            table.put(new cVector(tempVector), new cVector(v.norm));
+        }
+        
+        for (int i=0; i<this.VertexCount(); i++)
+        {
+            Vertex v = this.GetVertex(i);
+            
+            tempVector.set(v);
+            
+            cVector n = table.get(tempVector.ToFloat());
+            
+            //if (n.dot(v.norm) < 0)
+            if (n == null)
+                continue;
+            
+            LA.vecCopy(n, v.norm);
+            
+            this.SetVertex(v, i);
+        }
+        
+        Grafreed.epsequal = epsequal;
+        Vertex.normalmode = keepnormal;
+    }
+    
     void GenerateNormals(boolean crease)
     {
         boolean wastrim = trimmed;
@@ -3869,6 +4012,9 @@
                 {
                     triangles[i] = i;
                 }
+                
+                Untrim();
+                MergeNormals();
             }
         }
 
@@ -3929,6 +4075,9 @@
                 triangles = new int[1];
                 triangles[0] = 3;
             }
+            
+            Untrim();
+            MergeNormals();
         }
 
     /*
@@ -3978,6 +4127,40 @@
         }
 
         Vertex.normalmode = false;
+    }
+    
+    void MergeNormals()
+    {
+        boolean smooth = Grafreed.smoothmode;
+        boolean link = Grafreed.linkUV;
+        Grafreed.smoothmode = true;
+        Grafreed.linkUV = true;
+
+        System.out.println("#Vertex = " + VertexCount());
+        System.out.println("#Face = " + FaceCount());
+
+        java.util.HashSet<Vertex> table = new java.util.HashSet<Vertex>();
+        
+        for (int i = 0; i < VertexCount(); i++)
+        {
+            Vertex v = GetVertex(i);
+
+            if (!table.contains(v))
+            {
+                table.add(v);
+            }
+        }
+
+        Grafreed.smoothmode = smooth;
+        Grafreed.linkUV = link;
+        
+//        for (int i = 0; i < VertexCount(); i++)
+//        {
+//            Vertex v = GetVertex(i);
+//
+//            table.add(v);
+//        }
+
     }
     
     static cVector temp1 = new cVector();
@@ -4752,7 +4935,7 @@
             {
                 i3 = positions.length-3;
                 i2 = uvmap.length - 2;
-                new Exception().printStackTrace();
+                //new Exception().printStackTrace();
             }
             
             v./*pos.*/x = positions[i3];
@@ -5476,17 +5659,27 @@
     
     transient int nbbadfaces; // ?? = 1000000;
     
-    int ChooseTriangle()
+    /*
+     */
+    int ChooseTriangle(boolean firstEquilateral)
     {
         int chosen = -1;
         
         double minweight = 1E10;
         
+        int step = 8; // ?
+        
+        if (firstEquilateral)
+            step = 1;
+        
         nbbadfaces = 0;
-        for (int i=0; i<faces.size(); i+=8)
+        for (int i=0; i<faces.size(); i+=step)
 //        for (int i=faces.size(); (i-=8)>=0;)
         {
             Face face = (Face) faces.get(i);
+            
+            if (face.used)
+                continue;
             
             if (!Valid(face))
             {
@@ -5496,6 +5689,15 @@
             
             if (Boundary(face))
                 continue;
+            
+//            if (Boundary(face.p))
+//                continue;
+//            
+//            if (Boundary(face.q))
+//                continue;
+//            
+//            if (Boundary(face.r))
+//                continue;
             
             if (!ValidValence(face))
                 continue;
@@ -5508,22 +5710,55 @@
         //??    if (face.weight < 0)
         //        continue;
             
-            double K = 1; // 0.01; // .25;
-            
-            double factor = (1-K)*face.nbiterations + K; //*face.weight;
-            
-            double weight = FaceWeight(face); // *Math.pow(PerimeterMax(face),0.25)*factor;
-            
-            if (minweight > weight)
+            if (firstEquilateral)
             {
-                minweight = weight;
+                if (OneFaceUsed(links.get(face.p)))
+                    continue;
+
+                if (OneFaceUsed(links.get(face.q)))
+                    continue;
+
+                if (OneFaceUsed(links.get(face.r)))
+                    continue;
+
                 chosen = i;
-                if (minweight == 0)
-                    break;
+                break;
+            }
+            else
+            {
+                double K = 1; // 0.01; // .25;
+
+                double factor = (1-K)*face.nbiterations + K; //*face.weight;
+
+                double weight = FaceWeight(face); // *Math.pow(PerimeterMax(face),0.25)*factor;
+
+                if (minweight > weight)
+                {
+                    minweight = weight;
+                    chosen = i;
+                    if (minweight == 0)
+                        break;
+                }
             }
         }
         
         return chosen;
+    }
+
+    private boolean OneFaceUsed(Vector<Face> faces)
+    {
+        if (faces.size() != 6)
+            return true;
+                
+        for (int i=0; i<6; i+=1)
+        {
+            if (faces.get(i).used)
+            {
+                return true;
+            }
+        }
+
+        return false;
     }
         
     static boolean remove3valence = true;
@@ -5559,7 +5794,7 @@
                 }
                 else
                 {
-                    assert(links.size() == vertices.size());
+                // TODO   Grafreed.Assert(links.size() == vertices.size());
                     
                     links.setSize(vertices.size());
                     for (int i=vertices.size(); --i>=0;)
@@ -5567,6 +5802,7 @@
 //                        linkstouched[i] = false;
                         if (links.get(i) == null) // ??
                         {
+                            new Exception().printStackTrace();
                             links.set(i, new Vector(8));
 //                            linkstouched[i] = true;
                         }
@@ -5577,6 +5813,8 @@
                     }
                 }
 
+                boolean once = false;
+                
                 for (int i=faces.size(); --i>=0;)
                 {
                     Face face = (Face) faces.get(i);
@@ -5588,6 +5826,9 @@
                     //if (linkstouched[face.r])
                         links.get(face.r).add(face);
                     
+                        if (face.used)
+                            once = true;
+                        
                     face.good = 1;
                     face.boundary = -1;
                 }
@@ -6953,6 +7194,10 @@
             return (face.boundary = 1) == 1;
         }
         
+        // June 2019
+        if (true)
+            return (face.boundary = 0) == 1;
+        
         // reverse triangle test
         q1.set(p);
         q2.set(q);
@@ -7402,7 +7647,7 @@
             //InitWeights();
         }
         
-        int chosen = ChooseTriangle(); // Best is slow and not really better
+        int chosen = ChooseTriangle(true); // Best is slow and not really better
         
         if (chosen == -1)
         {
@@ -7416,7 +7661,7 @@
                 //remove3valence = false;
              //   InitWeights();
 
-                chosen = ChooseTriangle();
+                chosen = ChooseTriangle(true);
             }
         }
         
@@ -7692,7 +7937,7 @@
     
 //    boolean lock;
     
-    void SplitInTwo(boolean reduction34, boolean onlyone)
+    boolean SplitInTwo(boolean reduction34, boolean onlyone)
     {
         if (stripified)
         {
@@ -7729,12 +7974,12 @@
         {
             System.err.println("EXCEPTION CAUGHT");
             e.printStackTrace();
-            return;
+            return false;
         } catch (Error e)
         {
             System.err.println("ERROR CAUGHT");
             e.printStackTrace();
-            return;
+            return false;
         }
         
         System.out.println("# faces = " + faces.size());
@@ -7744,6 +7989,7 @@
         {
             Face face = (Face) faces.get(i);
             
+            face.used = false;
             face.nbiterations = 1;
             face.weight = -1;
             face.boundary = -1;
@@ -7795,6 +8041,11 @@
         nbbadfaces = faces.size();
         //remove3valence = true;
        
+        int count = 2;
+        
+        if (onlyone)
+            count = 1;
+        
         firstpass = true;
         
         int n = faces.size();
@@ -7810,8 +8061,9 @@
             System.out.print('.');
         }
         System.out.println();
+        boolean atleastone = false;
         int i = 0;
-        while (reduction34 || faces.size() > n/2)
+        while (true) // reduction34 || faces.size() > n/2)
         {
             if (i++%100 == 0)
             {
@@ -7833,6 +8085,8 @@
                 {
                     if (!RemoveOneTriangle())
                         break;
+                    
+                    atleastone = true;
                 }
          //       if (iterationcount == 0)
          //           break;
@@ -7843,8 +8097,8 @@
                 break;
             }
             firstpass = false;
-            if (onlyone)
-                break; // one triangle only
+//            if (--count<0 && !reduction34)
+//                break; // one triangle only
         }
         
         InitLinks(false); // for further display
@@ -7860,6 +8114,8 @@
         Trim(true,false,false,false,false);
         
         Globals.theRenderer.setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR));
+        
+        return atleastone;
     }
     
     void UpdateIndices(Face face, Face minface)
@@ -7872,18 +8128,21 @@
             face.p = minface.p;
             //if (leafweights)
                 face.good = 0; // false;
+                face.used = true;
         }
         if (face.q == minface.p || face.q == minface.q || face.q == minface.r)
         {
             face.q = minface.p;
             //if (leafweights)
                 face.good = 0; // false;
+                face.used = true;
         }
         if (face.r == minface.p || face.r == minface.q || face.r == minface.r)
         {
             face.r = minface.p;
             //if (leafweights)
                 face.good = 0; // false;
+                face.used = true;
         }
 
         if (face.p >/*=*/ minface.q && face.p < minface.r)
@@ -7943,50 +8202,50 @@
             if (v == 2)
                 vert = minface.r;
 //            Face face = (Face) faces.get(i);
-        Vector<Face> vertfaces = links.get(vert);
-        for (int i=vertfaces.size(); --i>=0;)
-        {
-            Face face = (Face) vertfaces.get(i);
-            
-         //   if (face.weight == 10000)
-         //       continue;
-            
-            if (face.p == minface.p || face.q == minface.p || face.r == minface.p ||
-                face.p == minface.q || face.q == minface.q || face.r == minface.q ||
-                face.p == minface.r || face.q == minface.r || face.r == minface.r)
+            Vector<Face> vertfaces = links.get(vert);
+            for (int i=vertfaces.size(); --i>=0;)
             {
-                if (!leafweights)
+                Face face = (Face) vertfaces.get(i);
+
+             //   if (face.weight == 10000)
+             //       continue;
+
+                if (face.p == minface.p || face.q == minface.p || face.r == minface.p ||
+                    face.p == minface.q || face.q == minface.q || face.r == minface.q ||
+                    face.p == minface.r || face.q == minface.r || face.r == minface.r)
                 {
-//                    if(minfaceweight <= 0)
-//                    assert(minfaceweight > 0);
-//                    
-//                    //FaceWeight(face);
-//                    if(face.weight < 0)
-//                    assert(face.weight >= 0);
-                    
-                    face.weight += minfaceweight;
-                    
-//                    if (face.weight >= 10000)
-//                        assert(face.weight < 10000);
+                    if (!leafweights)
+                    {
+    //                    if(minfaceweight <= 0)
+    //                    assert(minfaceweight > 0);
+    //                    
+    //                    //FaceWeight(face);
+    //                    if(face.weight < 0)
+    //                    assert(face.weight >= 0);
+
+                        face.weight += minfaceweight;
+
+    //                    if (face.weight >= 10000)
+    //                        assert(face.weight < 10000);
+                    }
+                    else
+                        face.weight = -1;
+
+                    face.nbiterations += 1;
+                    face.boundary = -1;
+
+                    Vertex p = (Vertex)vertices.get(face.p);
+                    Vertex q = (Vertex)vertices.get(face.q);
+                    Vertex r = (Vertex)vertices.get(face.r);
+
+                    p.boundary = -1;
+                    q.boundary = -1;
+                    r.boundary = -1;
                 }
                 else
-                    face.weight = -1;
-                
-                face.nbiterations += 1;
-                face.boundary = -1;
-                
-                Vertex p = (Vertex)vertices.get(face.p);
-                Vertex q = (Vertex)vertices.get(face.q);
-                Vertex r = (Vertex)vertices.get(face.r);
-
-                p.boundary = -1;
-                q.boundary = -1;
-                r.boundary = -1;
+                    assert(false);
             }
-            else
-                assert(false);
         }
-    }
         
 //        TouchVertex(minface.p);
 //        TouchVertex(minface.q);
@@ -8187,6 +8446,7 @@
         for (int i=vertfaces.size(); --i>=0;)
         {
             Face face = (Face) vertfaces.get(i);
+            face.used = true;
             face.good = 0; // false;
             if (leafweights)
                 face.weight = -1;
@@ -8465,7 +8725,8 @@
     int[] startvertices;
     float[] averagepoints;
     float[] extremepoints;
-    float[] supportsizes; // distance of closest point
+    float[] supportminsize; // distance of closest point
+    float[] supportmaxsize; // distance of fartest point
     
     transient Hashtable vertextable;
     /*transient*/ private Vertex[] verticesCopy;
diff --git a/CameraPane.java b/CameraPane.java
index 9a919e6..7039da8 100644
--- a/CameraPane.java
+++ b/CameraPane.java
@@ -8022,7 +8022,7 @@
         }
     }
 
-    /*boolean*/ public void BindTextures(cTexture tex, int resolution) // INTERFACE
+    /*boolean*/ public void BindTextures(cTexture tex, int resolution) throws Exception // INTERFACE
     {
         if (// DrawMode() != 0 || /*tex == null ||*/
                 ambientOcclusion ) // || !textureon)
@@ -8067,7 +8067,7 @@
         return; // true;
     }
     
-    CacheTexture GetCacheTexture(String tex, boolean bump, int resolution)
+    CacheTexture GetCacheTexture(String tex, boolean bump, int resolution) throws Exception
     {
         CacheTexture/*com.sun.opengl.util.texture.Texture*/ texture = null;
         
@@ -8184,7 +8184,9 @@
                                 texturedata = GetFileTexture(cachename, processbump, resolution);                                
                                 
                                 
-                                if (texturedata != null)
+                                if (texturedata == null)
+                                    throw new Exception();
+                                    
                                     texture = new CacheTexture(com.sun.opengl.util.texture.TextureIO.newTexture(texturedata),resolution);
         //texture = GetTexture(tex, bump);
                             }
@@ -8306,7 +8308,7 @@
         return texture;
     }
     
-    com.sun.opengl.util.texture.Texture GetTexture(String tex, boolean bump, int resolution)
+    com.sun.opengl.util.texture.Texture GetTexture(String tex, boolean bump, int resolution) throws Exception
     {
         CacheTexture texture = GetCacheTexture(tex, bump, resolution);
                 
@@ -8324,14 +8326,14 @@
         return texture!=null?texture.texture:null;
     }
     
-    public com.sun.opengl.util.texture.TextureData GetTextureData(String tex, boolean bump, int resolution)
+    public com.sun.opengl.util.texture.TextureData GetTextureData(String tex, boolean bump, int resolution) throws Exception
     {
         CacheTexture texture = GetCacheTexture(tex, bump, resolution);
                 
         return texture!=null?texture.texturedata:null;
     }
     
-    boolean BindTexture(String tex, boolean bump, int resolution)
+    boolean BindTexture(String tex, boolean bump, int resolution) throws Exception
     {
         if (/*tex == null ||*/ ambientOcclusion ) // || !textureon)
         {
@@ -10798,7 +10800,16 @@
             // Bump noise
             gl.glActiveTexture(GL.GL_TEXTURE6);
             //gl.glBindTexture(GL.GL_TEXTURE_2D, bump_noise);
-            BindTexture(NOISE_TEXTURE, false, 2);
+            
+    try
+    {
+        BindTexture(NOISE_TEXTURE, false, 2);
+    }
+    catch (Exception e)
+    {
+        System.err.println("FAILED: " + NOISE_TEXTURE);
+    }
+           
 
             gl.glActiveTexture(GL.GL_TEXTURE0);
             gl.glEnable(GL.GL_TEXTURE_2D);
@@ -11354,7 +11365,14 @@
 
                 usedtextures.clear();
             
-                BindTextures(DEFAULT_TEXTURES, 2);
+    try
+    {
+        BindTextures(DEFAULT_TEXTURES, 2);
+    }
+    catch (Exception e)
+    {
+        System.err.println("FAILED: " + DEFAULT_TEXTURES);
+    }
             }
             //System.out.println("--> " + stackdepth);
 //            GrafreeD.traceon();
@@ -11445,7 +11463,14 @@
             if (checker != null && DrawMode() == DEFAULT)
             {
                 //BindTexture(IMMORTAL_TEXTURE);
-                BindTextures(checker.GetTextures(), checker.texres);
+    try
+    {
+        BindTextures(checker.GetTextures(), checker.texres);
+    }
+    catch (Exception e)
+    {
+        System.err.println("FAILED: " + checker.GetTextures());
+    }
                 // NEAREST
                 GetGL().glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); // GL.GL_LINEAR);
                 DrawChecker(gl);
@@ -16602,7 +16627,7 @@
             //gl.glColorMask(false, false, false, false);
 
             //render_scene_from_light_view(gl, drawable, 0, 0);
-            if (Globals.RENDERSHADOW && Globals.lighttouched && !movingcamera) // && !parent.IsFreezed())
+            if (Globals.RENDERSHADOW && Globals.lighttouched && (!movingcamera || !Globals.FREEZEONMOVE)) // && !parent.IsFreezed())
             {
                 gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
 
diff --git a/Composite.java b/Composite.java
index bffa912..1d9e036 100644
--- a/Composite.java
+++ b/Composite.java
@@ -866,7 +866,14 @@
         tex = GetTextures();
     }
 
-    display.BindTextures(tex, texres);
+    try
+    {
+        display.BindTextures(tex, texres);
+    }
+    catch (Exception e)
+    {
+        System.err.println("FAILED: " + this);
+    }
     
         if (//true) // new NORMAND
             touched || softtouched)
diff --git a/Face.java b/Face.java
index 6b289df..b6c962a 100644
--- a/Face.java
+++ b/Face.java
@@ -31,6 +31,8 @@
     //cVector norm;
     //short flags;
         
+    transient boolean used;
+    
     transient float weight; // face weight using normals if leaf or maximum of all recursive elements
     transient int good; // vertex links broken
     transient int boundary;
diff --git a/GenericJoint.java b/GenericJoint.java
index 1119276..4c7c0e0 100644
--- a/GenericJoint.java
+++ b/GenericJoint.java
@@ -557,7 +557,8 @@
                 bRep.startvertices = new int[numObjects];
             bRep.averagepoints = new float[(bRep.startvertices.length-1) * 3];
             bRep.extremepoints = new float[(bRep.startvertices.length-1) * 3];
-            bRep.supportsizes = new float[(bRep.startvertices.length-1)];
+            bRep.supportminsize = new float[(bRep.startvertices.length-1)];
+            bRep.supportmaxsize = new float[(bRep.startvertices.length-1)];
                 buildrep = true;
                 
                 initialmatrices = new ObjectArrayList<Transform>();
@@ -1225,11 +1226,12 @@
                                 }
                                 else
                                 {
-                                    if (bRep.averagepoints == null || bRep.extremepoints == null || bRep.supportsizes == null)
+                                    if (bRep.averagepoints == null || bRep.extremepoints == null || bRep.supportminsize == null || bRep.supportmaxsize == null)
                                     {
                                         bRep.averagepoints = new float[(bRep.startvertices.length-1) * 3];
                                         bRep.extremepoints = new float[(bRep.startvertices.length-1) * 3];
-                                        bRep.supportsizes = new float[(bRep.startvertices.length-1)];
+                                        bRep.supportminsize = new float[(bRep.startvertices.length-1)];
+                                        bRep.supportmaxsize = new float[(bRep.startvertices.length-1)];
                                     }
                                     
                                     float averagex = 0;
@@ -1299,7 +1301,8 @@
                                         }
                                     }
                                     
-                                    bRep.supportsizes[currentobject-1] = (float)Math.sqrt(mindist2);
+                                    bRep.supportminsize[currentobject-1] = (float)Math.sqrt(mindist2);
+                                    bRep.supportmaxsize[currentobject-1] = (float)Math.sqrt(maxdist2);
                                 }
 
 //                                if (hull.numTriangles() > 0)
diff --git a/Globals.java b/Globals.java
index ca7d104..e0c7291 100644
--- a/Globals.java
+++ b/Globals.java
@@ -1,12 +1,13 @@
 
 public class Globals
 {
-        public static boolean ADVANCED = false;
+        public static boolean ADVANCED = true; //false;
         
     static iCameraPane theRenderer;
     
         private static boolean LIVE = false;
         public static boolean RENDERSHADOW = true;
+        public static boolean FREEZEONMOVE = false; // true;
         
         static boolean CROWD = false;
         static public int drawMode = iCameraPane.DEFAULT; // WARNING
diff --git a/Grafreed.java b/Grafreed.java
index 088a313..f05fa38 100644
--- a/Grafreed.java
+++ b/Grafreed.java
@@ -23,6 +23,8 @@
     static float epsvertex2 = 0.001f;
     static boolean linkUV = false; // not uniform at load time
 
+    static boolean smoothmode = false;
+    
     static Wav wav = new Wav("/Users/nbriere/0ut/wavs/monoformat"); // output");
     static boolean hassound = false;
     static boolean savesound = false;
diff --git a/Grid.java b/Grid.java
index f607c0d..1780c12 100644
--- a/Grid.java
+++ b/Grid.java
@@ -4,7 +4,7 @@
 
     Grid()
     {
-        this(35, 34);
+        this(36, 36);
     }
 
     Grid(int u, int v)
diff --git a/GroupEditor.java b/GroupEditor.java
index a7eda89..e833b7c 100644
--- a/GroupEditor.java
+++ b/GroupEditor.java
@@ -210,10 +210,6 @@
 		oe.menuBar.add(menu = new Menu("Setting"));
         if (Globals.ADVANCED)
         {
-                resetMeshItem = menu.add(new MenuItem("Reset All"));
-		resetMeshItem.addActionListener(this);
-		stepAllItem = menu.add(new MenuItem("Step All"));
-		stepAllItem.addActionListener(this);
 		revertMeshItem = menu.add(new MenuItem("Revert Meshes"));
 		revertMeshItem.addActionListener(this);
 		resetreferencesItem = menu.add(new MenuItem("Reset Mesh References"));
@@ -372,6 +368,10 @@
                 oe.menuBar.add(menu = new Menu("Attributes"));
 		clearMaterialsItem = menu.add(new MenuItem("Clear Materials"));
 		clearMaterialsItem.addActionListener(this);
+                resetAllItem = menu.add(new MenuItem("Reset All"));
+		resetAllItem.addActionListener(this);
+		stepAllItem = menu.add(new MenuItem("Step All"));
+		stepAllItem.addActionListener(this);
 		menu.add("-");
 		liveleavesItem = menu.add(new MenuItem("Live Leaves"));
 		liveleavesItem.addActionListener(this);
@@ -493,7 +493,7 @@
                 //this.AddOptions(oe.toolbarPanel, oe.aConstraints);
                 
                 oe.toolbarPanel.add(liveCB = new cCheckBox("Live", Globals.isLIVE())); //, oe.aConstraints);
-                liveCB.setToolTipText("Enabled animation");
+                liveCB.setToolTipText("Enable animation");
                                 liveCB.addItemListener(this);
 
 		oe.toolbarPanel.add(oneStepButton = new cButton("Step", !Grafreed.NIMBUSLAF)); //, oe.aConstraints);
@@ -2281,7 +2281,7 @@
 		{
 			RevertMeshes();
 		} else
-		if (source == resetMeshItem)
+		if (source == resetAllItem)
 		{
 			ResetAll();
 		} else
@@ -3652,7 +3652,16 @@
                             String pigment = Object3D.GetPigment(tex);
                             //String bump = Object3D.GetBump(tex);
                             
-                            com.sun.opengl.util.texture.TextureData texturedata = Globals.theRenderer.GetTextureData(pigment, false, node.texres);
+                            com.sun.opengl.util.texture.TextureData texturedata = null;
+                            
+                            try
+                            {
+                                texturedata = Globals.theRenderer.GetTextureData(pigment, false, node.texres);
+                            }
+                            catch (Exception e)
+                            {
+                                System.err.println("FAIL: " + node);
+                            }
                             
                             double s = v.s;
                             
@@ -5131,7 +5140,7 @@
 	private MenuItem linkverticesItem;
 	private MenuItem relinkverticesItem;
 	private MenuItem setMasterItem;
-	private MenuItem resetMeshItem;
+	private MenuItem resetAllItem;
 	private MenuItem stepAllItem;
 	private MenuItem revertMeshItem;
 	private MenuItem poseMeshItem;
diff --git a/LA.java b/LA.java
index 904647a..154bebd 100644
--- a/LA.java
+++ b/LA.java
@@ -88,6 +88,9 @@
 
     static void vecCopy(cVector a, cVector b)
     {
+        Grafreed.Assert (a != null);
+        assert (b != null);
+        
         b.x = a.x;
         b.y = a.y;
         b.z = a.z;
diff --git a/Merge.java b/Merge.java
index 24d1788..03408c4 100644
--- a/Merge.java
+++ b/Merge.java
@@ -134,6 +134,7 @@
     transient cVector maxima = new cVector();
 
 //    ObjectArrayList<Transform> initialmatrices;
+    transient boolean rendered = false;
 
     void DrawNode(iCameraPane display, Object3D /*Composite*/ root, boolean selected) // ??
     {
@@ -153,6 +154,8 @@
             {
                 e.printStackTrace();
             }
+            
+            rendered = true;
         }
         
         super.DrawNode(display, root, selected);
@@ -260,7 +263,8 @@
             bRep.startvertices = new int[NumGeometries(GetObject()) + 1];
             bRep.averagepoints = new float[(bRep.startvertices.length-1) * 3];
             bRep.extremepoints = new float[(bRep.startvertices.length-1) * 3];
-            bRep.supportsizes = new float[(bRep.startvertices.length-1)];
+            bRep.supportminsize = new float[(bRep.startvertices.length-1)];
+            bRep.supportmaxsize = new float[(bRep.startvertices.length-1)];
             buildrep = true;
 
          //   initialmatrices = new ObjectArrayList<Transform>();
@@ -686,11 +690,12 @@
                                 }
                                 else
                                 {
-                                    if (bRep.averagepoints == null || bRep.extremepoints == null || bRep.supportsizes == null)
+                                    if (bRep.averagepoints == null || bRep.extremepoints == null || bRep.supportminsize == null || bRep.supportmaxsize == null)
                                     {
                                         bRep.averagepoints = new float[(bRep.startvertices.length-1) * 3];
                                         bRep.extremepoints = new float[(bRep.startvertices.length-1) * 3];
-                                        bRep.supportsizes = new float[(bRep.startvertices.length-1)];
+                                        bRep.supportminsize = new float[(bRep.startvertices.length-1)];
+                                        bRep.supportmaxsize = new float[(bRep.startvertices.length-1)];
                                     }
                                     
                                     float averagex = 0;
@@ -731,42 +736,47 @@
                                         v.norm.normalize();
                                     }
                                     
-                                    int index3 = currentobject-1;
-                                    index3 *= 3;
-                                    
-                                    bRep.averagepoints[index3] = averagex/count;
-                                    bRep.averagepoints[index3+1] = averagey/count;
-                                    bRep.averagepoints[index3+2] = averagez/count;
-
-                                    double mindist2 = 1E10f;
-                                    double maxdist2 = -1E10f;
-                                    
-                                    for (int i=bRep.startvertices[currentobject-1]; i<bRep.startvertices[currentobject]; i++)
+                                    if (!rendered)
                                     {
-                                        Vertex v = bRep.GetVertex(i);
-                                        
-                                        double x = v.x - bRep.averagepoints[index3];
-                                        double y = v.y - bRep.averagepoints[index3+1];
-                                        double z = v.z - bRep.averagepoints[index3+2];
-                                        
-                                        double dist2 = x*x + y*y + z*z;
-                                        
-                                        if (mindist2 > dist2)
-                                            mindist2 = dist2;
-                                        if (maxdist2 < dist2)
+                                        int index3 = currentobject-1;
+                                        index3 *= 3;
+
+                                        bRep.averagepoints[index3] = averagex/count;
+                                        bRep.averagepoints[index3+1] = averagey/count;
+                                        bRep.averagepoints[index3+2] = averagez/count;
+
+                                        double mindist2 = 1E10f;
+                                        double maxdist2 = -1E10f;
+
+                                        for (int i=bRep.startvertices[currentobject-1]; i<bRep.startvertices[currentobject]; i++)
                                         {
-                                            maxdist2 = dist2;
-                                            bRep.extremepoints[index3] = (float)v.x;
-                                            bRep.extremepoints[index3+1] = (float)v.y;
-                                            bRep.extremepoints[index3+2] = (float)v.z;
+                                            Vertex v = bRep.GetVertex(i);
+
+                                            double x = v.x - bRep.averagepoints[index3];
+                                            double y = v.y - bRep.averagepoints[index3+1];
+                                            double z = v.z - bRep.averagepoints[index3+2];
+
+                                            double dist2 = x*x + y*y + z*z;
+
+                                            if (mindist2 > dist2)
+                                                mindist2 = dist2;
+
+                                            if (maxdist2 < dist2)
+                                            {
+                                                maxdist2 = dist2;
+                                                bRep.extremepoints[index3] = (float)v.x;
+                                                bRep.extremepoints[index3+1] = (float)v.y;
+                                                bRep.extremepoints[index3+2] = (float)v.z;
+                                            }
                                         }
+
+                                        bRep.supportminsize[currentobject-1] = (float)Math.sqrt(mindist2);
+                                        bRep.supportmaxsize[currentobject-1] = (float)Math.sqrt(maxdist2);
+    //                                    for (int i = 0; i < hull.numVertices(); i++)
+    //                                    {
+    //                                        
+    //                                    }
                                     }
-                                    
-                                    bRep.supportsizes[currentobject-1] = (float)Math.sqrt(mindist2);
-//                                    for (int i = 0; i < hull.numVertices(); i++)
-//                                    {
-//                                        
-//                                    }
                                 }
 
 //                                if (hull.numTriangles() > 0)
diff --git a/ObjEditor.java b/ObjEditor.java
index cfefeab..75f346b 100644
--- a/ObjEditor.java
+++ b/ObjEditor.java
@@ -784,6 +784,7 @@
 //    NumberSlider vDivsField;
 //    JCheckBox endcaps;
     JCheckBox liveCB;
+    JCheckBox selectCB;
     JCheckBox hideCB;
     JCheckBox link2masterCB;
     JCheckBox markCB;
@@ -986,9 +987,11 @@
             
         liveCB = AddCheckBox(setupPanel, "Live", copy.live);
                 liveCB.setToolTipText("Animate object");
+        selectCB = AddCheckBox(setupPanel, "Select", !copy.dontselect);
+                selectCB.setToolTipText("Make object selectable");
+//            Return();
         hideCB = AddCheckBox(setupPanel, "Hide", copy.hide);
                 hideCB.setToolTipText("Hide object");
-//            Return();
         markCB = AddCheckBox(setupPanel, "Mark", copy.marked);
         markCB.setToolTipText("Set the animation target transform");
         
@@ -1028,7 +1031,7 @@
         oe.ctrlPanel.add(commandsPanel);
         oe.ctrlPanel.Return();
 
-    pushPanel = AddSlider(oe.ctrlPanel, "Push", -10, 10, 0, 1);
+    pushPanel = AddSlider(oe.ctrlPanel, "Push", -1, 1, copy.NORMALPUSH, 1.1); // To have the buttons
     normalpushField = (cNumberSlider)pushPanel.getComponent(1);
     //Return();
 
@@ -3007,6 +3010,10 @@
         {
             copy.live ^= true;
             return;
+        } else if (event.getSource() == selectCB)
+        {
+            copy.dontselect ^= true;
+            return;
         } else if (event.getSource() == hideCB)
         {
             copy.hide ^= true;
@@ -3588,7 +3595,7 @@
         }
         
         if (normalpushField != null)
-                copy.NORMALPUSH = (float)normalpushField.getFloat()/1000;
+                copy.NORMALPUSH = (float)normalpushField.getFloat()/100;
     }
 
         void SnapObject()
diff --git a/Object3D.java b/Object3D.java
index 9c74924..56b46d5 100644
--- a/Object3D.java
+++ b/Object3D.java
@@ -300,6 +300,7 @@
         }
         
     boolean live = false;
+    boolean dontselect = false;
     boolean hide = false;
     boolean link2master = false; // performs reset support/master at each frame
     boolean marked = false; // animation node
@@ -1834,12 +1835,15 @@
             if (obj.name == null)
                 continue; // can't be a null one
             
+            // Try perfect match first.
             if (n.equals(obj.name))
             {
                 theobj = obj;
                 count++;
             }
         }
+        
+        // not needed: n = n.split(":")[0]; // Poser generates a count
         
     if (count != 1)
         for (int i=Size(); --i>=0;)
@@ -3002,8 +3006,10 @@
                     v.fromParent = LA.newMatrix();
                 }
 
-                LA.matConcat(v.toParent, toParent, v.toParent);
-                LA.matConcat(fromParent, v.fromParent, v.fromParent);
+//                LA.matConcat(v.toParent, toParent, v.toParent);
+//                LA.matConcat(fromParent, v.fromParent, v.fromParent);
+                LA.matConcat(toParent, v.toParent, v.toParent);
+                LA.matConcat(v.fromParent, fromParent, v.fromParent);
             }
 
             toParent = null; // LA.matIdentity(toParent);
@@ -3236,7 +3242,9 @@
         bRep.support = null;
         BoundaryRep temprep = (BoundaryRep) Grafreed.clone(bRep);
 //            bRep.SplitInTwo(onlyone); // thread...
-            temprep.SplitInTwo(reduction34, onlyone);
+        
+        while(temprep.SplitInTwo(reduction34, onlyone));
+        
             bRep = temprep;
             bRep.support = sup;
             Touch();
@@ -4711,7 +4719,7 @@
 
     cTreePath SelectLeaf(int indexcount, boolean deselect)
     {
-        if (hide)
+        if (hide || dontselect)
             return null;
         
         if (count <= 0)
@@ -4737,7 +4745,7 @@
     
     cTreePath Select(int indexcount, boolean deselect)
     {
-        if (hide)
+        if (hide || dontselect)
             return null;
             
         if (count <= 0)
@@ -5407,7 +5415,7 @@
     boolean NeedSupport()
     {
         return
-                CameraPane.SUPPORT && !CameraPane.movingcamera && link2master && /*live &&*/ support != null
+                CameraPane.SUPPORT && (!CameraPane.movingcamera || !Globals.FREEZEONMOVE) && link2master && /*live &&*/ support != null
                  // PROBLEM with CROWD!!
                     && (Globals.DrawMode() == iCameraPane.SHADOW || !Globals.RENDERSHADOW || Globals.CROWD);
     }
@@ -5424,7 +5432,7 @@
         }
         
         if (display.DrawMode() == iCameraPane.SELECTION &&
-                hide)
+                (hide || dontselect))
             return;
 
         if (name != null && name.contains("sclera"))
@@ -5666,7 +5674,17 @@
         tex = GetTextures();
     }
 
-    display.BindTextures(tex, texres);
+    boolean failed = false;
+    
+    try
+    {
+        display.BindTextures(tex, texres);
+    }
+    catch (Exception e)
+    {
+        System.err.println("FAILED: " + this);
+        failed = true;
+    }
            
             if (!compiled)
             {
@@ -5688,7 +5706,8 @@
                 }
             }
 
-    display.ReleaseTextures(tex);
+    if (!failed)
+        display.ReleaseTextures(tex);
 
     display.PopMaterial(this, selected);
         }
@@ -5817,6 +5836,9 @@
     
     void drawSelf(iCameraPane display, Object3D /*Composite*/ root, boolean selected, boolean blocked)
     {
+        if (display.DrawMode() == iCameraPane.SELECTION && dontselect)
+            return;
+        
         if (hide)
             return;
         // shadow optimisation
@@ -5942,6 +5964,9 @@
         if (display.DrawMode() == display.SHADOW && projectedVertices != null && projectedVertices.length > 2 && projectedVertices[2].y >= 10000)
             return; // no shadow for transparent objects
         
+        if (display.DrawMode() == iCameraPane.SELECTION && dontselect)
+            return;
+        
         if (hide)
             return;
         
diff --git a/Vertex.java b/Vertex.java
index e8cdcec..9714028 100644
--- a/Vertex.java
+++ b/Vertex.java
@@ -112,7 +112,6 @@
     {
         //if (normalmode) // pos == null)
         //	return 0;
-
         if (norm == null || !normalmode)
         {
             return /*pos.*/ super.hashCode();
@@ -129,12 +128,26 @@
         Vertex vert = (Vertex) o;
 
         //System.out.println("pos = " + pos + "; vert.pos = " + vert/*.pos*/);
+        
+        double tolerance = 0.00001;
+        
+        if (!Grafreed.epsequal)
+            tolerance = 0;
 
-        return Math.abs(/*pos.*/x - vert./*pos.*/x) +
-                Math.abs(/*pos.*/y - vert./*pos.*/y) +
-                Math.abs(/*pos.*/z - vert./*pos.*/z) < 0.00001 && // GrafreeD.epsvertex2 && // WARNING: USE 0.0001 for serial issues
-                (Grafreed.linkUV || Math.abs(s - vert.s) + Math.abs(t - vert.t) < 0.00001)
-                ; // GrafreeD.epsvertex2;
+        boolean samepos = Math.abs(/*pos.*/x - vert./*pos.*/x) +
+                          Math.abs(/*pos.*/y - vert./*pos.*/y) +
+                          Math.abs(/*pos.*/z - vert./*pos.*/z) <= tolerance && // GrafreeD.epsvertex2 && // WARNING: USE 0.0001 for serial issues
+                          (Grafreed.linkUV || Math.abs(s - vert.s) + Math.abs(t - vert.t) <= tolerance)
+                        ; // GrafreeD.epsvertex2;
+        
+        if (samepos && Grafreed.smoothmode)
+        {
+            norm.add(vert.norm);
+            norm.normalize();
+            vert.norm.set(norm);
+        }
+        
+        return samepos;
     }
     /*
     public boolean isSame(Object o)
diff --git a/cVector.java b/cVector.java
index 0517b70..bc50fbe 100644
--- a/cVector.java
+++ b/cVector.java
@@ -63,6 +63,15 @@
         }
     }
 
+    cVector ToFloat()
+    {
+        x = (float)x;
+        y = (float)y;
+        z = (float)z;
+        
+        return this;
+    }
+    
     void set(cVector v)
     {
         x = v.x;
@@ -247,18 +256,21 @@
         return "[" + x0 + ", " + y0 + ", " + z0 + "]";
     }
 
-    /*
     public boolean equals(Object o)
     {
         //if (true) return false;
 
         cVector vert = (cVector) o;
         
+        double tolerance = 0.00001;
+        
+        if (!Grafreed.epsequal)
+            tolerance = 0;
+
         return Math.abs(x - vert.x) +
                 Math.abs(y - vert.y) +
-                Math.abs(z - vert.z) < 0.01;
+                Math.abs(z - vert.z) <= tolerance;
     }
-     */
     
     public int hashCode()
     {
diff --git a/iCameraPane.java b/iCameraPane.java
index 866cbe7..ccb0763 100644
--- a/iCameraPane.java
+++ b/iCameraPane.java
@@ -55,7 +55,7 @@
     
     void DrawString(Object3D obj);
     
-    void BindTextures(cTexture tex, int resolution);
+    void BindTextures(cTexture tex, int resolution) throws Exception;
     void ReleaseTextures(cTexture tex);
     
     void DrawFace(Object3D obj, Vertex pv, Vertex qv, Vertex rv, Face face);
@@ -82,7 +82,7 @@
     
     void setCursor(java.awt.Cursor cursor);
     
-    com.sun.opengl.util.texture.TextureData GetTextureData(String tex, boolean bump, int resolution);
+    com.sun.opengl.util.texture.TextureData GetTextureData(String tex, boolean bump, int resolution) throws Exception;
             
     void repaint();
     

--
Gitblit v1.6.2