checkpoint
[anneal.git] / src / edu / berkeley / qfat / bind / HasQuadric.java
diff --git a/src/edu/berkeley/qfat/bind/HasQuadric.java b/src/edu/berkeley/qfat/bind/HasQuadric.java
new file mode 100644 (file)
index 0000000..d5c32da
--- /dev/null
@@ -0,0 +1,84 @@
+package edu.berkeley.qfat.bind;
+import edu.berkeley.qfat.geom.*;
+import javax.media.opengl.*;
+
+/** any object associated with a specific point in 3D space */
+public abstract class HasQuadric extends HasPoint {
+
+    public Matrix errorQuadric() { return quadric; }
+    public boolean quadricStale = false;
+    /** the nearest vertex in the "score_against" mesh */
+    public HasQuadric nearest_in_other_mesh;
+
+    /** the number of vertices in the other mesh for which this is the nearest_in_other_mesh */
+    public int    quadric_count;
+
+    /** the total error quadric (contributions from all vertices in other mesh for which this is nearest) */
+    public Matrix quadric = Matrix.ZERO;
+
+    public Matrix fundamentalQuadric = null;
+
+    public void recomputeFundamentalQuadricIfNeighborChanged() {
+        HasQuadric oldv = nearest_in_other_mesh;
+        HasQuadric newv = nearest();
+        if (oldv==newv) return;
+        recomputeFundamentalQuadric();
+        if (oldv!=null) oldv.recomputeFundamentalQuadricIfNeighborChanged();
+        // for some reason this causes an infinite loop
+        //if (newv!=null) newv.recomputeFundamentalQuadricIfNeighborChanged();
+    }
+    public void recomputeFundamentalQuadricIfStale() {
+        if (quadricStale || fundamentalQuadric==null) 
+            recomputeFundamentalQuadric();
+    }
+    public void recomputeFundamentalQuadric() {
+        unApplyQuadricToNeighbor();
+        if (quadricStale || fundamentalQuadric==null) {
+            fundamentalQuadric = _recomputeFundamentalQuadric();
+            quadricStale = false;
+        }
+        applyQuadricToNeighbor();
+    }
+    public abstract Matrix _recomputeFundamentalQuadric();
+    public void unComputeError() { setError(0); }
+    public void reComputeError() {
+        unComputeError();
+        computeError();
+    }
+    public abstract void setError(float nerror);
+    public abstract void computeError();
+    public abstract HasQuadric nearest();
+    public void applyQuadricToNeighbor() {
+        HasQuadric new_nearest = nearest();
+        if (nearest_in_other_mesh != null && new_nearest == nearest_in_other_mesh) return;
+
+        if (nearest_in_other_mesh != null) unApplyQuadricToNeighbor();
+        if (nearest_in_other_mesh != null) throw new Error();
+
+        nearest_in_other_mesh = new_nearest;
+
+        if (nearest_in_other_mesh!=null) {
+            nearest_in_other_mesh.unComputeError();
+            nearest_in_other_mesh.quadric = nearest_in_other_mesh.quadric.plus(fundamentalQuadric());
+            nearest_in_other_mesh.quadric_count++;
+            nearest_in_other_mesh.computeError();
+        }
+
+        reComputeError();
+    }
+    public Matrix fundamentalQuadric() {
+        if (fundamentalQuadric == null) recomputeFundamentalQuadric();
+        return fundamentalQuadric;
+    }
+    public void unApplyQuadricToNeighbor() {
+        if (nearest_in_other_mesh == null) return;
+        if (fundamentalQuadric == null) return;
+        nearest_in_other_mesh.unComputeError();
+        nearest_in_other_mesh.quadric = nearest_in_other_mesh.quadric.minus(fundamentalQuadric);
+        nearest_in_other_mesh.quadric_count--;
+        if (nearest_in_other_mesh.quadric_count==0)
+            nearest_in_other_mesh.quadric = Matrix.ZERO;
+        nearest_in_other_mesh.computeError();
+        nearest_in_other_mesh = null;
+    }
+}