From 6ed65dcb597fb2153cef75bf1845978f1115658c Mon Sep 17 00:00:00 2001
From: Normand Briere <nbriere@noware.ca>
Date: Fri, 14 Dec 2018 22:53:55 -0500
Subject: [PATCH] Repair shadow, normal push + attractor mesh.

---
 ObjEditor.java     |   40 ++
 Texture.java       |    2 
 NumberSlider.java  |    1 
 Mocap.java         |  156 +++++++-----
 BiparamEditor.java |    4 
 FileObject.java    |   11 
 ScriptNode.java    |    8 
 BoundaryRep.java   |    2 
 CameraPane.java    |   92 ++++--
 cSpringEditor.java |   10 
 GroupEditor.java   |   17 +
 cSpring.java       |  231 +++++++++++++-----
 Object3D.java      |  106 +++++++-
 13 files changed, 469 insertions(+), 211 deletions(-)

diff --git a/BiparamEditor.java b/BiparamEditor.java
index 6fde80f..c04a299 100644
--- a/BiparamEditor.java
+++ b/BiparamEditor.java
@@ -68,7 +68,7 @@
                 
             uDivsField = AddSlider(oe.ctrlPanel, "U #", biparam.minUDivs, 250+biparam.minUDivs, biparam.uDivs);
             Return();
-            vDivsField = AddSlider(oe.ctrlPanel, "V #", biparam.minVDivs, (int)(250/6.28)+biparam.minVDivs, biparam.vDivs);
+            vDivsField = AddSlider(oe.ctrlPanel, "V #", biparam.minVDivs, (int)(500/3.14)+biparam.minVDivs, biparam.vDivs);
             Return();
 //		oe.aConstraints.gridwidth = 1;
 //		oe.aConstraints.fill = GridBagConstraints.VERTICAL;
@@ -205,7 +205,7 @@
     public void applySelf()
     {
 		//System.out.println("Biparam :: applySelf");
-        //super.applySelf();
+        super.applySelf();
         int udivs = uDivsField.getInteger(); // biparam.minUDivs, 99);
         int vdivs = vDivsField.getInteger(); // biparam.minUDivs, 99);
         //biparam.name = nameField.getText();
diff --git a/BoundaryRep.java b/BoundaryRep.java
index 3a1d080..d786a91 100644
--- a/BoundaryRep.java
+++ b/BoundaryRep.java
@@ -4948,7 +4948,7 @@
             {
                 Vertex v = GetVertex(i);
                 
-                if (v.norm.x == 0 && v.norm.y == 0 && v.norm.z == 0)
+                if (v.norm == null || v.norm.x == 0 && v.norm.y == 0 && v.norm.z == 0)
                     continue;
 
                 from.set(v.x, v.y, v.z);
diff --git a/CameraPane.java b/CameraPane.java
index f2d438e..a5a5ed5 100644
--- a/CameraPane.java
+++ b/CameraPane.java
@@ -7444,6 +7444,8 @@
             //gl.glFrustum(-0.5*scale, 0.5*scale, -0.5*scale, 0.5*scale, 1, 100);
             //glu.gluPerspective(lightshaper_fovy, 1, lightshaper_zNear, lightshaper_zFar);
             double scale = lightCamera.SCALE / lightCamera.Distance();
+// PATCH FILLE AUX JEANS           
+            //scale *= lightCamera.shaper_fovy / 25;
             gl.glScaled(2 * scale, 2 * scale, -scale);
             gl.glTranslated(0, 0, lightCamera.DECAL);
 
@@ -9092,6 +9094,8 @@
             //gl.glFrustum(-0.5*scale, 0.5*scale, -0.5*scale, 0.5*scale, 1, 100);
             //glu.gluPerspective(lightshaper_fovy, 1, lightshaper_zNear, lightshaper_zFar);
             double scale = lightCamera.SCALE / lightCamera.Distance();
+// PATCH FILLE AUX JEANS           
+            //scale *= lightCamera.shaper_fovy / 25;
             gl.glScaled(2 * scale, 2 * scale, -scale);
             gl.glTranslated(0, 0, lightCamera.DECAL);
 
@@ -9231,6 +9235,8 @@
         {
             //glu.gluPerspective(lightshaper_fovy, 1, lightshaper_zNear, lightshaper_zFar);
             double scale = lightCamera.SCALE / lightCamera.Distance();
+// PATCH FILLE AUX JEANS            
+            //scale *= lightCamera.shaper_fovy / 25;
             gl.glScaled(2 * scale, 2 * scale, -scale);
             gl.glTranslated(0, 0, lightCamera.DECAL);
         //System.out.println("DECAL = " + LIGHTDECAL + "; SCALE = " + LIGHTSCALE);
@@ -9754,40 +9760,40 @@
                         selectedpoint.radius = radius;
                         selectedpoint.recalculate();
                         selectedpoint.material = new cMaterial();
-                        selectedpoint.material.color = 0.15f;
+                        selectedpoint.material.color = 0.15f; // Yellow
                         selectedpoint.material.modulation = 0.75f;
                         
-                        debugpoint.radius = radius;
-                        debugpoint.recalculate();
-                        debugpoint.material = new cMaterial();
-                        debugpoint.material.color = 0.25f;
-                        debugpoint.material.modulation = 0.75f;
+                        debugpointG.radius = radius;
+                        debugpointG.recalculate();
+                        debugpointG.material = new cMaterial();
+                        debugpointG.material.color = 0.25f; // Green
+                        debugpointG.material.modulation = 0.75f;
                         
-                        debugpoint2.radius = radius;
-                        debugpoint2.recalculate();
-                        debugpoint2.material = new cMaterial();
-                        debugpoint2.material.color = 0.75f;
-                        debugpoint2.material.modulation = 0.75f;
+                        debugpointP.radius = radius;
+                        debugpointP.recalculate();
+                        debugpointP.material = new cMaterial();
+                        debugpointP.material.color = 0.75f; // Purple
+                        debugpointP.material.modulation = 0.75f;
                         
-                        debugpoint3.radius = radius;
-                        debugpoint3.recalculate();
-                        debugpoint3.material = new cMaterial();
-                        debugpoint3.material.color = 0.5f;
-                        debugpoint3.material.modulation = 0.75f;
+                        debugpointC.radius = radius;
+                        debugpointC.recalculate();
+                        debugpointC.material = new cMaterial();
+                        debugpointC.material.color = 0.5f; // Cyan
+                        debugpointC.material.modulation = 0.75f;
                         
-                        debugpoint4.radius = radius;
-                        debugpoint4.recalculate();
-                        debugpoint4.material = new cMaterial();
-                        debugpoint4.material.color = 0f;
-                        debugpoint4.material.modulation = 0.75f;
+                        debugpointR.radius = radius;
+                        debugpointR.recalculate();
+                        debugpointR.material = new cMaterial();
+                        debugpointR.material.color = 0f; // Red
+                        debugpointR.material.modulation = 0.75f;
                         
                         InitPoints(radius);
                     }
                     selectedpoint.draw(this, /*(Composite)*/ null, false, false);
-                    debugpoint.draw(this, /*(Composite)*/ null, false,false);
-                    debugpoint2.draw(this, /*(Composite)*/ null, false,false);
-                    debugpoint3.draw(this, /*(Composite)*/ null, false,false);
-                    debugpoint4.draw(this, /*(Composite)*/ null, false,false);
+                    debugpointG.draw(this, /*(Composite)*/ null, false,false);
+                    debugpointP.draw(this, /*(Composite)*/ null, false,false);
+                    debugpointC.draw(this, /*(Composite)*/ null, false,false);
+                    debugpointR.draw(this, /*(Composite)*/ null, false,false);
                     // DrawPoints(this);
                 }
                 
@@ -9825,12 +9831,14 @@
 
             if (checker != null && drawMode == DEFAULT)
             {
-               // BindTexture(IMMORTAL_TEXTURE);
+                //BindTexture(IMMORTAL_TEXTURE);
+                BindTextures(checker.GetTextures(), checker.texres);
                 // NEAREST
                 GetGL().glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); // GL.GL_LINEAR);
                 DrawChecker(gl);
                 //checker.Draw(this, null, false);
               //  ReleaseTexture(IMMORTAL_TEXTURE);
+                ReleaseTextures(checker.GetTextures());
             }
 
             if (object.parent != null)
