return (float)total;
}
- public class BindingGroup {
- public HashSet<E> es = new HashSet<E>();
- public BindingGroup() { }
- public BindingGroup(E e) {
- es.add(e);
- }
- public void add(E e) {
- if (e.bg != null) { merge(e.bg); return; }
- es.add(e);
- e.bg = this;
- }
- public void merge(BindingGroup bg) {
- for(E e : bg.es) {
- e.bg = null;
- add(e);
- }
- }
- }
-
+ public void rebuildPointSet() { pointset.rebuild(); }
public Vec diagonal() { return pointset.diagonal(); }
public Point centroid() { return pointset.centroid(); }
public Vert nearest(Point p) { return pointset.nearest(p); }
Vert bound_to = this;
Matrix binding = new Matrix();
float oldscore = 0;
+ boolean quadricStale = false;
public Matrix errorQuadric() { return quadric; }
public Point getPoint() { return p; }
}
public void recomputeFundamentalQuadric() {
+ if (!quadricStale && fundamentalQuadric != null) return;
+ quadricStale = false;
unApplyQuadricToNeighbor();
Matrix m = Matrix.ZERO;
E e = this.e;
public void applyQuadricToNeighbor() {
if (score_against == null) return;
+ Vert new_nearest = score_against.nearest(p);
+ 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) {
- nearest_in_other_mesh = score_against.nearest(p);
-
- // don't attract to vertices that face the other way
- if (nearest_in_other_mesh.e == null || nearest_in_other_mesh.norm().dot(norm()) < 0) {
- nearest_in_other_mesh = null;
- } else {
- 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();
- }
+ if (nearest_in_other_mesh != null) throw new Error();
+
+ nearest_in_other_mesh = new_nearest;
+
+ // don't attract to vertices that face the other way
+ if (nearest_in_other_mesh.e == null || nearest_in_other_mesh.norm().dot(norm()) < 0) {
+ nearest_in_other_mesh = null;
+ } else {
+ 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();
}
applyQuadricToNeighbor();
// should recompute fundamental quadrics of all vertices sharing a face, but we defer...
+ E e = this.e;
+ do {
+ e.p2.quadricStale = true;
+ e = e.pair.next;
+ } while(e != this.e);
+
+
// FIXME: intersection test needed?
return true;
}
}
}
+ public class BindingGroup {
+ private HashSet<E> set = new HashSet<E>();
+ public BindingGroup bind_others;
+ public BindingGroup other() { return bind_others; }
+ public BindingGroup(BindingGroup bind_others) { this.bind_others = bind_others; }
+ public BindingGroup() {
+ this.bind_others = new BindingGroup(this);
+ }
+ public void add(E e) {
+ if (set.contains(e)) return;
+ for (E epeer : e.bind_peers.set) {
+ epeer.bind_peers = this;
+ set.add(epeer);
+ }
+ for (E eother : e.bind_to.set) {
+ eother.bind_to = bind_others;
+ bind_others.add(eother);
+ }
+
+ for(E ex : (!swap ? right : left)) {
+ if (e.prev.isBoundTo(ex.prev)) {
+ System.out.println("hit!");
+ }
+ }
+
+ }
+ public void dobind(E e) {
+ for(E ebound : set) {
+ e.p1.bind(ebound.p2);
+ e.p2.bind(ebound.p1);
+ }
+ }
+ public void shatter(BindingGroup bg1, BindingGroup bg2) {
+ for(E e : set) {
+ e.shatter(e.midpoint(), bg1, bg2, false);
+ }
+ }
+ }
+
/** [UNIQUE] an edge */
public final class E implements Comparable<E> {
E prev; // previous half-edge
E next; // next half-edge
E pair; // partner half-edge
- public BindingGroup bg = new BindingGroup(this);
+ public BindingGroup bind_peers = new BindingGroup();
+ public BindingGroup bind_to = bind_peers.other();
boolean shattered = false;
public int compareTo(E e) { return e.length() > length() ? 1 : -1; }
+ public void bindEdge(E e) { bind_to.add(e); }
+ public void dobind() { bind_to.dobind(this); }
- public void bind(E e) { bind(e, new Matrix()); }
- public void bind(E e, Matrix m) { e.bg.add(this); }
-
- public void dobind() {
- if (bg==null) return;
- for(E ex : bg.es) {
- if (ex==this) continue;
- p1.bind(ex.p1);
- p2.bind(ex.p2);
- }
- }
-
- public Point shatter() { return shatter(midpoint(), null, null); }
- public Point shatter(Point mid, BindingGroup bg1, BindingGroup bg2) {
+ public Point shatter() { return shatter(midpoint(), null, null, false); }
+ public Point shatter(Point mid, BindingGroup bg1, BindingGroup bg2, boolean swap) {
if (shattered) return mid;
shattered = true;
if (bg1==null) bg1 = new BindingGroup();
if (bg2==null) bg2 = new BindingGroup();
- for(E e : bg.es) e.shatter(e.midpoint(), bg1, bg2);
+ bind_peers.shatter(bg1, bg2);
+ bind_to.shatter(bg2.other(), bg1.other());
pair.shatter();
destroy();
prev.t = null;
pair.next.t = null;
pair.prev.t = null;
- this.bg = null;
- pair.bg = null;
+ this.bind_to = null;
+ pair.bind_to = null;
+ this.bind_peers = null;
+ pair.bind_peers = null;
pair.prev.next = next;
next.prev = pair.prev;
prev.next = pair.next;
this.prev.next = this;
this.next.prev = this;
this.pair.pair = this;
+ bind_peers.add(this);
if (this.next.p1 != p2) throw new Error();
if (this.prev.p2 != p1) throw new Error();
if (this.p1.e == null) this.p1.e = this;