public static final Random random = new Random();
private RTree<T> tris = new RTree<T>();
- private PointSet<Vert> vertices = new PointSet<Vert>();
+ private PointSet<Vertex> vertices = new PointSet<Vertex>();
+ public boolean immutableVertices;
+ public boolean ignorecollision = false;
public Mesh score_against = null;
public double score = 0;
+
+ public Mesh(boolean immutableVertices) { this.immutableVertices = immutableVertices; }
+
+ public void makeVerticesImmutable() { this.immutableVertices = true; }
public float score() { return (float)score; }
- public int numedges = 0;
- public float avgedge = 0;
public int size() { return vertices.size(); }
- public Iterable<Vert> vertices() { return vertices; }
-
- public Iterator<T> iterator() {
- return tris.iterator();
- }
+ public Iterable<Vertex> vertices() { return vertices; }
+ public Iterator<T> iterator() { return tris.iterator(); }
public void rebindPoints() {
// unbind all points
}
public void unApplyQuadricToNeighborAll() {
- HashSet<Vert> done = new HashSet<Vert>();
+ HashSet<Vertex> done = new HashSet<Vertex>();
for(T t : this)
- for(Vert p : new Vert[] { t.v1(), t.v2(), t.v3() }) {
+ for(Vertex p : new Vertex[] { t.v1(), t.v2(), t.v3() }) {
if (done.contains(p)) continue;
done.add(p);
p.unApplyQuadricToNeighbor();
}
}
public void recomputeAllFundamentalQuadrics() {
- HashSet<Vert> done = new HashSet<Vert>();
+ HashSet<Vertex> done = new HashSet<Vertex>();
for(T t : this)
- for(Vert p : new Vert[] { t.v1(), t.v2(), t.v3() }) {
+ for(Vertex p : new Vertex[] { t.v1(), t.v2(), t.v3() }) {
if (done.contains(p)) continue;
done.add(p);
p.recomputeFundamentalQuadric();
public float applyQuadricToNeighborAll() {
int num = 0;
double dist = 0;
- HashSet<Vert> done = new HashSet<Vert>();
+ HashSet<Vertex> done = new HashSet<Vertex>();
for(T t : this)
- for(Vert p : new Vert[] { t.v1(), t.v2(), t.v3() }) {
+ for(Vertex p : new Vertex[] { t.v1(), t.v2(), t.v3() }) {
if (done.contains(p)) continue;
done.add(p);
p.applyQuadricToNeighbor();
}
public void transform(Matrix m) {
- ArrayList<Vert> set = new ArrayList<Vert>();
- for (Vert v : vertices)
- set.add(v);
- for(Vert v : set) v.transform(m);
+ ArrayList<Vertex> set = new ArrayList<Vertex>();
+ for(Vertex v : vertices) set.add(v);
+ for(Vertex v : set) v.transform(m);
}
+ public void rebuild() { /*vertices.rebuild();*/ }
+ public Vec diagonal() { return vertices.diagonal(); }
+ public Point centroid() { return vertices.centroid(); }
+ public Vertex nearest(Point p) { return vertices.nearest(p); }
+
+ /** compute the volume of the mesh */
public float volume() {
double total = 0;
for(T t : this) {
return (float)total;
}
- public void rebuild() { /*vertices.rebuild();*/ }
- public Vec diagonal() { return vertices.diagonal(); }
- public Point centroid() { return vertices.centroid(); }
- public Vert nearest(Point p) { return vertices.nearest(p); }
- public final class Vert extends HasPoint {
+ // Vertexices //////////////////////////////////////////////////////////////////////////////
+
+ public final class Vertex extends HasPoint {
public String toString() { return p.toString(); }
public Point p;
E e; // some edge *leaving* this point
/** the nearest vertex in the "score_against" mesh */
- Vert nearest_in_other_mesh;
+ Vertex nearest_in_other_mesh;
/** the number of vertices in the other mesh for which this is the nearest_in_other_mesh */
int quadric_count;
/** the total error quadric (contributions from all vertices in other mesh for which this is nearest) */
Matrix quadric = Matrix.ZERO;
- Vert bound_to = this;
+ Vertex bound_to = this;
Matrix binding = Matrix.ONE;
float oldscore = 0;
boolean quadricStale = false;
return fundamentalQuadric;
}
- private Vert(Point p) {
+ private Vertex(Point p) {
this.p = p;
if (vertices.get(p) != null) throw new Error();
vertices.add(this);
public void applyQuadricToNeighbor() {
if (score_against == null) return;
- Vert new_nearest = score_against.nearest(p);
+ Vertex 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();
}
public void computeError() {
if (quadric_count == 0) {
- if (!tilemesh) {
- }
- else if (nearest_in_other_mesh == null) {
+ if (immutableVertices) {
+ } else if (nearest_in_other_mesh == null) {
if (score_against != null) {
- Vert ne = score_against.nearest(p);
+ Vertex ne = score_against.nearest(p);
oldscore = ne.fundamentalQuadric().preAndPostMultiply(p) * 100 * 10;
} else {
oldscore = 0;
/** does NOT update bound pairs! */
public boolean transform(Matrix m) {
+ if (immutableVertices) throw new Error();
unApplyQuadricToNeighbor();
Point oldp = this.p;
try {
new Visitor<T>() {
public void visit(T t) {
if (!good) return;
- E e = Vert.this.e;
+ E e = Vertex.this.e;
do {
if (!t.has(e.p1) && !t.has(e.p2) && e.intersects(t)) { good = false; }
if (e.t != null) {
if (!e.t.has(t.e3().p1) && !e.t.has(t.e3().p2) && t.e3().intersects(e.t)) { good = false; }
}
e = e.pair.next;
- } while(e != Vert.this.e);
+ } while(e != Vertex.this.e);
}
});
public boolean move(Vec v) {
Matrix m = Matrix.translate(v);
- Vert p = this;
+ Vertex p = this;
boolean good = true;
do {
good &= p.transform(m);
}
public E getE(Point p2) {
- Vert v = vertices.get(p2);
+ Vertex v = vertices.get(p2);
if (v==null) return null;
return getE(v);
}
- public E getE(Vert p2) {
+ public E getE(Vertex p2) {
E e = this.e;
do {
if (e==null) return null;
return norm.norm();
}
- public boolean isBoundTo(Vert p) {
- Vert px = p;
+ public boolean isBoundTo(Vertex p) {
+ Vertex px = p;
do {
if (px==this) return true;
px = px.bound_to;
return false;
}
public void unbind() { bound_to = this; binding = Matrix.ONE; }
- public void bind(Vert p) { bind(p, Matrix.ONE); }
- public void bind(Vert p, Matrix binding) {
+ public void bind(Vertex p) { bind(p, Matrix.ONE); }
+ public void bind(Vertex p, Matrix binding) {
if (isBoundTo(p)) return;
- Vert temp_bound_to = p.bound_to;
+ Vertex temp_bound_to = p.bound_to;
Matrix temp_binding = p.binding;
p.bound_to = this.bound_to;
p.binding = binding.times(this.binding); // FIXME: may have order wrong here
/** [UNIQUE] an edge */
public final class E implements Comparable<E> {
- public final Vert p1, p2;
+ public final Vertex p1, p2;
T t; // triangle to our "left"
E prev; // previous half-edge
E next; // next half-edge
public boolean intersects(T t) { return t.intersects(p1.p, p2.p); }
public float comparator() {
- Vert nearest = score_against.nearest(midpoint());
+ Vertex nearest = score_against.nearest(midpoint());
//if (t==null) return length();
/*
double ang = Math.abs(crossAngle());
if (shattered || destroyed) return mid;
shattered = true;
- Vert r = next.p2;
+ Vertex r = next.p2;
E next = this.next;
E prev = this.prev;
pair.next = prev;
if (p1.e == this) p1.e = prev.next;
if (pair.p1.e == pair) pair.p1.e = pair.prev.next;
- avgedge -= this.length();
- avgedge -= pair.length();
- numedges--;
- numedges--;
}
private void sync() {
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;
- if (!added) {
- added = true;
- numedges++;
- avgedge += length();
- }
+ if (!added) added = true;
}
private boolean added = false;
public E(Point p1, Point p2) {
if (vertices.get(p1) != null) throw new Error();
if (vertices.get(p2) != null) throw new Error();
- this.p1 = new Vert(p1);
- this.p2 = new Vert(p2);
+ this.p1 = new Vertex(p1);
+ this.p2 = new Vertex(p2);
this.prev = this.next = this.pair = new E(this, this, this);
this.p1.e = this;
this.p2.e = this.pair;
/** adds a new half-edge from prev.p2 to p2 */
public E(E prev, Point p) {
- Vert p2;
+ Vertex p2;
p2 = vertices.get(p);
- if (p2 == null) p2 = new Vert(p);
+ if (p2 == null) p2 = new Vertex(p);
this.p1 = prev.p2;
this.p2 = p2;
this.prev = prev;
sync();
}
public Point midpoint() { return new Point((p1.p.x+p2.p.x)/2, (p1.p.y+p2.p.y)/2, (p1.p.z+p2.p.z)/2); }
- public boolean has(Vert v) { return v==p1 || v==p2; }
+ public boolean has(Vertex v) { return v==p1 || v==p2; }
public float length() { return p1.p.minus(p2.p).mag(); }
public String toString() { return p1+"->"+p2; }
}
public E makeE(Point p1, Point p2) {
- Vert v1 = vertices.get(p1);
- Vert v2 = vertices.get(p2);
+ Vertex v1 = vertices.get(p1);
+ Vertex v2 = vertices.get(p2);
if (v1 != null && v2 != null) {
E e = v1.getE(v2);
if (e != null) return e;
}
- public class FaceIterator implements Iterator<T> {
- private HashSet<T> visited = new HashSet<T>();
- private LinkedList<T> next = new LinkedList<T>();
- public FaceIterator() { }
- public FaceIterator(Vert v) { next.addFirst(v.e.t); }
- public boolean hasNext() { return next.peek()!=null; }
- public void remove() { throw new Error(); }
- public T next() {
- T ret = next.removeFirst();
- if (ret == null) return null;
- visited.add(ret);
- T t1 = ret.e1().pair.t;
- T t2 = ret.e2().pair.t;
- T t3 = ret.e3().pair.t;
- if (t1 != null && !visited.contains(t1)) next.addFirst(t1);
- if (t2 != null && !visited.contains(t2)) next.addFirst(t2);
- if (t3 != null && !visited.contains(t3)) next.addFirst(t3);
- return ret;
- }
- }
-
/** [UNIQUE] a triangle (face) */
public final class T extends Triangle {
public final E e1;
public E e1() { return e1; }
public E e2() { return e1.next; }
public E e3() { return e1.prev; }
- public Vert v1() { return e1.p1; }
- public Vert v2() { return e1.p2; }
- public Vert v3() { return e1.next.p2; }
+ public Vertex v1() { return e1.p1; }
+ public Vertex v2() { return e1.p2; }
+ public Vertex v3() { return e1.next.p2; }
public Point p1() { return e1.p1.p; }
public Point p2() { return e1.p2.p; }
public Point p3() { return e1.next.p2.p; }
public boolean hasE(E e) { return e1==e || e1.next==e || e1.prev==e; }
- public boolean has(Vert v) { return v1()==v || v2()==v || v3()==v; }
+ public boolean has(Vertex v) { return v1()==v || v2()==v || v3()==v; }
- public void glVertices(GL gl) {
-
- /*
- if (e1().bind_to.set.size() == 0) return;
- if (e2().bind_to.set.size() == 0) return;
- if (e3().bind_to.set.size() == 0) return;
- */
-
- norm().glNormal(gl);
- p1().glVertex(gl);
- p2().glVertex(gl);
- p3().glVertex(gl);
+ public boolean shouldBeDrawn() {
+ if (e1().bind_to.set.size() == 0) return false;
+ if (e2().bind_to.set.size() == 0) return false;
+ if (e3().bind_to.set.size() == 0) return false;
+ return true;
}
+
}
- public boolean tilemesh = false;
- public boolean ignorecollision = false;
}