@@ -10388,6 +10396,7 @@
                 "PARAM lodbias = { 10,10,10,10 };" + // 20, -2, -20, 1.0 };" +
                 "PARAM infinity  = { 100000000, 100000000, 100000000, 1.0 };" +
                 "PARAM one2048th = { 0.00048828125, 0.00048828125, 0.00048828125, 1.0 };" +
+                "PARAM ninetenth = { 0.9, 0.9, 0.9, 1.0 };" +
                 "PARAM almostone = { 0.999, 0.999, 0.999, 1.0 };" +
                 "PARAM c256 = { 256, 256, 256, 1.0 };" +
                 "PARAM c256i = { 0.00390625, 0.00390625, 0.00390625, 1.0 };" +
@@ -11302,6 +11311,7 @@
     String Shadow(String depth, String shadow)
     {
         return "MAX temp.x, ndotl.x, one64th.x;" +
+               "MIN temp.x, temp.x, ninetenth.x;" +
                 /**/
                 // Sine
                 "MUL temp.y, temp.x, temp.x;" +
@@ -14438,7 +14448,7 @@
         gl.glPushAttrib(GL.GL_ALL_ATTRIB_BITS);
         gl.glPushMatrix();
         gl.glLoadIdentity();
-        PushMatrix(checker.toParent);
+        //PushMatrix(checker.toParent);
 
         gl.glMatrixMode(GL.GL_TEXTURE);
         gl.glPushMatrix();
@@ -14461,8 +14471,8 @@
 
         gl.glNormal3f(0.0f, 0.0f, 1.0f);
             
-        float step = 0.1666f; //0.25f;
-        float stepv = step * 1652 / 998;
+        float step = 2; // 0.1666f; //0.25f;
+        float stepv = 2; // step * 1652 / 998;
 
         int i0 = 0;
         /*
@@ -14532,15 +14542,27 @@
 
                 //float u = (i+1)/2;
                 //float v = (j+1)/2;
-                gl.glTexCoord2f((i + 1) / 2, (j + 1) / 2); // (1,0) // (i+1+step)/2,(j+1)/2);
+                if (checker.flipV)
+                        gl.glTexCoord2f((i + 1) / 2, 1 - (j + 1) / 2);
+                else
+                        gl.glTexCoord2f((i + 1) / 2, (j + 1) / 2); // (1,0) // (i+1+step)/2,(j+1)/2);
                 gl.glVertex3f(i, j, -0.5f);
 
+                if (checker.flipV)
+                gl.glTexCoord2f((i + 1 + step) / 2, 1 - (j + 1) / 2); // (1,1) // (i+1+step)/2,(j+1+step)/2);
+                else
                 gl.glTexCoord2f((i + 1 + step) / 2, (j + 1) / 2); // (1,1) // (i+1+step)/2,(j+1+step)/2);
                 gl.glVertex3f(i + step, j, -0.5f);
 
+                if (checker.flipV)
+                gl.glTexCoord2f((i + 1 + step) / 2, 1 - (j + 1 + stepv) / 2); // (0,1) //(i+1)/2,(j+1+step)/2);
+                else
                 gl.glTexCoord2f((i + 1 + step) / 2, (j + 1 + stepv) / 2); // (0,1) //(i+1)/2,(j+1+step)/2);
                 gl.glVertex3f(i + step, j + stepv, -0.5f);
 
+                if (checker.flipV)
+                gl.glTexCoord2f((i + 1) / 2, 1 - (j + 1 + stepv) / 2); // (0,0) //(i+1)/2,(j+1)/2);
+                else
                 gl.glTexCoord2f((i + 1) / 2, (j + 1 + stepv) / 2); // (0,0) //(i+1)/2,(j+1)/2);
                 gl.glVertex3f(i, j + stepv, -0.5f);
             }
@@ -14552,7 +14574,7 @@
         gl.glMatrixMode(GL.GL_PROJECTION);
         gl.glPopMatrix();
         gl.glMatrixMode(GL.GL_MODELVIEW);
-        PopMatrix(null); // checker.toParent); // null);
+        //PopMatrix(null); // checker.toParent); // null);
         gl.glPopMatrix();
         PopTextureMatrix(checker.toParent);
         gl.glMatrixMode(GL.GL_TEXTURE);
@@ -15370,10 +15392,10 @@
     //double[] selectedpoint = new double[3];
     static Superellipsoid selectedpoint = new Superellipsoid();
     static Sphere previousselectedpoint = null;
-    static Sphere debugpoint = new Sphere();
-    static Sphere debugpoint2 = new Sphere();
-    static Sphere debugpoint3 = new Sphere();
-    static Sphere debugpoint4 = new Sphere();
+    static Sphere debugpointG = new Sphere();
+    static Sphere debugpointP = new Sphere();
+    static Sphere debugpointC = new Sphere();
+    static Sphere debugpointR = new Sphere();
     
     static Sphere debugpoints[] = new Sphere[8];
  
diff --git a/FileObject.java b/FileObject.java
index e41d012..6de2b2c 100644
--- a/FileObject.java
+++ b/FileObject.java
@@ -22,10 +22,10 @@
         return false; // ???? false;
     }
     
-    void Reset()
-    {
-    //    filecontent = null;
-    }
+//    void Reset()
+//    {
+//    //    filecontent = null;
+//    }
     
     void ClearUI()
     {
@@ -54,9 +54,12 @@
             else
             {
                 filecontent = ObjEditor.ReadGFD/*z*/(name);
+                if (filecontent != null)
+                {
                 filecontent.parent = null;
                 filecontent.fileparent = this;
                 filecontent.RepairTexture();
+                }
                 // stripify on load instead?
           // OK...
           //      filecontent.Stripify(); // fine. faster and read-only anyway
diff --git a/GroupEditor.java b/GroupEditor.java
index 48fcf23..da3ecc4 100644
--- a/GroupEditor.java
+++ b/GroupEditor.java
@@ -1120,6 +1120,8 @@
 		resetParentItem.addActionListener(this);
 		repairParentItem = menu.add(new MenuItem("Repair Parent"));
 		repairParentItem.addActionListener(this);
+		repairShadowItem = menu.add(new MenuItem("Repair Shadow"));
+		repairShadowItem.addActionListener(this);
 		menu.add(invariantsItem = new MenuItem("Invariants"));
 		invariantsItem.addActionListener(this);
 		menu.add(recompileItem = new MenuItem("Recompile"));
@@ -2537,6 +2539,20 @@
 			{
 				Object3D obj = (Object3D)e.nextElement();
                                 obj.RepairParent();
+//                                for (int i=0; i<obj.size(); i++)
+//                                {
+//                                    obj.get(i).parent = obj;
+//                                }
+			}
+			
+			refreshContents();
+		} else
+		if (event.getSource() == repairShadowItem)
+		{
+			for (Enumeration e = group.selection.elements(); e.hasMoreElements();)
+			{
+				Object3D obj = (Object3D)e.nextElement();
+                                obj.RepairShadow();
 //                                for (int i=0; i<obj.size(); i++)
 //                                {
 //                                    obj.get(i).parent = obj;
@@ -5009,6 +5025,7 @@
         
 	private MenuItem resetParentItem;
 	private MenuItem repairParentItem;
+	private MenuItem repairShadowItem;
 	private MenuItem sortbysizeItem;
 	private MenuItem sortbynameItem;
         
diff --git a/Mocap.java b/Mocap.java
index 172ab78..f451172 100644
--- a/Mocap.java
+++ b/Mocap.java
@@ -261,9 +261,9 @@
         
 //    LA.matConcat(toParent, hip.get(0).toParent, toParent);
         
-        CameraPane.debugpoint.toParent[3][0] = poship.x;
-        CameraPane.debugpoint.toParent[3][1] = poship.y;
-        CameraPane.debugpoint.toParent[3][2] = poship.z;        
+        CameraPane.debugpointG.toParent[3][0] = poship.x;
+        CameraPane.debugpointG.toParent[3][1] = poship.y;
+        CameraPane.debugpointG.toParent[3][2] = poship.z;        
         
         LA.matInvert(toParent, fromParent);
         
@@ -324,21 +324,21 @@
 //        LA.matYRotate(toParent, angleY - angleYhip);
 //        LA.matTranslate(toParent, pos.x - poship.x, pos.y - poship.y, pos.z - poship.z);
         
-        CameraPane.debugpoint2.toParent[3][0] = pos.x;
-        CameraPane.debugpoint2.toParent[3][1] = pos.y;
-        CameraPane.debugpoint2.toParent[3][2] = pos.z;        
+        CameraPane.debugpointP.toParent[3][0] = pos.x;
+        CameraPane.debugpointP.toParent[3][1] = pos.y;
+        CameraPane.debugpointP.toParent[3][2] = pos.z;        
         
-        CameraPane.debugpoint3.toParent[3][0] = poship.x;
-        CameraPane.debugpoint3.toParent[3][1] = poship.y;
-        CameraPane.debugpoint3.toParent[3][2] = poship.z;        
+        CameraPane.debugpointC.toParent[3][0] = poship.x;
+        CameraPane.debugpointC.toParent[3][1] = poship.y;
+        CameraPane.debugpointC.toParent[3][2] = poship.z;        
         
         poship.x = toParent[3][0];
         poship.y = toParent[3][1];
         poship.z = toParent[3][2];
         
-        CameraPane.debugpoint4.toParent[3][0] = poship.x;
-        CameraPane.debugpoint4.toParent[3][1] = poship.y;
-        CameraPane.debugpoint4.toParent[3][2] = poship.z;        
+        CameraPane.debugpointR.toParent[3][0] = poship.x;
+        CameraPane.debugpointR.toParent[3][1] = poship.y;
+        CameraPane.debugpointR.toParent[3][2] = poship.z;        
         
         LA.matInvert(toParent, fromParent);
     }
@@ -477,29 +477,45 @@
         }
     }
 
