import edu.berkeley.qfat.geom.*;
import edu.berkeley.qfat.geom.Point;
+// TO DO:
+// - real anneal
+// - solve self-intersection problem
+// - get a better test model?
+
// FIXME: re-orient goal (how?)
public class Main extends MeshViewer {
Point p1 = new Point(stlf.coordArray[i+1].x * MAG, stlf.coordArray[i+1].y * MAG, stlf.coordArray[i+1].z * MAG);
Point p2 = new Point(stlf.coordArray[i+2].x * MAG, stlf.coordArray[i+2].y * MAG, stlf.coordArray[i+2].z * MAG);
Vec n = new Vec(stlf.normArray[i/3].x * MAG, stlf.normArray[i/3].y * MAG, stlf.normArray[i/3].z * MAG);
- Mesh.T t = goal.newT(p0, p1, p2, n);
+ Mesh.T t = goal.newT(p0, p1, p2, n, 0);
}
// rotate to align major axis -- this probably needs to be done by a human.
float goal_height = goal.diagonal().dot(new Vec(0, 1, 0));
float goal_depth = goal.diagonal().dot(new Vec(0, 0, 1));
+ /*
float width = (float)0.6;
float height = (float)0.08;
float depth = (float)0.3;
+ */
+ float width = (float)0.6;
+ float depth = (float)0.08;
+ float height = (float)0.3;
+
+ float rshift = width/2;
+ float lshift = -(width/2);
+
translations = new Matrix[] {
- new Matrix(new Vec(-(width/2), height, 0)),
- new Matrix(new Vec( (width/2), height, 0)),
- new Matrix(new Vec(-(width/2), -height, 0)),
- new Matrix(new Vec( (width/2), -height, 0)),
- new Matrix(new Vec(-(width/2), 0, depth)),
- new Matrix(new Vec( (width/2), 0, depth)),
- new Matrix(new Vec(-(width/2), 0, -depth)),
- new Matrix(new Vec( (width/2), 0, -depth)),
+ new Matrix(new Vec(lshift, depth, 0)),
+ new Matrix(new Vec(rshift, depth, 0)),
+ new Matrix(new Vec(lshift, -depth, 0)),
+ new Matrix(new Vec(rshift, -depth, 0)),
+ new Matrix(new Vec(lshift, 0, height)),
+ new Matrix(new Vec(rshift, 0, height)),
+ new Matrix(new Vec(lshift, 0, -height)),
+ new Matrix(new Vec(rshift, 0, -height)),
new Matrix(new Vec( width, 0, 0)),
new Matrix(new Vec(-width, 0, 0)),
- /*
- new Matrix(new Vec( 0, 0, depth)),
- new Matrix(new Vec( 0, 0, -depth)),
- */
+
+ new Matrix(new Vec( 0, 0, height)),
+ new Matrix(new Vec( 0, 0, -height)),
};
- Point ltf = new Point(-(width/2), (height/2), (depth/2));
- Point mtf = new Point( 0.0, (height/2), (depth/2));
- Point rtf = new Point( (width/2), (height/2), (depth/2));
- Point ltn = new Point(-(width/2), (height/2), -(depth/2));
- Point mtn = new Point( 0.0, (height/2), -(depth/2));
- Point rtn = new Point( (width/2), (height/2), -(depth/2));
- Point lbf = new Point(-(width/2), -(height/2), (depth/2));
- Point mbf = new Point( 0.0, -(height/2), (depth/2));
- Point rbf = new Point( (width/2), -(height/2), (depth/2));
- Point lbn = new Point(-(width/2), -(height/2), -(depth/2));
- Point mbn = new Point( 0.0, -(height/2), -(depth/2));
- Point rbn = new Point( (width/2), -(height/2), -(depth/2));
+ Point ltf = new Point(lshift, (depth/2), (height/2));
+ Point mtf = new Point( 0.0, (depth/2), (height/2));
+ Point rtf = new Point(rshift, (depth/2), (height/2));
+ Point ltn = new Point(lshift, (depth/2), -(height/2));
+ Point mtn = new Point( 0.0, (depth/2), -(height/2));
+ Point rtn = new Point(rshift, (depth/2), -(height/2));
+ Point lbf = new Point(lshift, -(depth/2), (height/2));
+ Point mbf = new Point( 0.0, -(depth/2), (height/2));
+ Point rbf = new Point(rshift, -(depth/2), (height/2));
+ Point lbn = new Point(lshift, -(depth/2), -(height/2));
+ Point mbn = new Point( 0.0, -(depth/2), -(height/2));
+ Point rbn = new Point(rshift, -(depth/2), -(height/2));
Point[] points = new Point[] {
ltf,
// top
- tile.newT(ltf, mtf, mtn, null);
- tile.newT(mtn, ltn, ltf, null);
- tile.newT(mtf, rtf, rtn, null);
- tile.newT(rtn, mtn, mtf, null);
+ tile.newT(ltf, mtf, mtn, null, 1);
+ tile.newT(mtn, ltn, ltf, null, 1);
+ tile.newT(mtf, rtf, rtn, null, 1);
+ tile.newT(rtn, mtn, mtf, null, 1);
// bottom (swap normals)
- tile.newT(mbf, lbf, mbn, null);
- tile.newT(lbn, mbn, lbf, null);
- tile.newT(rbf, mbf, rbn, null);
- tile.newT(mbn, rbn, mbf, null);
+ tile.newT(mbf, lbf, mbn, null, 2);
+ tile.newT(lbn, mbn, lbf, null, 2);
+ tile.newT(rbf, mbf, rbn, null, 2);
+ tile.newT(mbn, rbn, mbf, null, 2);
// left
- tile.newT(ltf, ltn, lbn, null);
- tile.newT(lbn, lbf, ltf, null);
+ tile.newT(ltf, ltn, lbn, null, 3);
+ tile.newT(lbn, lbf, ltf, null, 3);
// right (swap normals)
- tile.newT(rtn, rtf, rbn, null);
- tile.newT(rbf, rbn, rtf, null);
+ tile.newT(rtn, rtf, rbn, null, 4);
+ tile.newT(rbf, rbn, rtf, null, 4);
// front
- tile.newT(ltn, mtn, mbn, null);
- tile.newT(ltn, mbn, lbn, null);
- tile.newT(mtn, rtn, rbn, null);
- tile.newT(mtn, rbn, mbn, null);
+ tile.newT(ltn, mtn, mbn, null, 5);
+ tile.newT(ltn, mbn, lbn, null, 5);
+ tile.newT(mtn, rtn, rbn, null, 5);
+ tile.newT(mtn, rbn, mbn, null, 5);
// back
- tile.newT(mtf, ltf, mbf, null);
- tile.newT(mbf, ltf, lbf, null);
- tile.newT(rtf, mtf, rbf, null);
- tile.newT(rbf, mtf, mbf, null);
+ tile.newT(mtf, ltf, mbf, null, 6);
+ tile.newT(mbf, ltf, lbf, null, 6);
+ tile.newT(rtf, mtf, rbf, null, 6);
+ tile.newT(rbf, mtf, mbf, null, 6);
for(Matrix m : translations) {
for(Mesh.T t1 : tile) {
}
public synchronized void breakit() {
- if (verts > 300) return;
+ if (verts > 800) return;
+ //while(verts < 800) {
PriorityQueue<Mesh.E> es = new PriorityQueue<Mesh.E>();
for(Mesh.E e : tile.edges()) es.add(e);
- for(int i=0; i<10; i++) {
+ for(int i=0; i<40; i++) {
Mesh.E e = es.poll();
verts++;
//System.out.println("shatter " + e);
e.shatter();
tile.rebindPoints();
}
+ //}
}
public synchronized void rand(double temperature, Mesh.Vert p) {
double goal_score = goal.score();
p.reComputeError();
+
Vec v = new Vec((random.nextFloat() - (float)0.5) / 1000,
(random.nextFloat() - (float)0.5) / 1000,
(random.nextFloat() - (float)0.5) / 1000);
- //Matrix inv = p.errorQuadric();
- //Vec v = new Vec(inv.d, inv.h, inv.l).norm().times(1/(float)1000);
-
+ /*
+ Matrix inv = p.errorQuadric();
+ Vec v = new Vec(inv.d, inv.h, inv.l).norm().times(1/(float)1000);
+ */
boolean good = p.move(v);
double new_tile_score = tile.score();
double new_goal_score = goal.score();
//double swapProbability = Math.exp((-1 * delta) / temperature);
//boolean doSwap = Math.random() < swapProbability;
boolean doSwap = good && (tile_delta <= 0 && goal_delta <= 0);
-
if (doSwap) {
tile_score = new_tile_score;
goal_score = new_goal_score;
for(Mesh.Vert v : hs) rand(10,v);
}
tile.rebuildPointSet();
+ repaint();
breakit();
repaint();
goal.unApplyQuadricToNeighborAll();
pointset.add(this);
}
+ private void glNormal(GL gl) {
+ Vec norm = norm();
+ gl.glNormal3f(norm.x, norm.y, norm.z);
+ }
+
public void recomputeFundamentalQuadric() {
- if (!quadricStale && fundamentalQuadric != null) return;
+ //if (!quadricStale && fundamentalQuadric != null) return;
quadricStale = false;
unApplyQuadricToNeighbor();
Matrix m = Matrix.ZERO;
oldscore = 0;
}
public void computeError() {
- oldscore = quadric_count == 0 ? 0 : (quadric.preAndPostMultiply(p) / quadric_count);
+ oldscore = quadric_count == 0 ? 0 : ((quadric.preAndPostMultiply(p) * 100) / quadric_count);
+ double ang = Math.abs(e.crossAngle());
+ if (ang < Math.PI * 0.2)
+ oldscore += ((Math.PI*0.2) - ang) * 10;
+ //System.out.println(oldscore);
score += oldscore;
}
// FIXME: intersection test needed?
boolean good = true;
+ /*
for(T t : Mesh.this) {
if (!good) break;
e = this.e;
do {
- if (!t.has(e.p1) && !t.has(e.p2) && e.t != null && e.intersects(t)) { good = false; break; }
+ if (!t.has(e.p1) && !t.has(e.p2) && e.intersects(t)) { good = false; break; }
+ if (e.t != null) {
+ if (!e.t.has(t.e1().p1) && !e.t.has(t.e1().p2) && t.e1().intersects(e.t)) { good = false; break; }
+ if (!e.t.has(t.e2().p1) && !e.t.has(t.e2().p2) && t.e2().intersects(e.t)) { good = false; break; }
+ if (!e.t.has(t.e3().p1) && !e.t.has(t.e3().p2) && t.e3().intersects(e.t)) { good = false; break; }
+ }
e = e.pair.next;
} while(e != this.e);
}
+*/
return good;
}
public BindingGroup(E e) { this(); set.add(e); }
public void add(E e) {
if (set.contains(e)) return;
- for (E epeer : e.bind_peers.set) {
- epeer.bind_peers = this;
- epeer.bind_to = bind_others;
- set.add(epeer);
- }
- for (E eother : e.bind_to.set) {
- bind_others.add(eother);
- }
+ set.add(e);
+ BindingGroup e_bind_peers = e.bind_peers;
+ BindingGroup e_bind_to = e.bind_to;
+ e.bind_peers = this;
+ e.bind_to = bind_others;
+ for (E epeer : e_bind_peers.set) add(epeer);
+ for (E eother : e_bind_to.set) bind_others.add(eother);
for(E eother : bind_others.set) {
if (e.next.bind_to.set.contains(eother.prev)) {
e.next.next.bindEdge(eother.prev.prev);
}
+ if (e.prev.bind_to.set.contains(eother.next)) {
+ e.prev.prev.bindEdge(eother.next.next);
+ }
}
}
public Point shatter() { return shatter(midpoint(), null, null); }
public Point shatter(Point mid, BindingGroup bg1, BindingGroup bg2) {
- if (shattered) return mid;
+ if (shattered || destroyed) return mid;
shattered = true;
Vert r = next.p2;
E next = this.next;
E prev = this.prev;
+ int old_colorclass = t==null ? 0 : t.colorclass;
if (bg1==null) bg1 = new BindingGroup();
if (bg2==null) bg2 = new BindingGroup();
+ BindingGroup old_bind_to = bind_to;
bind_peers.shatter(bg1, bg2);
- bind_to.shatter(bg2.other(), bg1.other());
+ old_bind_to.shatter(bg2.other(), bg1.other());
pair.shatter();
destroy();
- newT(r.p, p1.p, mid, null);
- newT(r.p, mid, p2.p, null);
+ newT(r.p, p1.p, mid, null, old_colorclass);
+ newT(r.p, mid, p2.p, null, old_colorclass);
bg1.add(p1.getE(mid));
bg2.add(p2.getE(mid).pair);
return mid;
prev.t = null;
pair.next.t = null;
pair.prev.t = 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;
}
private boolean added = false;
- public T makeT() { return t==null ? (t = new T(this)) : t; }
+ public T makeT(int colorclass) { return t==null ? (t = new T(this, colorclass)) : t; }
+
+ public double crossAngle() {
+ Vec v1 = t.norm().times(-1);
+ Vec v2 = pair.t.norm().times(-1);
+ return Math.acos(v1.norm().dot(v2.norm()));
+ }
/** angle between this half-edge and the next */
public double angle() {
if (v2 != null) return new E(v2.getFreeIncident(), p1).pair;
return new E(p1, p2);
}
- public T newT(Point p1, Point p2, Point p3, Vec norm) {
+ public T newT(Point p1, Point p2, Point p3, Vec norm, int colorclass) {
if (norm != null) {
Vec norm2 = p3.minus(p1).cross(p2.minus(p1));
float dot = norm.dot(norm2);
e23.makeAdjacent(e31);
e31.makeAdjacent(e12);
}
- T ret = e12.makeT();
+ T ret = e12.makeT(colorclass);
if (e12.t == null) throw new Error();
if (e23.t == null) throw new Error();
if (e31.t == null) throw new Error();
public final class T extends Triangle {
public final E e1;
public final int color;
+ public final int colorclass;
public void destroy() {
}
- T(E e1) {
+ T(E e1, int colorclass) {
this.e1 = e1;
E e2 = e1.next;
E e3 = e2.next;
break;
}
this.color = color;
+ this.colorclass = colorclass;
}
public E e1() { return e1; }
public E e2() { return e1.next; }
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 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);
+ }
}
}
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
gl.glMatrixMode(GL.GL_MODELVIEW);
+
+ float mat_specular[] = { 0.5f, 0.5f, 0.5f, 0.5f };
+ float mat_shininess[] = { 50.0f };
+ gl.glShadeModel(GL.GL_SMOOTH);
+ gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, mat_specular, 0);
+ //gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, mat_specular, 0);
+ gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT, new float[] { 0.3f, 0.3f, 0.3f, 0.3f }, 0);
+ //gl.glMaterialfv(GL.GL_FRONT, GL.GL_SHININESS, mat_shininess, 0);
+ gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[] { 1.0f, 4.0f, -10.0f, 0.0f }, 0);
+ gl.glLightfv(GL.GL_LIGHT1, GL.GL_POSITION, new float[] { -10.0f, 10.0f, 10.0f, 0.0f }, 0);
+ gl.glLightfv(GL.GL_LIGHT2, GL.GL_POSITION, new float[] { 10.0f, -10.0f, 10.0f, 0.0f }, 0);
+ gl.glLightfv(GL.GL_LIGHT3, GL.GL_POSITION, new float[] { 10.0f, 10.0f, -10.0f, 0.0f }, 0);
+ gl.glLightfv(GL.GL_LIGHT4, GL.GL_POSITION, new float[] { -10.0f, 10.0f, -10.0f, 0.0f }, 0);
+ gl.glLightfv(GL.GL_LIGHT5, GL.GL_POSITION, new float[] { 10.0f, -10.0f, -10.0f, 0.0f }, 0);
+ gl.glEnable(GL.GL_LIGHTING);
+ gl.glEnable(GL.GL_LIGHT0);
+ gl.glEnable(GL.GL_LIGHT1);
+ gl.glEnable(GL.GL_LIGHT2);
+ gl.glEnable(GL.GL_LIGHT3);
+ gl.glEnable(GL.GL_LIGHT4);
+ gl.glEnable(GL.GL_LIGHT5);
+
+ gl.glColorMaterial(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT_AND_DIFFUSE);
+ gl.glEnable(GL.GL_COLOR_MATERIAL);
+
display(gld);
}
gl.glBegin(GL.GL_TRIANGLES);
gl.glColor4f((float)0.5, (float)0.5, (float)0.5, (float)0.8);
- //draw(gl, false, goal);
+ draw(gl, false, goal);
gl.glEnd();
for(Matrix m : translations) {
//if (v1.z==0 && v1.y==0) continue;
i++;
- if (i != 1 /*&& i!=4*/) continue;
+ if (i != 7 /*&& i!=4*/) continue;
Point p = new Point(0, 0, 0).times(m);
Vec v = new Vec(p.x, p.y, p.z);
v = v.times((float)1.04);
gl.glTranslatef(-v.x, -v.y, -v.z);
}
//gl.glEnable(GL.GL_DEPTH_TEST);
+ gl.glEnable (GL.GL_LIGHTING);
}
private synchronized void draw(GL gl, boolean triangles, Mesh mesh) {
green -= .12f;
blue -= .15f;
- if (triangles) switch(t.color) {
+ if (triangles) switch(t.color/*class*/) {
case 0: gl.glColor4f((float)0.25, (float)0.25, (float)0.75, (float)0.3); break;
case 1: gl.glColor4f((float)0.25, (float)0.75, (float)0.25, (float)0.3); break;
case 2: gl.glColor4f((float)0.75, (float)0.25, (float)0.25, (float)0.3); break;
case 3: gl.glColor4f((float)0.50, (float)0.50, (float)0.50, (float)0.3); break;
+ case 4: gl.glColor4f((float)0.25, (float)0.75, (float)0.75, (float)0.3); break;
+ case 5: gl.glColor4f((float)0.25, (float)0.75, (float)0.75, (float)0.3); break;
+ case 6: gl.glColor4f((float)0.75, (float)0.25, (float)0.75, (float)0.3); break;
}
//gl.glBegin(GL.GL_LINES);
t.glVertices(gl);
gl.glEnd();
} else {
+ gl.glDisable(GL.GL_LIGHTING);
gl.glBegin(GL.GL_LINES);
+ gl.glColor3f(1, 1, 1);
t.e1().p1.p.glVertex(gl);
t.e1().p2.p.glVertex(gl);
t.e2().p1.p.glVertex(gl);
t.e3().p1.p.glVertex(gl);
t.e3().p2.p.glVertex(gl);
gl.glEnd();
+ gl.glEnable(GL.GL_LIGHTING);
}
Point centroid = t.centroid();
if (mesh==goal)
for(Mesh.Vert p : new Mesh.Vert[] { t.v1(), t.v2(), t.v3() }) {
- p.p.glVertex(gl);
+ //p.p.glVertex(gl);
//p.plus(p.norm().times(p.score()*10)).glVertex(gl);
//p.partner().p.glVertex(gl);
//tile.nearest(p).centroid().glVertex(gl);