c5c6a3b9cd088fc6249f7df8e672527331da3d67
[anneal.git] / src / edu / berkeley / qfat / MeshViewer.java
1 package edu.berkeley.qfat;
2 import java.io.*;
3 import java.awt.*;
4 import java.awt.event.*;
5 import javax.swing.*;
6 import javax.media.opengl.*;
7 import javax.media.opengl.glu.*;
8 import com.sun.opengl.util.*;
9 import java.util.*;
10 import edu.berkeley.qfat.geom.*;
11 import edu.berkeley.qfat.geom.Point;
12
13 public class MeshViewer implements GLEventListener, MouseListener, MouseMotionListener, KeyListener, MouseWheelListener  {
14
15     public Mesh tile = new Mesh(false);
16     public Mesh goal = new Mesh(false);
17     public Matrix[] transforms;
18     public Mesh.Vertex[] points;
19
20     public double temp;
21     public boolean tileon = true;
22     public boolean tilemeshon = false;
23     public boolean goalon = true;
24     public boolean anneal = false;
25     public boolean neighbors = false;
26     public boolean neighborsWire = false;
27     public boolean neighborsWireOne = false;
28
29     public int breaks = 0;
30     boolean alt = false;
31     boolean shift = false;
32     boolean control = false;
33
34     public void mouseWheelMoved(MouseWheelEvent e) {
35         tz -= e.getWheelRotation();
36     }
37
38     public void keyTyped(KeyEvent e)  { }
39     public void keyPressed(KeyEvent e)  {
40         switch(e.getKeyCode()) {
41             case KeyEvent.VK_CONTROL: control = true; break;
42             case KeyEvent.VK_ALT: alt = true; break;
43             case KeyEvent.VK_SHIFT: shift = true; break;
44             case KeyEvent.VK_SPACE: breaks++; break;
45             case KeyEvent.VK_UP: temp = temp * 2; break;
46             case KeyEvent.VK_ENTER: temp = 10; break;
47             case KeyEvent.VK_D: dump(); break;
48             case KeyEvent.VK_A: anneal = !anneal; break;
49             case KeyEvent.VK_N: neighbors = !neighbors; break;
50             case KeyEvent.VK_T: tileon = !tileon; break;
51             case KeyEvent.VK_G: goalon = !goalon; break;
52             case KeyEvent.VK_M: tilemeshon = !tilemeshon; break;
53         }
54     }
55     public synchronized void dump() {
56         try {
57         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("dump.stl")));
58         pw.println("solid dump");
59         for(Mesh.T t : tile) {
60             Vec normal = t.norm();
61             pw.println("facet normal " + normal.x + " " + normal.y + " " + normal.z);
62             pw.println("  outer loop");
63             for(Mesh.Vertex v : new Mesh.Vertex[] { t.v1(), t.v2(), t.v3() }) {
64                 pw.println("    vertex " + v.p.x + " " + v.p.y + " " + v.p.z);
65             }
66             pw.println("  endloop");
67             pw.println("endfacet");
68         }
69         pw.println("endsolid dump");
70         pw.flush();
71         pw.close();
72         } catch (Exception e) { throw new RuntimeException(e); }
73     }
74     public void keyReleased(KeyEvent e) {
75         switch(e.getKeyCode()) {
76             case KeyEvent.VK_CONTROL: control = false; break;
77             case KeyEvent.VK_ALT: alt = false; break;
78             case KeyEvent.VK_SHIFT: shift = false; break;
79         }
80     }
81
82     public void mouseClicked(MouseEvent e) { }
83     public void mouseEntered(MouseEvent e) { }
84     public void mouseExited(MouseEvent e) { }
85     public void mousePressed(MouseEvent e) { }
86     public void mouseReleased(MouseEvent e) { }
87
88     int mousex;
89     int mousey;
90     public void mouseMoved(MouseEvent e) {
91         mousex = e.getX();
92         mousey = e.getY();
93     }
94
95     float tx = 0;
96     float ty = 0;
97     float tz = 0;
98     float anglex = 0;
99     float angley = 0;
100     public void mouseDragged(MouseEvent e) {
101         if (shift) {
102             tx += (mousex - e.getX())/(float)20;
103             ty += (mousey - e.getY())/(float)20;
104         } else {
105             anglex -= mousex - e.getX();
106             angley += mousey - e.getY();
107         }
108         mousex = e.getX();
109         mousey = e.getY();
110     }
111
112     /**
113      * Take care of initialization here.
114      */
115     public void init(GLAutoDrawable gld) {
116         GL gl = gld.getGL();
117         gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
118         gl.glViewport(0, 0, 500, 300);
119         gl.glEnable(GL.GL_DEPTH_TEST);
120         gl.glClearDepth(1.0);
121         gl.glDepthFunc(GL.GL_LEQUAL);
122         gl.glMatrixMode(GL.GL_PROJECTION);
123         gl.glLoadIdentity();
124         gl.glMatrixMode(GL.GL_MODELVIEW);
125
126         float mat_specular[] = { 0.5f, 0.5f, 0.5f, 0.5f };
127         float mat_shininess[] = { 50.0f };
128         gl.glShadeModel(GL.GL_SMOOTH);
129         //gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, mat_specular, 0);
130         //gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, mat_specular, 0);  
131         //gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT, new float[] { 0.3f, 0.3f, 0.3f, 0.3f }, 0);  
132         //gl.glMaterialfv(GL.GL_FRONT, GL.GL_SHININESS, mat_shininess, 0);
133         gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[] { 1.0f,    4.0f,  -10.0f, 0.0f }, 0);
134         gl.glLightfv(GL.GL_LIGHT1, GL.GL_POSITION, new float[] { -10.0f, 10.0f,   10.0f, 0.0f }, 0);
135         gl.glLightfv(GL.GL_LIGHT2, GL.GL_POSITION, new float[] { 10.0f, -10.0f,   10.0f, 0.0f }, 0);
136         gl.glLightfv(GL.GL_LIGHT3, GL.GL_POSITION, new float[] { 10.0f,  10.0f,  -10.0f, 0.0f }, 0);
137         gl.glLightfv(GL.GL_LIGHT4, GL.GL_POSITION, new float[] { -10.0f, 10.0f,  -10.0f, 0.0f }, 0);
138         gl.glLightfv(GL.GL_LIGHT5, GL.GL_POSITION, new float[] { 10.0f, -10.0f,  -10.0f, 0.0f }, 0);
139         gl.glEnable(GL.GL_LIGHTING);
140         gl.glEnable(GL.GL_LIGHT0);
141         /*
142         gl.glEnable(GL.GL_LIGHT1);
143         gl.glEnable(GL.GL_LIGHT2);
144         gl.glEnable(GL.GL_LIGHT3);
145         gl.glEnable(GL.GL_LIGHT4);
146         gl.glEnable(GL.GL_LIGHT5);
147         */
148         gl.glColorMaterial(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT_AND_DIFFUSE);
149         gl.glEnable(GL.GL_COLOR_MATERIAL);
150
151         display(gld);
152     }
153
154     public int temps;
155     public int accepts;
156     public    int vertss;
157     public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
158     public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { }
159     public synchronized void display(GLAutoDrawable drawable) {
160
161         if (transforms==null) return;
162
163
164         glcanvas.setSize(f.getWidth(), f.getHeight() - 100);
165         Graphics2D g = (Graphics2D)f.getGraphics();
166         g.setColor(Color.black);
167         g.fillRect(0, f.getHeight()-100, f.getWidth(), f.getHeight());
168         g.setColor(Color.red);
169         int top = f.getHeight()-70;
170         g.drawString("temperature: "+temps, 10, 30+top);
171         g.drawString("acceptance: "+accepts, 10, 50+top);
172         g.drawString("vertices: "+vertss, 10, 70+top);
173         g.fillRect(140, 25+top, temps, 10);
174         g.fillRect(140, 45+top, accepts, 10);
175         g.fillRect(140, 65+top, vertss, 10);
176
177         GL gl = drawable.getGL();
178         GLU glu = new GLU();
179         gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
180         gl.glPointSize(5.0f);
181         gl.glLoadIdentity();
182         glu.gluPerspective(50, ((float)drawable.getWidth())/drawable.getHeight(), 0.5, 10);
183         glu.gluLookAt(0, 0, (tz/10)-1, 0, 0, 0, 0, 1, 0);
184         gl.glRotatef(anglex/3, 0, 1, 0);
185         gl.glRotatef(angley/3, 1, 0, 0);
186
187         gl.glBegin(GL.GL_TRIANGLES);
188         if (tileon)
189         draw(gl, true, safeTriangles);
190         if (tilemeshon)
191         draw(gl, false, safeTriangles);
192         gl.glEnd();
193
194         //draw(gl, false, tile);
195
196         gl.glBegin(GL.GL_TRIANGLES);
197         gl.glColor4f((float)0.5, (float)0.5, (float)0.5, (float)0.8);
198         if (goalon)
199             draw(gl, false, goal);
200         gl.glEnd();
201
202
203         int i = 0;
204         //gl.glDisable(GL.GL_DEPTH_TEST);
205         gl.glColor4f(1,1,1,1);
206         for(Matrix m : transforms) {
207             //if (v1.z==0 && v1.y==0) continue;
208             i++;
209             if (neighborsWireOne && i>1) continue;
210             //if (i>4) continue;
211             /*
212             Point p = new Point(0, 0, 0).times(m);
213             Vec v = new Vec(p.x, p.y, p.z);
214             v = v.times((float)1.04);
215             gl.glTranslatef(v.x, v.y, v.z);
216             */
217             if (neighbors) draw(gl, true, safeTriangles, m);
218             else if (neighborsWire || neighborsWireOne) draw(gl, false, safeTriangles, m);
219             /*
220             gl.glTranslatef(-v.x, -v.y, -v.z);
221             */
222         }
223         //gl.glEnable(GL.GL_DEPTH_TEST);
224         gl.glEnable (GL.GL_LIGHTING);
225
226     }
227
228     protected HashSet<Mesh.T> safeTriangles = new HashSet<Mesh.T>();
229
230     private void draw(GL gl, boolean triangles, Iterable<Mesh.T> tris) { draw(gl, triangles, tris, Matrix.ONE); }
231     private void draw(GL gl, boolean triangles, Iterable<Mesh.T> tris, Matrix m) {
232         float red = 0.0f;
233         float green = 0.0f;
234         float blue = 0.0f;
235         synchronized(safeTriangles) {
236         for(Mesh.T t : tris) {
237             if (red < 0.15) red = 1.0f;
238             if (green < 0.15) green = 1.0f;
239             if (blue < 0.15) blue = 1.0f;
240             red -= .09f;
241             green -= .12f;
242             blue -= .15f;
243
244             if (triangles) switch(t.color/*class*/) {
245                 case 0: gl.glColor4f((float)0.25, (float)0.25, (float)0.75, (float)0.3); break;
246                 case 1: gl.glColor4f((float)0.25, (float)0.75, (float)0.25, (float)0.3); break;
247                 case 2: gl.glColor4f((float)0.75, (float)0.25, (float)0.25, (float)0.3); break;
248                 case 3: gl.glColor4f((float)0.50, (float)0.50, (float)0.50, (float)0.3); break;
249                 case 4: gl.glColor4f((float)0.25, (float)0.75, (float)0.75, (float)0.3); break;
250                 case 5: gl.glColor4f((float)0.25, (float)0.75, (float)0.75, (float)0.3); break;
251                 case 6: gl.glColor4f((float)0.75, (float)0.25, (float)0.75, (float)0.3); break;
252             }
253             /*
254             if (t.e1().pair.t==null) gl.glColor4f((float)0.25, (float)0.25, (float)0.75, (float)0.3);
255             else if (t.e2().pair.t==null) gl.glColor4f((float)0.25, (float)0.25, (float)0.75, (float)0.3);
256             else if (t.e3().pair.t==null) gl.glColor4f((float)0.25, (float)0.25, (float)0.75, (float)0.3);
257             else  gl.glColor4f((float)0.75, (float)0.25, (float)0.25, (float)0.3);
258             */
259             //gl.glBegin(GL.GL_LINES);
260
261             if (triangles) {
262                 gl.glBegin(GL.GL_TRIANGLES);
263                 if (t.shouldBeDrawn()) {
264                     m.times(t.norm()).glNormal(gl);
265                     m.times(t.v1().goodp).glVertex(gl);
266                     m.times(t.v2().goodp).glVertex(gl);
267                     m.times(t.v3().goodp).glVertex(gl);
268                     //t.glVertices(gl, m);
269                 }
270                 gl.glEnd();
271             } else {
272                 gl.glDisable(GL.GL_LIGHTING);
273                 gl.glBegin(GL.GL_LINES);
274                 gl.glColor3f(1, 1, 1);
275                 m.times(t.e1().p1.goodp).glVertex(gl);
276                 m.times(t.e1().p2.goodp).glVertex(gl);
277                 m.times(t.e2().p1.goodp).glVertex(gl);
278                 m.times(t.e2().p2.goodp).glVertex(gl);
279                 m.times(t.e3().p1.goodp).glVertex(gl);
280                 m.times(t.e3().p2.goodp).glVertex(gl);
281                 gl.glEnd();
282                 gl.glEnable(GL.GL_LIGHTING);
283             }
284
285             Point centroid = t.centroid();
286             gl.glBegin(GL.GL_LINES);
287             gl.glColor3f(1, 1, 1);
288             /*
289             centroid.glVertex(gl);
290             centroid.plus(t.norm().times(t.diameter())).glVertex(gl);
291             */
292             /*
293             if (mesh==goal)
294                 for(Mesh.Vertex p : new Mesh.Vertex[] { t.v1(), t.v2(), t.v3() }) {
295                 gl.glDisable(GL.GL_LIGHTING);
296                 gl.glBegin(GL.GL_LINES);
297                 gl.glColor3f(1, 1, 1);
298                 p.p.glVertex(gl);
299                 //p.p.plus(p.norm().times(p.score())).glVertex(gl);
300                 if (p.nearest_in_other_mesh != null) p.nearest_in_other_mesh.p.glVertex(gl);
301                     //tile.nearest(p).centroid().glVertex(gl);
302                 gl.glEnd();
303                 gl.glEnable(GL.GL_LIGHTING);
304                 }
305             */
306             gl.glEnd();
307         }
308         }
309     }
310
311
312     //private JTextArea ocanvas = new JTextArea();
313     private JFrame f;
314     private GLCanvas glcanvas;
315     public MeshViewer(JFrame f) {
316         this.f = f;
317        GLCapabilities glcaps = new GLCapabilities();
318         glcanvas = new GLCanvas();
319         glcanvas.addGLEventListener(this);
320         f.add(glcanvas, BorderLayout.CENTER);
321
322         glcanvas.addMouseListener(this);
323         glcanvas.addMouseMotionListener(this);
324         glcanvas.addMouseWheelListener(this);
325         glcanvas.addKeyListener(this);
326     }
327     public void repaint() {
328         glcanvas.repaint();
329     }
330
331
332
333 }