+    static cVector centroid = new cVector();
+    static cVector mocaporigin = new cVector();
+        
     void SetHipOrientation()
     {
         Object3D hip = get(0);
         
         LA.matConcat(toParent, hip.get(0).toParent, matrix);
         
-        cVector centroid = new cVector();
+        mocaporigin.x = matrix[3][0];
+        mocaporigin.y = matrix[3][1];
+        mocaporigin.z = matrix[3][2];
+        
         centroid.x = matrix[3][0];
         centroid.y = matrix[3][1];
         centroid.z = matrix[3][2];
-        this.getCentroid(centroid, true);
+//        this.getCentroid(centroid, true);
+        
+        CameraPane.debugpointG.name = "";
+        CameraPane.debugpointG.toParent[3][0] = mocaporigin.x;
+        CameraPane.debugpointG.toParent[3][1] = mocaporigin.y;
+        CameraPane.debugpointG.toParent[3][2] = mocaporigin.z;
+        
+        CameraPane.debugpointP.name = "";
+        CameraPane.debugpointP.toParent[3][0] = centroid.x;
+        CameraPane.debugpointP.toParent[3][1] = centroid.y;
+        CameraPane.debugpointP.toParent[3][2] = centroid.z;
         
         cVector goal = GetGoal(centroid);
         if (goal != null)
         {
-            System.err.println("GOAL change (" + this + "): " + goal + " (was " + goalx + ", " + goalz + ")");
+            System.err.println("GOAL change (" + this + "): " + goal + " (was " + goalposx + ", " + goalposz + ")");
 
-            goalx = goal.x;
-            goalz = goal.z;
-            targetx = targetz = 0;
+            goalposx = goal.x;
+            goalposz = goal.z;
+            targetdirx = targetdirz = 0;
         }
         
-        if (goalx == 0 && goalz == 0)
+        if (goalposx == 0 && goalposz == 0)
         {
             // No target
             if (ScriptNode.speaker != null)
@@ -533,8 +549,8 @@
                 //sourcenode.parent.TransformToLocal(dst);
                 this.parent.TransformToLocal(dst);
                 
-                goalx = dst.x;
-                goalz = dst.z;
+                goalposx = dst.x;
+                goalposz = dst.z;
             }
             else
                 return;
@@ -550,17 +566,25 @@
 
         double angleYhip = Math.atan2(-temp.z, temp.x);
         
-        double angleYtarget = Math.atan2(goalx - centroid.x, goalz - centroid.z);
+        double angleYtarget = Math.atan2(goalposx - centroid.x, goalposz - centroid.z);
 
         LA.matIdentity(matrix);
         LA.matTranslate(matrix, -centroid.x, -centroid.y, -centroid.z);
-        double angle = CurveAngle(0, angleYtarget - angleYhip, 1); // 0.1f);
+        double angle = CurveAngle(0, angleYtarget - angleYhip, 0.1f);
         LA.matYRotate(matrix, angle);
         LA.matTranslate(matrix, centroid.x, centroid.y, centroid.z);
 
         LA.matConcat(matrix, toParent, toParent);
         
         LA.matInvert(toParent, fromParent);
+        
+        LA.matConcat(toParent, hip.get(0).toParent, matrix);
+        
+        centroid.x = matrix[3][0];
+        centroid.y = matrix[3][1];
+        centroid.z = matrix[3][2];
+        
+        double dist = LA.distance(centroid, mocaporigin);
         
         CheckForAction(centroid);
     }
@@ -637,11 +661,11 @@
     double pinx;
     double pinz;
     
