1b13c33f56704ad4663578de9597e0a6efd90764
[anneal.git] / src / edu / berkeley / qfat / bind / HasQuadric.java
1 package edu.berkeley.qfat.bind;
2 import edu.berkeley.qfat.geom.*;
3 import javax.media.opengl.*;
4
5 /** any object associated with a specific point in 3D space */
6 public abstract class HasQuadric extends HasBindingGroup implements HasPoint {
7
8     public Matrix errorQuadric() { return quadric; }
9     public boolean quadricStale = false;
10     /** the nearest vertex in the "score_against" mesh */
11     public HasQuadric nearest_in_other_mesh;
12
13     /** the number of vertices in the other mesh for which this is the nearest_in_other_mesh */
14     public int    quadric_count;
15
16     /** the total error quadric (contributions from all vertices in other mesh for which this is nearest) */
17     public Matrix quadric = Matrix.ZERO;
18
19     public Matrix fundamentalQuadric = null;
20
21     public void recomputeFundamentalQuadricIfNeighborChanged() {
22         HasQuadric oldv = nearest_in_other_mesh;
23         HasQuadric newv = nearest();
24         if (oldv==newv) return;
25         recomputeFundamentalQuadric();
26         if (oldv!=null) oldv.recomputeFundamentalQuadricIfNeighborChanged();
27         // for some reason this causes an infinite loop
28         //if (newv!=null) newv.recomputeFundamentalQuadricIfNeighborChanged();
29     }
30     public void recomputeFundamentalQuadricIfStale() {
31         if (quadricStale || fundamentalQuadric==null) 
32             recomputeFundamentalQuadric();
33     }
34     public void recomputeFundamentalQuadric() {
35         unApplyQuadricToNeighbor();
36         if (quadricStale || fundamentalQuadric==null) {
37             fundamentalQuadric = _recomputeFundamentalQuadric();
38             quadricStale = false;
39         }
40         applyQuadricToNeighbor();
41     }
42     public abstract Matrix _recomputeFundamentalQuadric();
43     public void unComputeError() { setError(0); }
44     public void reComputeError() {
45         unComputeError();
46         computeError();
47     }
48     public abstract void setError(float nerror);
49     public abstract void computeError();
50     public abstract HasQuadric nearest();
51     public void applyQuadricToNeighbor() {
52         HasQuadric new_nearest = nearest();
53         if (nearest_in_other_mesh != null && new_nearest == nearest_in_other_mesh) return;
54
55         if (nearest_in_other_mesh != null) unApplyQuadricToNeighbor();
56         if (nearest_in_other_mesh != null) throw new Error();
57
58         nearest_in_other_mesh = new_nearest;
59
60         if (nearest_in_other_mesh!=null) {
61             nearest_in_other_mesh.unComputeError();
62             nearest_in_other_mesh.quadric = nearest_in_other_mesh.quadric.plus(fundamentalQuadric());
63             nearest_in_other_mesh.quadric_count++;
64             nearest_in_other_mesh.computeError();
65         }
66
67         reComputeError();
68     }
69     public Matrix fundamentalQuadric() {
70         if (fundamentalQuadric == null) recomputeFundamentalQuadric();
71         return fundamentalQuadric;
72     }
73     public void unApplyQuadricToNeighbor() {
74         if (nearest_in_other_mesh == null) return;
75         if (fundamentalQuadric == null) return;
76         nearest_in_other_mesh.unComputeError();
77         nearest_in_other_mesh.quadric = nearest_in_other_mesh.quadric.minus(fundamentalQuadric);
78         nearest_in_other_mesh.quadric_count--;
79         if (nearest_in_other_mesh.quadric_count==0)
80             nearest_in_other_mesh.quadric = Matrix.ZERO;
81         nearest_in_other_mesh.computeError();
82         nearest_in_other_mesh = null;
83     }
84
85     public float getMaxX() { return getPoint().getMaxX(); }
86     public float getMinX() { return getPoint().getMinX(); }
87     public float getMaxY() { return getPoint().getMaxY(); }
88     public float getMinY() { return getPoint().getMinY(); }
89     public float getMaxZ() { return getPoint().getMaxZ(); }
90     public float getMinZ() { return getPoint().getMinZ(); }
91 }