1 package nl.tudelft.goal.ut2004.visualizer.timeline.map;
2
3 import java.awt.Point;
4 import java.nio.IntBuffer;
5 import java.util.Arrays;
6 import java.util.Collections;
7 import java.util.Comparator;
8 import java.util.LinkedList;
9 import java.util.List;
10
11 import javax.media.opengl.GL;
12 import javax.media.opengl.GL2;
13 import javax.media.opengl.GLAutoDrawable;
14 import javax.media.opengl.GLEventListener;
15 import javax.media.opengl.glu.GLU;
16 import javax.vecmath.Vector3d;
17 import static javax.media.opengl.GL.*;
18 import static javax.media.opengl.GL2.*;
19 import com.jogamp.opengl.util.gl2.GLUT;
20 import nl.tudelft.goal.ut2004.visualizer.map.BlendTriangle;
21
22 import com.jogamp.common.nio.Buffers;
23
24 import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
25
26
27
28
29
30
31
32
33 public class EnvironmentRenderer implements GLEventListener {
34 private static GLU glu = new GLU();
35 private static GLUT glut = new GLUT();
36
37 private MapViewpoint viewpoint;
38 private GLRendererCollection<IRenderableUTAgent> agentRenderes;
39 private GLRendererCollection<IRenderableWorldObject> objectRenderes;
40 private MapRenderer mapRenderer;
41
42 public EnvironmentRenderer(MapViewpoint viewpoint, GLRendererCollection<IRenderableUTAgent> agentRenderes,
43 GLRendererCollection<IRenderableWorldObject> objectRenderes, MapRenderer mapRenderer) {
44 this.viewpoint = viewpoint;
45 this.agentRenderes = agentRenderes;
46 this.objectRenderes = objectRenderes;
47 this.mapRenderer = mapRenderer;
48
49 }
50
51 @Override
52 public synchronized void init(GLAutoDrawable glDrawable) {
53 GL2 gl = glDrawable.getGL().getGL2();
54
55 gl.glMatrixMode(GL_PROJECTION);
56 gl.glLoadIdentity();
57 gl.glMatrixMode(GL_MODELVIEW);
58 gl.glLoadIdentity();
59
60 gl.glEnable(GL.GL_DEPTH_TEST);
61 gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
62
63 gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
64 gl.glClearDepth(1.0);
65 gl.glShadeModel(GL_SMOOTH);
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 gl.glDisable(GL_LIGHTING);
83
84
85 agentRenderes.prepare(gl);
86 objectRenderes.prepare(gl);
87 mapRenderer.prepare(gl);
88 }
89
90 @Override
91 public synchronized void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
92 GL2 gl = drawable.getGL().getGL2();
93 setProjection(gl, x, y, width, height);
94 }
95
96
97
98
99 private synchronized void setProjection(GL2 gl, int x, int y, int width, int height) {
100 if (height <= 0) {
101 height = 1;
102 }
103 float h = (float) width / (float) height;
104 gl.glViewport(0, 0, width, height);
105 gl.glMatrixMode(GL_PROJECTION);
106 gl.glLoadIdentity();
107 glu.gluPerspective(viewpoint.getViewAngle(), h, 10.0, 100000.0);
108 gl.glMatrixMode(GL_MODELVIEW);
109 gl.glLoadIdentity();
110 }
111
112
113
114
115
116
117 private synchronized void prepareCanvas(GL2 gl) {
118
119 gl.glEnable(GL_DEPTH_TEST);
120 gl.glClearColor(0.45f, 0.45f, 0.45f, 0f);
121
122 gl.glClear(GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
123
124
125 gl.glMatrixMode(GL_MODELVIEW);
126 gl.glLoadIdentity();
127
128
129 Location observerLoc = viewpoint.getLocation();
130 Location eyeLoc = viewpoint.getEye();
131 Vector3d upVec = viewpoint.getUp();
132
133
134 glu.gluLookAt(eyeLoc.x, eyeLoc.y, eyeLoc.z, observerLoc.x, observerLoc.y, observerLoc.z, upVec.x, upVec.y,
135 upVec.z);
136
137 gl.glScaled(1., 1., -1.);
138 }
139
140 int loops = 0;
141
142 @Override
143 public synchronized void display(GLAutoDrawable glDrawable) {
144 GL2 gl = glDrawable.getGL().getGL2();
145
146 int viewport[] = new int[4];
147 gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
148
149
150
151
152
153 int[] selectBufferArray = new int[512];
154 IntBuffer selectBuffer = Buffers.newDirectIntBuffer(selectBufferArray.length);
155
156 gl.glSelectBuffer(selectBufferArray.length, selectBuffer);
157
158
159
160
161 gl.glRenderMode(GL_SELECT);
162
163
164
165 gl.glInitNames();
166 gl.glPushName(-1);
167
168
169
170 gl.glMatrixMode(GL_PROJECTION);
171 gl.glPushMatrix();
172 {
173 gl.glLoadIdentity();
174
175
176 glu.gluPickMatrix(selectPoint.x, viewport[3] - selectPoint.y, 1.0f, 1.0f, viewport, 0);
177 glu.gluPerspective(viewpoint.getViewAngle(), (float) viewport[2] / (float) viewport[3], 10.0, 100000.0);
178
179 prepareCanvas(gl);
180 mapRenderer.render(gl);
181 agentRenderes.render(gl);
182 objectRenderes.render(gl);
183 gl.glMatrixMode(GL_PROJECTION);
184 }
185 gl.glPopMatrix();
186
187 gl.glMatrixMode(GL_MODELVIEW);
188
189
190
191
192
193
194 int numOfHits = gl.glRenderMode(GL_RENDER);
195 selectBuffer.get(selectBufferArray);
196
197
198 selectedObjects = new int[numOfHits];
199 for (int hitIndex = 0; hitIndex < numOfHits; hitIndex++) {
200 selectedObjects[hitIndex] = selectBufferArray[hitIndex * 4 + 3];
201 }
202
203 this.selectDirtyFlag = false;
204
205 prepareCanvas(gl);
206
207
208 mapRenderer.render(gl);
209 agentRenderes.render(gl);
210 objectRenderes.render(gl);
211
212 gl.glEnable(GL_BLEND);
213 gl.glEnable(GL_LIGHTING);
214 gl.glBegin(GL_TRIANGLES);
215
216
217 List<BlendTriangle> blendPolys = painterSort(mapRenderer.getBlendedTris());
218
219 for (BlendTriangle triangle : blendPolys) {
220 for (int i = 0; i < 3; i++) {
221 GlColor col = triangle.getVerts()[i].getColor();
222 gl.glColor4d(col.r, col.g, col.b, col.a);
223
224 Location loc = triangle.getVerts()[i].getLocation();
225 gl.glVertex3d(loc.x, loc.y, loc.z);
226 }
227 }
228 gl.glEnd();
229 gl.glDisable(GL_LIGHTING);
230 gl.glDisable(GL_BLEND);
231
232
233 String res = "[" + selectPoint.x + ", " + selectPoint.y + "] # " + numOfHits;
234 for (int objId : selectedObjects) {
235 res += ":" + objId;
236 }
237 renderText(gl, res, 0, 0, GLUT.BITMAP_HELVETICA_12);
238
239 loops++;
240 }
241
242
243
244
245
246
247
248
249
250
251
252
253
254 private List<BlendTriangle> painterSort(List<BlendTriangle> orgPolys) {
255 List<BlendTriangle> polys = new LinkedList<BlendTriangle>(orgPolys);
256 final Location eyeLoc = this.viewpoint.getEye();
257
258 Collections.sort(polys, new Comparator<BlendTriangle>() {
259 @Override
260 public int compare(BlendTriangle o1, BlendTriangle o2) {
261 if (maxDistance(o1) < maxDistance(o2))
262 return -1;
263 if (maxDistance(o1) > maxDistance(o2))
264 return 1;
265
266 return 0;
267 }
268
269
270
271
272
273 private double maxDistance(BlendTriangle tri) {
274 double max = Double.MIN_VALUE;
275
276 for (int i = 0; i < 3; i++) {
277 Location vertloc = tri.getVerts()[i].getLocation();
278 if (Location.getDistance(vertloc, eyeLoc) > max) {
279 max = Location.getDistance(vertloc, eyeLoc);
280 }
281 }
282 return max;
283 }
284
285 });
286
287 return polys;
288 }
289
290 private void renderText(GL2 gl, String text, int x, int y, int font) {
291 int viewport[] = new int[4];
292 gl.glGetIntegerv(GL_VIEWPORT, viewport, 0);
293
294 gl.glMatrixMode(GL_MODELVIEW);
295 gl.glPushMatrix();
296 gl.glLoadIdentity();
297 gl.glMatrixMode(GL_PROJECTION);
298 gl.glPushMatrix();
299 gl.glLoadIdentity();
300 {
301 gl.glOrtho(0, viewport[2], 0, viewport[3], -1, 1);
302 gl.glColor3d(1, 1, 1);
303 gl.glRasterPos3d(0, 0, 0);
304 glut.glutBitmapString(font, text);
305 }
306 gl.glMatrixMode(GL_PROJECTION);
307 gl.glPopMatrix();
308 gl.glMatrixMode(GL_MODELVIEW);
309 gl.glPopMatrix();
310
311 }
312
313
314 private boolean selectDirtyFlag = true;
315
316
317 private Point selectPoint = new Point();
318
319 private int[] selectedObjects = new int[0];
320
321 public synchronized int[] getSelectedObjects() throws IllegalStateException {
322 if (selectDirtyFlag) {
323 throw new IllegalStateException(
324 "Not objects from selected point. Did you call display() after setSelectPoint()?");
325 }
326
327 return Arrays.copyOf(selectedObjects, selectedObjects.length);
328 }
329
330
331
332
333
334
335
336 public synchronized void setSelectPoint(Point point) {
337 if (point == null) {
338 throw new IllegalArgumentException("Point cannot be null");
339 }
340
341 this.selectPoint = new Point(point);
342 this.selectDirtyFlag = true;
343 }
344
345 SelectionHit hi = new SelectionHit(loops);
346
347 public static class SelectionHit {
348
349
350
351
352
353
354 private SelectionHit(int z) {
355
356 }
357 }
358
359 @Override
360 public void dispose(GLAutoDrawable arg0) {
361
362
363 }
364 }