-    double targetx;
-    double targetz;
+    double targetdirx;
+    double targetdirz;
     
-    double goalx = -20;
-    double goalz = -10;
+    double goalposx = -20;
+    double goalposz = -10;
     
     boolean followpath;
     
@@ -712,7 +736,7 @@
             scriptactions.clear();
     }
     
-    static double EPSACTION = 0.1; // 0.075; //  0.1;
+    static double EPSACTION = 0.1; // 0.075; //  0.1;Came
     
     void AddFromTo(cVector from, cVector to)
     {
@@ -1278,6 +1302,7 @@
     
     void SetPosition(Object3D sourcenode, cVector floor, long floorid, cVector centroid)
     {
+            assert(false);
         //assert(CameraPane.drawMode == CameraPane.SHADOW);
         
         Object3D transformnode = new Object3D();
@@ -1481,9 +1506,9 @@
                 groundid = floorid;
                 
                 // green
-                CameraPane.debugpoint.toParent[3][0] = groundx;
-                CameraPane.debugpoint.toParent[3][1] = floor.y;
-                CameraPane.debugpoint.toParent[3][2] = groundz;
+                CameraPane.debugpointG.toParent[3][0] = groundx;
+                CameraPane.debugpointG.toParent[3][1] = floor.y;
+                CameraPane.debugpointG.toParent[3][2] = groundz;
                 
                 if (true) // slow && stepout && onein)
                 {
@@ -1560,9 +1585,9 @@
             
        //     System.out.println("Allo " + sourcenode);
             // purple
-                CameraPane.debugpoint2.toParent[3][0] = floor.x;// + posx;
-                CameraPane.debugpoint2.toParent[3][1] = ground; // floor.y;// + sourcenode.parent.toParent[3][1];
-                CameraPane.debugpoint2.toParent[3][2] = floor.z;// + posz;
+                CameraPane.debugpointP.toParent[3][0] = floor.x;// + posx;
+                CameraPane.debugpointP.toParent[3][1] = ground; // floor.y;// + sourcenode.parent.toParent[3][1];
+                CameraPane.debugpointP.toParent[3][2] = floor.z;// + posz;
                 
             
             if (false) // dist2 > 0.1)
@@ -1628,9 +1653,9 @@
             this.get(0).TransformToWorld(v0);
         
         // cyan
-        CameraPane.debugpoint3.toParent[3][0] = v0.x;
-        CameraPane.debugpoint3.toParent[3][1] = ground;
-        CameraPane.debugpoint3.toParent[3][2] = v0.z;
+        CameraPane.debugpointC.toParent[3][0] = v0.x;
+        CameraPane.debugpointC.toParent[3][1] = ground;
+        CameraPane.debugpointC.toParent[3][2] = v0.z;
         
             LA.matConcat(sourcenode.toParent, transformnode.toParent, sourcenode.toParent);
             LA.matInvert(sourcenode.toParent, sourcenode.fromParent);
@@ -1640,9 +1665,9 @@
             this.get(0).TransformToWorld(v0);
             
         // red
-        CameraPane.debugpoint4.toParent[3][0] = v0.x;
-        CameraPane.debugpoint4.toParent[3][1] = ground;
-        CameraPane.debugpoint4.toParent[3][2] = v0.z;
+        CameraPane.debugpointR.toParent[3][0] = v0.x;
+        CameraPane.debugpointR.toParent[3][1] = ground;
+        CameraPane.debugpointR.toParent[3][2] = v0.z;
         }
     }
     
@@ -1682,11 +1707,11 @@
         
         if (goal != null)
         {
-            System.err.println("GOAL change (" + sourcenode + "): " + goal + " (was " + goalx + ", " + goalz + ")");
+            System.err.println("GOAL change (" + sourcenode + "): " + goal + " (was " + goalposx + ", " + goalposz + ")");
             //sourcenode.parent.parent.Dump();
-            goalx = goal.x;
-            goalz = goal.z;
-            targetx = targetz = 0;
+            goalposx = goal.x;
+            goalposz = goal.z;
+            targetdirx = targetdirz = 0;
             
             followpath = true;
         }
@@ -1737,16 +1762,16 @@
 //        }
             if (false) // !uselast)
             {
-                CameraPane.debugpoint.toParent[3][0] = dst.x;
-                CameraPane.debugpoint.toParent[3][1] = dst.y;
-                CameraPane.debugpoint.toParent[3][2] = dst.z;
+                CameraPane.debugpointG.toParent[3][0] = dst.x;
+                CameraPane.debugpointG.toParent[3][1] = dst.y;
+                CameraPane.debugpointG.toParent[3][2] = dst.z;
             }
         }
         
