X-Git-Url: http://git.megacz.com/?p=anneal.git;a=blobdiff_plain;f=src%2Fedu%2Fberkeley%2Fqfat%2FMesh.java;h=2e68c17521c12e78e26c8f2ce1110fae62677760;hp=926a5b7b5d55ffea170ea62037216a1e88193c1a;hb=HEAD;hpb=d52f92b29c1987b5734c7183a9c01b5660f86482 diff --git a/src/edu/berkeley/qfat/Mesh.java b/src/edu/berkeley/qfat/Mesh.java index 926a5b7..2e68c17 100644 --- a/src/edu/berkeley/qfat/Mesh.java +++ b/src/edu/berkeley/qfat/Mesh.java @@ -1,6 +1,7 @@ package edu.berkeley.qfat; import java.awt.*; import java.util.*; +import java.io.*; import java.awt.event.*; import javax.swing.*; import javax.media.opengl.*; @@ -25,11 +26,12 @@ public class Mesh implements Iterable { public boolean option_errorNormals = false; public boolean option_selectable = true; - public void render(GL gl, Matrix m) { + public void render(GL gl, Matrix m) { render(gl, m, false); } + public void render(GL gl, Matrix m, boolean noColor) { if (option_wireframe) { gl.glDisable(GL.GL_LIGHTING); gl.glBegin(GL.GL_LINES); - gl.glColor3f(1, 1, 1); + if (!noColor) gl.glColor3f(1, 1, 1); for (T t : this) { // fixme used to be .goodp m.times(t.e1().v1.p).glVertex(gl); @@ -44,10 +46,11 @@ public class Mesh implements Iterable { return; } for(T t : this) { - gl.glColor4f((float)(0.25+(0.05*t.color)), - (float)(0.25+(0.05*t.color)), - (float)(0.75+(0.05*t.color)), - (float)0.3); + if (!noColor) + gl.glColor4f((float)(0.25+(0.05*t.color)), + (float)(0.25+(0.05*t.color)), + (float)(0.75+(0.05*t.color)), + (float)0.3); /* if (t.red) { gl.glColor4f((float)(0.75+(0.05*t.color)), @@ -63,7 +66,8 @@ public class Mesh implements Iterable { for(Mesh.Vertex p : new Mesh.Vertex[] { t.v1(), t.v2(), t.v3() }) { if (p.ok) { gl.glBegin(GL.GL_LINES); - gl.glColor3f(1, 1, 1); + if (!noColor) + gl.glColor3f(1, 1, 1); p.p.glVertex(gl); p.p.plus(p.norm().times((float)p.error()*10)).glVertex(gl); gl.glEnd(); @@ -81,6 +85,7 @@ public class Mesh implements Iterable { public float error() { return (float)error; } public int size() { return vertices.size(); } + public int numTriangles() { return triangles.size(); } public Iterable vertices() { return vertices; } public Iterator iterator() { return triangles.iterator(); } @@ -422,7 +427,10 @@ public class Mesh implements Iterable { Point pt = vv.plus(getPoint()); Point pp = pt; pt = getBindingConstraint().getProjection(pp); - if (pt==null) return false; + if (pt==null) { + System.out.println("constraint violation: " + getBindingConstraint()); + return false; + } System.out.println(pt.minus(pp).mag() + " " + getBindingConstraint()); for(Vertex v : (Iterable)getBoundPeers()) { @@ -586,6 +594,34 @@ public class Mesh implements Iterable { E pair; // partner half-edge boolean shattered = false; + + /** the "edge normal" -- average of the normals of the adjacent faces */ + public Vec norm() { + return + (t==null || pair==null || pair.t==null) + ? null + : t.norm().plus(pair.t.norm()).norm(); + } + + public void glVertices(GL gl) { + Point p1 = v1.p; + Point p2 = v2.p; + if (t != null) { + p1 = p1.plus(t.centroid().minus(p1).times(0.1f)); + p2 = p2.plus(t.centroid().minus(p2).times(0.1f)); + p1 = p1.plus(norm().times(length() * 0.01f)); + p2 = p2.plus(norm().times(length() * 0.01f)); + } + p1.glVertex(gl); + p2.glVertex(gl); + if (t==null || pair.t==null) return; + + Point atip = p2.minus(Point.ZERO).times(4).plus(p1.minus(Point.ZERO)).div(5).plus(Point.ZERO); + atip = (t.norm().plus(pair.t.norm())).norm().times(getSegment().length() / 5).plus(atip); + p2.glVertex(gl); + atip.glVertex(gl); + } + public boolean intersects(T t) { return t.intersects(v1.p, v2.p); } public Segment getSegment() { return new Segment(v1.getPoint(), v2.getPoint()); } @@ -632,21 +668,30 @@ public class Mesh implements Iterable { if (next==null || prev==null) continue; if (eother.next==null || eother.prev==null) continue; - if (next.isBoundTo(eother.pair.prev.pair) && !prev.isBoundTo(eother.pair.next.pair)) - prev.bindTo(next.getBindingMatrix(eother.pair.prev.pair), eother.pair.next.pair); - if (!next.isBoundTo(eother.pair.prev.pair) && prev.isBoundTo(eother.pair.next.pair)) - next.bindTo(prev.getBindingMatrix(eother.pair.next.pair), eother.pair.prev.pair); + Matrix m = getBindingMatrix(eother); + if (next.isBoundTo(eother.pair.prev.pair) && + !prev.isBoundTo(eother.pair.next.pair) && + m.equalsModuloEpsilon(next.getBindingMatrix(eother.pair.prev.pair), EPSILON)) + prev.bindEdge(next.getBindingMatrix(eother.pair.prev.pair), eother.pair.next.pair); + if (!next.isBoundTo(eother.pair.prev.pair) && + prev.isBoundTo(eother.pair.next.pair) && + m.equalsModuloEpsilon(prev.getBindingMatrix(eother.pair.next.pair), EPSILON)) + next.bindEdge(prev.getBindingMatrix(eother.pair.next.pair), eother.pair.prev.pair); + + //if (next.isBoundTo(eother.prev) && !prev.isBoundTo(eother.next)) + //prev.bindTo(next.getBindingMatrix(eother.prev), eother.next); + //if (!next.isBoundTo(eother.prev) && prev.isBoundTo(eother.next)) + //next.bindTo(prev.getBindingMatrix(eother.next), eother.prev); + + if (next.isBoundTo(eother.next) && + !prev.isBoundTo(eother.prev) && + m.equalsModuloEpsilon(next.getBindingMatrix(eother.next), EPSILON)) + prev.bindEdge(next.getBindingMatrix(eother.next), eother.prev); + if (!next.isBoundTo(eother.next) && + prev.isBoundTo(eother.prev) && + m.equalsModuloEpsilon(prev.getBindingMatrix(eother.prev), EPSILON)) + next.bindEdge(prev.getBindingMatrix(eother.prev), eother.next); - /* - if (next.isBoundTo(eother.prev) && !prev.isBoundTo(eother.next)) - prev.bindTo(next.getBindingMatrix(eother.prev), eother.next); - if (!next.isBoundTo(eother.prev) && prev.isBoundTo(eother.next)) - next.bindTo(prev.getBindingMatrix(eother.next), eother.prev); - */ - if (next.isBoundTo(eother.next) && !prev.isBoundTo(eother.prev)) - prev.bindTo(next.getBindingMatrix(eother.next), eother.prev); - if (!next.isBoundTo(eother.next) && prev.isBoundTo(eother.prev)) - next.bindTo(prev.getBindingMatrix(eother.prev), eother.next); } } @@ -665,35 +710,24 @@ public class Mesh implements Iterable { public int compareTo(E e) { return e.comparator() > comparator() ? 1 : -1; } - public void bindEdge(E e, Matrix m) { - _bindEdge(e, m); - pair._bindEdge(e.pair, m); + public void bindEdge(Matrix m, E e) { + bindEdge(e, m); } - public void _bindEdge(E e, Matrix m) { - e = e.pair; - /* - //assumes edges are identical length at binding time - Vec reflectionPlaneNormal = e.v2.p.minus(e.v1.p).norm(); - float a = reflectionPlaneNormal.x; - float b = reflectionPlaneNormal.y; - float c = reflectionPlaneNormal.z; - Matrix reflectionMatrix = - new Matrix( 1-2*a*a, -2*a*b, -2*a*c, 0, - -2*a*b, 1-2*b*b, -2*b*c, 0, - -2*a*c, -2*b*c, 1-2*c*c, 0, - 0, 0, 0, 1); - m = m.times(Matrix.translate(e.midpoint().minus(Point.ORIGIN)) - .times(reflectionMatrix) - .times(Matrix.translate(Point.ORIGIN.minus(e.midpoint())))); - System.out.println(reflectionPlaneNormal); - System.out.println(" " + v1.p + " " + m.times(e.v1.p)); - System.out.println(" " + v2.p + " " + m.times(e.v2.p)); - */ + public void bindEdge(E e, Matrix m) { /* - if (m.times(e.v1.p).minus(v1.p).mag() > EPSILON) throw new Error(); - if (m.times(e.v2.p).minus(v2.p).mag() > EPSILON) throw new Error(); + for(E e_ : (Iterable)e.getBoundPeers()) { + if (e.v1.getPoint().distance((e.getBindingMatrix(e_).times(e_.v1.getPoint()))) > 0.01f) + throw new RuntimeException("blah! " + e.v1.getPoint() + " " + e.getBindingMatrix(e_).times(e_.v1.getPoint())); + if (e.v2.getPoint().distance((e.getBindingMatrix(e_).times(e_.v2.getPoint()))) > 0.01f) + throw new RuntimeException("blah! " + e.v2.getPoint() + " " + e.getBindingMatrix(e_).times(e_.v2.getPoint())); + if (v1.getPoint().distance(m.times(e.getBindingMatrix(e_).times(e_.v1.getPoint()))) > 0.01f) + throw new RuntimeException("blah! " + v1.getPoint() + " " + m.times(e_.v1.getPoint())); + if (v2.getPoint().distance(m.times(e.getBindingMatrix(e_).times(e_.v2.getPoint()))) > 0.01f) + throw new RuntimeException("blah! " + v2.getPoint() + " " + m.times(e_.v2.getPoint())); + } */ - this.bindTo(m, e); + this.bindTo(m, e, EPSILON); + this.pair.bindTo(m, e.pair, EPSILON); } public void dobind() { @@ -701,10 +735,6 @@ public class Mesh implements Iterable { if (e==this) continue; v1.bindTo(getBindingMatrix(e), e.v1); v2.bindTo(getBindingMatrix(e), e.v2); - /* - e.v1.setConstraint(getAffineConstraint()); - e.v2.setConstraint(getAffineConstraint()); - */ } } @@ -869,6 +899,7 @@ public class Mesh implements Iterable { public E(Point v1, Point v2) { if (vertices.get(v1) != null) throw new Error(); if (vertices.get(v2) != null) throw new Error(); + if (v1.equals(v2)) throw new Error("attempt to create a zero-length edge!"); this.v1 = new Vertex(v1); this.v2 = new Vertex(v2); this.prev = this.next = this.pair = new E(this, this, this); @@ -938,9 +969,13 @@ public class Mesh implements Iterable { public T newT(HasPoint v1, HasPoint v2, HasPoint v3) { return newT(v1.getPoint(), v2.getPoint(), v3.getPoint(), null, 0); } + public T newT(Point v1, Point v2, Point v3, Vec norm) { return newT(v1, v2, v3, norm, 1); } public T newT(Point v1, Point v2, Point v3, Vec norm, int colorclass) { + if (v1.equals(v2) + || v2.equals(v3) + || v3.equals(v1)) + throw new Error("attempt to make a triangle with a length-zero side"); if (coalesce) { - for(Vertex v : vertices) { if (v1.distance(v.p) < EPSILON) { v1 = v.p; break; } } for(Vertex v : vertices) { if (v2.distance(v.p) < EPSILON) { v2 = v.p; break; } } for(Vertex v : vertices) { if (v3.distance(v.p) < EPSILON) { v3 = v.p; break; } } @@ -949,6 +984,11 @@ public class Mesh implements Iterable { v2 = new Point(round(v2.x), round(v2.y), round(v2.z)); v3 = new Point(round(v3.x), round(v3.y), round(v3.z)); */ + /* + // triangle's vertices got merged + if (v1.equals(v2) || v2.equals(v3) || v3.equals(v1)) + return null; + */ } if (norm != null) { Vec norm2 = v3.minus(v1).cross(v2.minus(v1)); @@ -959,6 +999,7 @@ public class Mesh implements Iterable { E e12 = makeE(v1, v2); E e23 = makeE(v2, v3); E e31 = makeE(v3, v1); + if (e12==e23 || e23==e31 || e12==e31) throw new Error(); while(e12.next != e23 || e23.next != e31 || e31.next != e12) { e12.makeAdjacent(e23); e23.makeAdjacent(e31); @@ -1149,11 +1190,9 @@ public class Mesh implements Iterable { public boolean destroyed() { return destroyed; } public boolean shouldBeDrawn() { - - if (e1().bindingGroupSize() <= 1) return false; - if (e2().bindingGroupSize() <= 1) return false; - if (e3().bindingGroupSize() <= 1) return false; - + if (e1().bindingGroupUnconstrained()) return false; + if (e2().bindingGroupUnconstrained()) return false; + if (e3().bindingGroupUnconstrained()) return false; return true; } @@ -1171,4 +1210,24 @@ public class Mesh implements Iterable { super.glVertices(gl, m); } } + + // Dump ///////////////////////////////////////////////////////////////////////////// + + public void dump(OutputStream os) throws IOException { + PrintWriter pw = new PrintWriter(new OutputStreamWriter(os)); + pw.println("solid dump"); + for(Mesh.T t : this) { + Vec normal = t.norm(); + pw.println("facet normal " + normal.x + " " + normal.y + " " + normal.z); + pw.println(" outer loop"); + for(Mesh.Vertex v : new Mesh.Vertex[] { t.v1(), t.v2(), t.v3() }) { + pw.println(" vertex " + v.p.x + " " + v.p.y + " " + v.p.z); + } + pw.println(" endloop"); + pw.println("endfacet"); + } + pw.println("endsolid dump"); + pw.flush(); + } + }