-        if (goalx != 0 || goalz != 0) // TODO
+        if (goalposx != 0 || goalposz != 0) // TODO
         {
             // overwrite speaker orientation
-            dst.set(goalx,0,goalz);
+            dst.set(goalposx,0,goalposz);
             if (sourcenode.parent != null) // july 2014
           sourcenode.parent.
                   TransformToLocal(dst);
@@ -1798,26 +1823,26 @@
         // mars 2014
         if (false) // goalx != 0 || goalz != 0)
         {
-            targetx = dst.x - src.x;
-            targetz = dst.z - src.z;
+            targetdirx = dst.x - src.x;
+            targetdirz = dst.z - src.z;
             
-            if (Math.abs(targetx) > 0.1 || Math.abs(targetz) > 0.1)
+            if (Math.abs(targetdirx) > 0.1 || Math.abs(targetdirz) > 0.1)
             {
                 // far enough from goal. keep the goal position.
-                targetx = 0;
-                targetz = 0;
+                targetdirx = 0;
+                targetdirz = 0;
             }
             else
             {
                 // too close to goal. switch to target direction instead.
-                goalx = 0;
-                goalz = 0;
+                goalposx = 0;
+                goalposz = 0;
             }
         }
         
         //sourcenode.getCentroid(src, true);
 
-        if (speakernode == sourcenode && goalx == 0 && goalz == 0)
+        if (speakernode == sourcenode && goalposx == 0 && goalposz == 0)
         {
             if (ScriptNode.lastspeaker != null)
                 new Exception().printStackTrace();
@@ -1826,13 +1851,13 @@
 
     //    LA.xformPos(src, fromParent, src);
 
-        if ((ScriptNode.speaker != null && CameraPane.SPEAKERMOCAP || goalx != 0 || goalz != 0) && targetx == 0 && targetz == 0)
+        if ((ScriptNode.speaker != null && CameraPane.SPEAKERMOCAP || goalposx != 0 || goalposz != 0) && targetdirx == 0 && targetdirz == 0)
             dst.sub(src);
         else
             // vector mode
         {
-            dst.x = targetx;
-            dst.z = targetz;
+            dst.x = targetdirx;
+            dst.z = targetdirz;
             
             // TEST TARGET
     //        dst.x = CameraPane.selectedpoint.toParent[3][0];
@@ -2280,9 +2305,16 @@
             toVector.x = LA.cos(to);
             toVector.y = LA.sin(to);
 
+            double fromA = Math.atan2(fromVector.y, fromVector.x);
+            double toA = Math.atan2(toVector.y, toVector.x);
+            
             Vector2d currentVector = Slerp(fromVector, toVector, step);
 
-            return Math.atan2(currentVector.y, currentVector.x);
+            double angle = Math.atan2(currentVector.y, currentVector.x);
+            
+            double angle2 = (1-step) * fromA + step * toA;
+            
+            return angle;
         }
 
         public static Vector2d Slerp(Vector2d from, Vector2d to, double step)
@@ -3191,7 +3223,7 @@
 
         // july 2014
 //        goalx = goalz = 0;
-        targetx = targetz = 0;
+        targetdirx = targetdirz = 0;
         
         //SetPositionDelta(true, true, true, false);
 //        LoadData();
diff --git a/NumberSlider.java b/NumberSlider.java
index 25db748..5c7135a 100644
--- a/NumberSlider.java
+++ b/NumberSlider.java
@@ -102,6 +102,7 @@
 
         if (pow <= 0)
         {
+                // Transition between min and max
                 // value = (Math.pow(getValue()/1000.0, POW) * (max - min)) + min;
                 // value - min = Math.pow(getValue()/1000.0, POW) * (max - min);
                 // (value - min) / (max - min) = Math.pow(getValue()/1000.0, POW);
diff --git a/ObjEditor.java b/ObjEditor.java
index a0dc1a7..f7c8293 100644
--- a/ObjEditor.java
+++ b/ObjEditor.java
@@ -160,12 +160,16 @@
         objEditor.ctrlPanel.remove(slowerButton);
         objEditor.ctrlPanel.remove(fasterButton);
         objEditor.ctrlPanel.remove(remarkButton);
+        
+        Remove(normalpushField);
     }
 
     public ObjEditor GetEditor()
     {
         return objEditor; //.GetEditor();
     }
+    
+    // Sometimes myself, sometimes my callee's.
     ObjEditor objEditor;
 
     /*
@@ -814,7 +818,7 @@
 
         aConstraints.fill = GridBagConstraints.VERTICAL;
         jlabel.setHorizontalAlignment(SwingConstants.TRAILING);
-        aConstraints.gridwidth = 2;
+        aConstraints.gridwidth = 1;
         ctrlPanel.add(jlabel, aConstraints); //, oe.ctrlPanel.getComponentCount()-1);
         aConstraints.gridx += 1;
         aConstraints.fill = GridBagConstraints.HORIZONTAL;
@@ -983,6 +987,9 @@
 
         Return();
 
+    normalpushField = AddSlider(oe.ctrlPanel, "Push", -10, 10, 0, -1);
+    Return();
+            
 //	oe.ctrlPanel.add(stepButton = new cButton("Step"), ObjEditor.aConstraints, oe.ctrlPanel.getComponentCount() - 2);
 //        ObjEditor.aConstraints.gridx += 1;
 
@@ -1446,7 +1453,7 @@
         aConstraints.gridx += 1;
         aConstraints.gridwidth = ObjEditor.GRIDWIDTH;
         //aConstraints.weightx = 0;
-        ctrlPanel.add(colorField = new NumberSlider(0.001, 1, -0.1), aConstraints);
+        ctrlPanel.add(colorField = new NumberSlider(0.001, 1, -0.5), aConstraints);
         aConstraints.gridx = 0;
         aConstraints.gridy += 1;
         aConstraints.gridwidth = 1;
@@ -1456,7 +1463,7 @@
         aConstraints.fill = GridBagConstraints.HORIZONTAL;
         aConstraints.gridx += 1;
         aConstraints.gridwidth = ObjEditor.GRIDWIDTH;
-        ctrlPanel.add(modulationField = new NumberSlider(0.001, 1, -0.1), aConstraints);
+        ctrlPanel.add(modulationField = new NumberSlider(0.001, 1, -0.5), aConstraints);
         aConstraints.gridx = 0;
         aConstraints.gridy += 1;
         aConstraints.gridwidth = 1;
@@ -1466,7 +1473,7 @@
         aConstraints.fill = GridBagConstraints.HORIZONTAL;
         aConstraints.gridx += 1;
         aConstraints.gridwidth = ObjEditor.GRIDWIDTH;
-        ctrlPanel.add(textureField = new NumberSlider(0.001, 1, -0.1), aConstraints);
+        ctrlPanel.add(textureField = new NumberSlider(0.001, 1, -0.5), aConstraints);
         aConstraints.gridx = 0;
         aConstraints.gridy += 1;
         aConstraints.gridwidth = 1;
@@ -1476,7 +1483,7 @@
         aConstraints.fill = GridBagConstraints.HORIZONTAL;
         aConstraints.gridx += 1;
         aConstraints.gridwidth = ObjEditor.GRIDWIDTH;
-        ctrlPanel.add(anisoField = new NumberSlider(0.001, 1, -0.1), aConstraints);
+        ctrlPanel.add(anisoField = new NumberSlider(0.001, 1, -0.5), aConstraints);
         aConstraints.gridx = 0;
         aConstraints.gridy += 1;
         aConstraints.gridwidth = 1;
@@ -1486,7 +1493,7 @@
         aConstraints.fill = GridBagConstraints.HORIZONTAL;
         aConstraints.gridx += 1;
         aConstraints.gridwidth = ObjEditor.GRIDWIDTH;
-        ctrlPanel.add(anisoVField = new NumberSlider(0.001, 1, -0.1), aConstraints);
+        ctrlPanel.add(anisoVField = new NumberSlider(0.001, 1, -0.5), aConstraints);
         aConstraints.gridx = 0;
         aConstraints.gridy += 1;
         aConstraints.gridwidth = 1;
@@ -1555,7 +1562,7 @@
         aConstraints.fill = GridBagConstraints.HORIZONTAL;
         aConstraints.gridx += 1;
         aConstraints.gridwidth = ObjEditor.GRIDWIDTH;
-        ctrlPanel.add(subsurfaceField = new NumberSlider(0.001, 1, -0.1), aConstraints);
+        ctrlPanel.add(subsurfaceField = new NumberSlider(0.001, 1, -0.5), aConstraints);
         aConstraints.gridx = 0;
         aConstraints.gridy += 1;
         aConstraints.gridwidth = 1;
@@ -1624,7 +1631,7 @@
         aConstraints.fill = GridBagConstraints.HORIZONTAL;
         aConstraints.gridx += 1;
         aConstraints.gridwidth = ObjEditor.GRIDWIDTH;
-        ctrlPanel.add(metalnessField = new NumberSlider(0.001, 1, -0.1), aConstraints);
+        ctrlPanel.add(metalnessField = new NumberSlider(0.001, 1, -0.5), aConstraints);
         aConstraints.gridx = 0;
         aConstraints.gridy += 1;
         aConstraints.gridwidth = 1;
@@ -1695,7 +1702,7 @@
         aConstraints.fill = GridBagConstraints.HORIZONTAL;
         aConstraints.gridx += 1;
         aConstraints.gridwidth = ObjEditor.GRIDWIDTH;
-        ctrlPanel.add(opacityField = new NumberSlider(0.001, 1, -0.1), aConstraints);
+        ctrlPanel.add(opacityField = new NumberSlider(0.001, 1, -0.5), aConstraints);
         aConstraints.gridx = 0;
         aConstraints.gridy += 1;
         aConstraints.gridwidth = 1;
@@ -3549,7 +3556,13 @@
             //System.out.println("PARENT = " + parent);
             //if (parent != null)
             //	parent.applySelf();
-            refreshContents();
+		if (e.getSource() == normalpushField)
+		{
+			objEditor.refreshContents();
+			//Refresh();
+		}
+		else
+                    refreshContents();
             // ??? client.refreshEditWindow();
         }
         //else
@@ -3561,7 +3574,7 @@
         //group.name = nameField.getText();
         //objEditor.applySelf();
 
-        assert (objEditor == this);
+        // OCT2018: assert (objEditor == this);
         if (copy.selection == null || copy.selection.size() == 0)
 			//super.applySelf()
                                 ; else
@@ -3585,6 +3598,9 @@
                 objEditor.copy = keep;
             }
         }
+        
+        if (normalpushField != null)
+                copy.NORMALPUSH = (float)normalpushField.getFloat()/1000;
     }
 
         void SnapObject()
@@ -4629,4 +4645,6 @@
     NumberSlider opacityPowerField;
     JTree jTree;
     //ObjectUI parent;
+    
+    NumberSlider normalpushField;
 }
diff --git a/Object3D.java b/Object3D.java
index f6cf69b..8a39641 100644
--- a/Object3D.java
+++ b/Object3D.java
@@ -21,6 +21,19 @@
     
     ScriptNode scriptnode;
 
+        void InitOthers()
+        {
+                if (projectedVertices == null || projectedVertices.length <= 2)
+                {
+                    projectedVertices = new Object3D.cVector2[3];
+                }
+                for (int i = 0; i < 3; i++)
+                {
+                    projectedVertices[i] = new cVector2(); // Others
+                }
+                projectedVertices[0].x = 100; // bump
+        }
+
     void MinMax(cVector minima, cVector maxima)
     {
         for (int xyz = 0; xyz < 3; xyz++)
@@ -295,6 +308,8 @@
     boolean random = false;
     boolean speedup = false;
     boolean rewind = false;
+    
+    float NORMALPUSH = 0;
     
     Object3D support;
     
@@ -779,7 +794,10 @@
 //            factor = CameraPane.STEP;
 //        }
         
-        if (marked && CameraPane.isLIVE() && live && CameraPane.drawMode == CameraPane.SHADOW && currentframe != CameraPane.framecount)
+        if (marked && CameraPane.isLIVE() && live &&
+                //TEMP21aug2018
+                CameraPane.drawMode == CameraPane.SHADOW &&
+                currentframe != CameraPane.framecount)
         {
             currentframe = CameraPane.framecount;
             
@@ -2130,15 +2148,8 @@
         if (/*parent != null &&*/ material == null)
         {
             material = new cMaterial(GetMaterial());
-            if (projectedVertices == null || projectedVertices.length <= 2)
-            {
-                projectedVertices = new Object3D.cVector2[3];
-            }
-            for (int i = 0; i < 3; i++)
-            {
-                projectedVertices[i] = new cVector2(); // Others
-            }
-            projectedVertices[0].x = 100; // bump
+            
+            InitOthers();
             
             if (this instanceof Camera)
             {
@@ -4161,6 +4172,22 @@
         }
     }
     
+    void RepairShadow()
+    {
+        if (blockloop)
+            return;
+        
+        if (this.material != null)
+            this.InitOthers();
+                
+        for (int i=0; i<Size(); i++)
+        {               
+                blockloop = true;
+            get(i).RepairShadow();
+                blockloop = false;
+        }
+    }
+    
     void RepairTexture()
     {
         if (this instanceof FileObject || blockloop)
@@ -5958,7 +5985,7 @@
 
         javax.media.opengl.GL gl = display.GetGL();
 
-        if (CameraPane.BOXMODE) // || CameraPane.movingcamera)
+        if (CameraPane.BOXMODE && !selected) // || CameraPane.movingcamera)
         {
             int fc = bRep.FaceCount();
             int vc = bRep.VertexCount();
@@ -6699,13 +6726,26 @@
                 gl.glNormal3f((float) v2.x, (float) v2.y, (float) v2.z);
             }
 
+            // P
+            float x = (float)pv.x;
+            float y = (float)pv.y;
+            float z = (float)pv.z;
+            
             if (hasnorm)
             {
 //            if (!pv.norm.normalized())
 //                assert(pv.norm.normalized());
             
                 //System.out.println("normalp = " + pv.norm.x + ", " + pv.norm.y + ", " + pv.norm.z);
-                gl.glNormal3f((float) pv.norm.x, (float) pv.norm.y, (float) pv.norm.z);
+                    float nx = (float)pv.norm.x;
+                    float ny = (float)pv.norm.y;
+                    float nz = (float)pv.norm.z;
+                    
+                x += nx * NORMALPUSH;
+                y += ny * NORMALPUSH;
+                z += nz * NORMALPUSH;
+                
+                gl.glNormal3f(nx, ny, nz);
             }
             gl.glColor4f(pv.AO, pv.AO, pv.AO, 1);
             SetColor(display, pv);
@@ -6716,13 +6756,28 @@
             else
                 gl.glTexCoord2f((float) pv.s, (float) pv.t);
             //System.out.println("vertexp = " + pv.x + ", " + pv.y + ", " + pv.z);
-            gl.glVertex3f((float) pv./*pos.*/x, (float) pv./*pos.*/y, (float) pv./*pos.*/z);
+            
+            gl.glVertex3f(x, y, z);
+            
+            // Q
+            x = (float)qv.x;
+            y = (float)qv.y;
+            z = (float)qv.z;
+            
 //            Print(pv);
             if (hasnorm)
             {
 //            assert(qv.norm.normalized());
                 //System.out.println("normalq = " + qv.norm.x + ", " + qv.norm.y + ", " + qv.norm.z);
-                gl.glNormal3f((float) qv.norm.x, (float) qv.norm.y, (float) qv.norm.z);
+                    float nx = (float)qv.norm.x;
+                    float ny = (float)qv.norm.y;
+                    float nz = (float)qv.norm.z;
+                    
+                x += nx * NORMALPUSH;
+                y += ny * NORMALPUSH;
+                z += nz * NORMALPUSH;
+                
+                gl.glNormal3f(nx, ny, nz);
             }
             //System.out.println("vertexq = " + qv.s + ", " + qv.t);
         //    boolean locked = false;
@@ -6746,16 +6801,31 @@
         //    }
             gl.glColor4f(qv.AO, qv.AO, qv.AO, 1);
             SetColor(display, qv);
+            
+            gl.glVertex3f(x, y, z);
             //gl.glColor4f(r, g, b, 1);
    //gl.glColor4f(qv.boundary, qv.boundary, qv.boundary, 1);
             //System.out.println("vertexq = " + qv.x + ", " + qv.y + ", " + qv.z);
-            gl.glVertex3f((float) qv./*pos.*/x, (float) qv./*pos.*/y, (float) qv./*pos.*/z);
 //            Print(qv);
+
+            // R
+            x = (float)rv.x;
+            y = (float)rv.y;
+            z = (float)rv.z;
+            
             if (hasnorm)
             {
 //            assert(rv.norm.normalized());
                 //System.out.println("normalr = " + rv.norm.x + ", " + rv.norm.y + ", " + rv.norm.z);
-                gl.glNormal3f((float) rv.norm.x, (float) rv.norm.y, (float) rv.norm.z);
+                    float nx = (float)rv.norm.x;
+                    float ny = (float)rv.norm.y;
+                    float nz = (float)rv.norm.z;
+                    
+                x += nx * NORMALPUSH;
+                y += ny * NORMALPUSH;
+                z += nz * NORMALPUSH;
+                
+                gl.glNormal3f(nx, ny, nz);
             }
             
         //    if ((dot&4) == 0)
@@ -6776,7 +6846,7 @@
             //gl.glColor4f(r, g, b, 1);
    //gl.glColor4f(rv.boundary, rv.boundary, rv.boundary, 1);
             //System.out.println("vertexr = " + rv.x + ", " + rv.y + ", " + rv.z);
-            gl.glVertex3f((float) rv./*pos.*/x, (float) rv./*pos.*/y, (float) rv./*pos.*/z);
+            gl.glVertex3f(x, y, z);
 //            Print(rv);
         //gl.glEnd();
         }
@@ -8163,6 +8233,8 @@
     {
         Object3D targ = this;
         
+        targ.NORMALPUSH = obj.NORMALPUSH;
+        
         if (obj.material != null)
         {
             if ((mask&MATERIAL)!=0) // ==(COLOR|MATERIAL))
diff --git a/ScriptNode.java b/ScriptNode.java
index 6e25865..1315df0 100644
--- a/ScriptNode.java
+++ b/ScriptNode.java
@@ -972,25 +972,25 @@
         
         if (command.equals("targetx"))
         {
-            ((Mocap) object).targetx = Float.parseFloat(strs[index+2]);
+            ((Mocap) object).targetdirx = Float.parseFloat(strs[index+2]);
             return;
         }
         
         if (command.equals("targetz"))
         {
-            ((Mocap) object).targetz = Float.parseFloat(strs[index+2]);
+            ((Mocap) object).targetdirz = Float.parseFloat(strs[index+2]);
             return;
         }
         
         if (command.equals("goalx"))
         {
-            ((Mocap) object).goalx = Float.parseFloat(strs[index+2]);
+            ((Mocap) object).goalposx = Float.parseFloat(strs[index+2]);
             return;
         }
         
         if (command.equals("goalz"))
         {
-            ((Mocap) object).goalz = Float.parseFloat(strs[index+2]);
+            ((Mocap) object).goalposz = Float.parseFloat(strs[index+2]);
             return;
         }
         
diff --git a/Texture.java b/Texture.java
index 8f0cc1d..23134d0 100644
--- a/Texture.java
+++ b/Texture.java
@@ -10,7 +10,7 @@
 public class Texture extends Composite implements java.io.Serializable
 {
     // deprecated due to serial problems
-    static final long serialVersionUID = // -5280151442948961597L; // new java
+    static final long serialVersionUID = //-5280151442948961597L; // new java
                                          7695543694999681408L; // old java !!!
     
     // default = -8076744133104150348L
diff --git a/cSpring.java b/cSpring.java
index 2986693..445f1ac 100644
--- a/cSpring.java
+++ b/cSpring.java
@@ -82,7 +82,7 @@
 
     // timestep
     double timestep = 1;
-    double normalpusH = 0; // 1;
+    double normalpush = 0; // 1;
     static float H0 = 1E1f; // aucune importance...
     // mass
     double M = 1;
@@ -967,6 +967,7 @@
             for (int i = 0; i < allNodes.size(); i++)
             {
                 DynamicNode dn = allNodes.get(i);
+                dn.linked = false;
                 dn.closestpoint = null;
             }
         }
@@ -1416,6 +1417,7 @@
         //transient double rotangle; // Z of axis
         transient boolean reverse = false;
         
+        transient boolean linked = false;
         transient Vertex closestpoint = null;
         
         //Point3D lastForce = new Point3D();
@@ -1491,6 +1493,11 @@
                         otherForce.add(f.forceOn(this));
                     }
                 }
+            }
+
+            if (Double.isNaN(springForce.y))
+            {
+                    springForce.x = springForce.y = springForce.z = 0;
             }
         }
 
@@ -2339,28 +2346,7 @@
         return this;
     }
     
-    class Avoider extends Force
-    {
-        static final long serialVersionUID = -8657094699711594990L;
-        
-        Avoider()
-        {
-        }
-
-        Avoider(Object3D col)
-        {
-            SetAvoider(col);
-        }
-
-        void SetParameter(int index, double value)
-        {
-            parameters.setElementAt(new Double(value), index);
-        }
-        
-        void SetAvoider(Object3D col)
-        {
-            avoider = col;
-        }
+        Object3D avoider;
         
         void ResetGlobalTransform()
         {
@@ -2372,10 +2358,6 @@
 
         transient double[][] toRoot; // = new double[4][4];
         
-        //Vector<Vertex> sortedcollider;
-        Object3D avoider;
-        Vector<Double> parameters = new Vector<Double>(); // serial issue
-
         Vertex ClosestPoint(Vector<Vertex> collider, DynamicNode N, int startindex, int endindex, int sortaxis)
         {
             if (startindex == endindex)
@@ -2469,7 +2451,8 @@
             
             for (int i=collider.size(); --i>=0;)
             {
-                if (collider.get(i).norm.dot(((Vertex)N.position).norm) < 0)
+                // Why? 3 dec 2018
+                if (collider.get(i).norm.dot(((Vertex)N.position).norm) < 0.5)
                     continue;
                 
                 temp.set(N.position);
@@ -2487,43 +2470,24 @@
                 }
             }
             
-            return cp;
+            return mindist2 < 1 ? cp : null;
         }
         
-        Point3D forceOn(DynamicNode N)
+    class Avoider extends Force
+    {
+        static final long serialVersionUID = -8657094699711594990L;
+        
+        Avoider()
         {
-            force.x = 0;
-            force.y = 0;
-            force.z = 0;
-            
-        if (avoider.transientrep == null)
-            avoider.Revert();
-            
-            if (avoider.transientrep == null || avoider.transientrep.VertexCount() == 0 || avoider.transientrep.trimmed)
-                return force;
-            
-   ResetGlobalTransform();
-            if (N.closestpoint == null)
-            {
-                //avoider.bRep.GetVertex(0); // "sort"
-                
-                ResetGlobalTransform();
-            
-                N.closestpoint = ClosestPoint(avoider.transientrep./*sortedV*/vertices, N, 0,avoider.transientrep./*sortedV*/vertices.size(), 0);
-                    
-                if (N.closestpoint == null) // ????
-                    return force;
-            }
-            
-            if (avoider == This())
-            {
-                // good but must freeze the order first... not really...
-           //     if (cp.index < ((Vertex)N.position).index)
-           //         return force;
-            }
-            
-            if (normalpusH != 0) // && cp == null /*???*/) // speed == 0)
-            {
+        }
+
+        Avoider(Object3D col)
+        {
+            SetAvoider(col);
+        }
+
+        void Avoidance(DynamicNode N)
+        {
                 temp.set(N.position);
                 if (avoider != This())
                 {
@@ -2531,16 +2495,16 @@
                     temp2.mul(0.001);
                     temp.sub(temp2); // push outside because of mesh artifacts
                 }
-                
+
                 vect1.set(N.closestpoint);
-                
+
                 LA.xformPos(vect1,toRoot,vect1);
                 //avoider.TransformToWorld(vect1, vect1);
-                        
+
                 temp.sub(vect1);
-                
+
                 double distance = Math.sqrt(temp.length2());
-                
+
                 if (distance < 0.01)
                 {
                     temp2.set(N.closestpoint.norm);
@@ -2554,9 +2518,98 @@
                     if (IsAutoFreeze())
                         dot = -dot;
 
-                    temp.mul(normalpusH/*/distance*/*-dot/Math.sqrt(distance));
+                    temp.mul(normalpush/*/distance*/*-dot/Math.sqrt(distance));
                     force.add(temp);
                 }
+        }
+
+        void Attraction(DynamicNode N)
+        {
+                temp.set(N.position);
+                if (avoider != This())
+                {
+                    temp2.set(N.closestpoint.norm);
+                    temp2.mul(0.001);
+                    temp.sub(temp2); // push outside because of mesh artifacts
+                }
+
+                vect1.set(N.closestpoint);
+
+                LA.xformPos(vect1,toRoot,vect1);
+                //avoider.TransformToWorld(vect1, vect1);
+
+                temp.sub(vect1);
+
+                double distance = Math.sqrt(temp.length2());
+
+                //if (distance < 0.01)
+                {
+                    temp2.set(N.closestpoint.norm);
+                    double dot = temp2.dot(temp);
+
+//                    if (dot > 0)
+//                        dot = 0;
+
+                    // normal pushing
+                    temp.set(N.closestpoint.norm);
+//                    if (IsAutoFreeze())
+//                        dot = -dot;
+
+                    temp.mul(normalpush/*/distance*/ * -dot * distance);
+                    force.add(temp);
+                }
+        }
+
+        void SetParameter(int index, double value)
+        {
+            parameters.setElementAt(new Double(value), index);
+        }
+        
+        void SetAvoider(Object3D col)
+        {
+            avoider = col;
+        }
+        
+        //Vector<Vertex> sortedcollider;
+        Vector<Double> parameters = new Vector<Double>(); // serial issue
+
+        Point3D forceOn(DynamicNode N)
+        {
+            force.x = 0;
+            force.y = 0;
+            force.z = 0;
+            
+        if (avoider.transientrep == null)
+            avoider.Revert();
+            
+            if (avoider.transientrep == null || avoider.transientrep.VertexCount() == 0 || avoider.transientrep.trimmed)
+                return force;
+            
+   ResetGlobalTransform();
+            if (!N.linked)
+            {
+                //avoider.bRep.GetVertex(0); // "sort"
+                
+                ResetGlobalTransform();
+            
+                N.closestpoint = ClosestPoint(avoider.transientrep.vertices, N, 0,avoider.transientrep.vertices.size(), 0);
+                N.linked = true;
+            }
+            
+            if (avoider == This())
+            {
+                // good but must freeze the order first... not really...
+           //     if (cp.index < ((Vertex)N.position).index)
+           //         return force;
+            }
+            
+            if (normalpush != 0) // && cp == null /*???*/) // speed == 0)
+            {
+                if (N.closestpoint == null)
+                    return force;
+                
+                //Avoidance(N);
+                Attraction(N);
             }
             
             if (parameters.size() > 0)
@@ -2590,6 +2643,7 @@
                 totalforce = new Point3D();
                     
             totalforce.set(0,0,0);
+            
             if (forces.size() == 0)
                 totalforce.set(super.forceOn(N));
             
@@ -2660,7 +2714,7 @@
             force.y = 0;
             force.z = 0;
                 
-            if (normalpusH != 0) // speed == 0) // Now normal force
+            if (normalpush != 0) // speed == 0) // Now normal force
             {
              //   temp.set(N.position);
              //   temp.sub(Phys.reference);
@@ -2668,7 +2722,7 @@
                 
                 // normal pushing
                 temp.set(N.normal);
-                temp.mul(normalpusH/distance);
+                temp.mul(normalpush/distance);
                 force.add(temp);
             }
             
@@ -2900,6 +2954,7 @@
             return force;
         }
     }
+    
     static int TABLESAC = 1024;
     static double[] tablesac = new double[TABLESAC];
 
@@ -2993,6 +3048,40 @@
             //    mass = M;
             } // ???
 
+            if (avoider != null)
+            {
+                    if (avoider.transientrep == null)
+                        avoider.Revert();
+
+                    if (avoider.transientrep == null || avoider.transientrep.VertexCount() == 0 || avoider.transientrep.trimmed)
+                        return force;
+
+                    ResetGlobalTransform();
+                    if (!N.linked)
+                    {
+                        //avoider.bRep.GetVertex(0); // "sort"
+
+                        //ResetGlobalTransform();
+
+                        N.closestpoint = ClosestPoint(avoider.transientrep.vertices, N, 0,avoider.transientrep.vertices.size(), 0);
+                        N.linked = true;
+                    }
+                    
+                    if (N.closestpoint != null)
+                    {
+                        temp.set(N.position);
+                        vect1.set(N.closestpoint);
+                        LA.xformPos(vect1,toRoot,vect1);
+                        temp.sub(vect1);
+
+                            temp2.set(N.closestpoint.norm);
+                            double dot = temp2.dot(temp);
+
+                            if (dot < 0)
+                                mass = Float.NaN;
+                    }
+            }
+            
             force.x = 0;
             force.y = (float) (-acceleration * mass);
             force.z = 0; // -acceleration * mass * 1000 * Math.cos(time/234.0 + framecount*100); // (Math.random()*2 - 1); //  
@@ -3189,7 +3278,7 @@
             }
             if (false)  // isHandle)
             {
-                double K = Math.exp(-displacement*normalpusH);
+                double K = Math.exp(-displacement*normalpush);
                 magnitude /= (displacement*(1-K) + K);
             }
                 
diff --git a/cSpringEditor.java b/cSpringEditor.java
index 50018df..d94eeeb 100644
--- a/cSpringEditor.java
+++ b/cSpringEditor.java
@@ -133,7 +133,7 @@
 //        ObjEditor.aConstraints.gridwidth = 1;
 //        //ObjEditor.aConstraints.fill = 0;
 //        ObjEditor.aConstraints.gridx -= 1;
-            normalField = AddSlider(oe.ctrlPanel, "Normal:", 0, 20.0, Math.log(spring.normalpusH+1), 1);
+            normalField = AddSlider(oe.ctrlPanel, "Normal:", 0, 20.0, Math.log(spring.normalpush+1), 1);
             Return();
  
         /**/
@@ -472,7 +472,11 @@
                 
                 spring.W.AddForce(spring.new Avoider(GetEditor().copy.selection.get(0)));
             }
-//            else
+            else
+            {
+                if (spring.W instanceof cSpring.ActingForces)
+                        ((cSpring.ActingForces)spring.W).forces.clear();
+            }
             /*
             if (spring.Phys == null) // || spring.IsAutoFreeze())
                 spring.InitPhysics();
@@ -564,7 +568,7 @@
             spring.K = k;
             spring.M = m;
             spring.G.acceleration = g;
-            spring.normalpusH = d; // * Math.sqrt(m/k);
+            spring.normalpush = d; // * Math.sqrt(m/k);
             spring.limit = L;
             spring.restlengthFactor = t;
             spring.W.wind = v;

--
Gitblit v1.6.2