1 package nl.tudelft.goal.ut2004.visualizer.timeline.map;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.LinkedList;
6 import java.util.List;
7 import java.util.logging.Level;
8 import java.util.logging.Logger;
9
10 import javax.media.opengl.GL;
11 import javax.media.opengl.GL2;
12 import javax.media.opengl.glu.GLU;
13 import javax.media.opengl.glu.GLUquadric;
14
15 import nl.tudelft.goal.ut2004.visualizer.map.BlendTriangle;
16 import nl.tudelft.goal.ut2004.visualizer.services.ISelectionHandler;
17
18 import com.jogamp.opengl.util.gl2.GLUT;
19 import static javax.media.opengl.GL.*;
20 import static javax.media.opengl.GL2.*;
21
22 import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
23 import cz.cuni.amis.pogamut.base3d.worldview.object.Rotation;
24 import cz.cuni.amis.pogamut.unreal.communication.worldview.map.IUnrealMap;
25
26
27
28
29
30
31
32
33
34
35
36 public class UTAgentSubGLRenderer implements ISubGLRenderer<IRenderableUTAgent> {
37
38 private static Logger logger;
39 private static GLU glu;
40 private static GLUT glut;
41 private static GLUquadric quadratic;
42
43
44
45
46 private final IRenderableUTAgent agent;
47 private final IUnrealMap map;
48 private final double SPHERE_RADIUS = 60;
49 private final int SPHERE_SLICES = 32;
50 private final int SPHERE_STACKS = 32;
51
52
53
54
55
56
57
58 public UTAgentSubGLRenderer(IRenderableUTAgent utAgent, IUnrealMap map) {
59 this.agent = utAgent;
60 this.map = map;
61 }
62
63 @Override
64 public void prepare(GL gl) {
65 glu = new GLU();
66 glut = new GLUT();
67 quadratic = glu.gluNewQuadric();
68
69 logger = Logger.getLogger("TLMapRenderer");
70 logger.setLevel(Level.INFO);
71 }
72
73 @Override
74 public IRenderableUTAgent getObject() {
75 return agent;
76 }
77
78 @Override
79 public void render(GL gla) {
80 GL2 gl = gla.getGL2();
81
82 try {
83 Location entityLocation = agent.getLocation();
84 if (entityLocation == null) {
85 return;
86 }
87
88 Location center = new Location(entityLocation.x, entityLocation.y, entityLocation.z + SPHERE_RADIUS * 1.1);
89 GlColor color = new GlColor(agent.getColor());
90
91 gl.glLoadName(agent.getGLName());
92
93 renderAgent(gl, color, center);
94 gl.glLoadName(-1);
95 renderInfo(gl, color, center);
96 renderFade(gl, color, agent.getFadeLine());
97
98
99
100
101
102
103
104 } catch (RuntimeException e) {
105 e.printStackTrace();
106
107 }
108 }
109
110
111
112
113
114
115
116 private void renderAgent(GL gla, GlColor color, Location position) {
117 GL2 gl = gla.getGL2();
118
119 gl.glPushMatrix();
120 {
121 gl.glTranslated(position.x, position.y, position.z);
122
123 gl.glColor4d(color.r, color.g, color.b, color.a);
124 glu.gluSphere(quadratic, SPHERE_RADIUS, SPHERE_SLICES, SPHERE_STACKS);
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 }
140 gl.glPopMatrix();
141
142 Rotation rot = agent.getRotation();
143 if (rot != null) {
144 renderRotation(gl, new GlColor(1, 0, 0), position, rot);
145 }
146
147
148
149
150
151 }
152
153 private ISelectionHandler getSelectionHandler() {
154
155 return null;
156 }
157
158
159
160
161
162
163
164
165
166
167
168
169
170 private void renderRotation(GL gla, GlColor color, Location center, Rotation rotation) {
171 GL2 gl = gla.getGL2();
172
173 gl.glPushMatrix();
174 {
175 gl.glTranslated(center.x, center.y, center.z);
176
177 Location endOfArrow = rotation.toLocation().getNormalized().scale(SPHERE_RADIUS * 2.5);
178
179 gl.glBegin(GL.GL_LINES);
180 gl.glColor4d(color.r, color.g, color.b, color.a);
181 gl.glVertex3d(0, 0, 0);
182 gl.glVertex3d(endOfArrow.x, endOfArrow.y, endOfArrow.z);
183 gl.glEnd();
184
185 gl.glTranslated(endOfArrow.x, endOfArrow.y, endOfArrow.z);
186
187
188
189
190
191
192 double yaw = rotation.getYaw() / 32767 * 180;
193
194 double roll = rotation.getRoll() / 32767 * 180;
195
196 double pitch = rotation.getPitch() / 32767 * 180;
197
198
199
200
201
202
203
204 if (logger.isLoggable(Level.FINE))
205 logger.fine(" Rotation: Yaw " + yaw + " roll " + roll + " pitch " + pitch);
206
207
208 gl.glRotated(yaw, 0, 0, 1);
209
210
211 gl.glRotated(90, 0, 1, 0);
212
213 glut.glutSolidCone(20, 40, 16, 16);
214 }
215 gl.glPopMatrix();
216
217 }
218
219
220
221
222
223
224
225
226
227
228 private void renderFade(GL gla, GlColor color, IFadeLine fadeline) {
229 GL2 gl = gla.getGL2();
230
231 gl.glEnable(GL_BLEND);
232 gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
233
234 gl.glBegin(GL_QUADS);
235
236 Location lastLocation = null;
237 double lastAlpha = 0;
238
239 for (long ms = 0; ms < fadeline.getDuration(); ms += 100) {
240 Location currentLocation = fadeline.getPosition(ms);
241 double currentAlpha = ((double) ms) / fadeline.getDuration();
242
243 if (lastLocation == null) {
244 lastLocation = currentLocation;
245 lastAlpha = currentAlpha;
246 continue;
247 }
248
249 if (currentLocation != null) {
250 pushFadeQuad(gl, color, currentLocation, lastLocation, currentAlpha, lastAlpha);
251
252 lastLocation = currentLocation;
253 lastAlpha = currentAlpha;
254 }
255 }
256
257 gl.glEnd();
258
259 gl.glDisable(GL_BLEND);
260 }
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279 private void pushFadeQuad(GL gla, GlColor color, Location start, Location end, double startAlpha, double endAlpha) {
280 GL2 gl = gla.getGL2();
281
282
283 Location dir = Location.sub(start, end).setZ(0);
284
285 if (dir.getLength() == 0) {
286 return;
287 }
288
289 dir = dir.getNormalized();
290
291
292 Location trans = new Location(dir.y, -dir.x, 0);
293 trans = trans.scale(6);
294
295
296 Location p1 = end.sub(trans);
297
298 Location p2 = end.add(trans);
299
300 gl.glColor4d(color.r, color.g, color.b, 1 - endAlpha);
301 gl.glVertex3d(p1.x, p1.y, p1.z + SPHERE_RADIUS);
302 gl.glVertex3d(p2.x, p2.y, p2.z + SPHERE_RADIUS);
303
304
305 Location p3 = start.add(trans);
306 Location p4 = start.sub(trans);
307
308 gl.glColor4d(color.r, color.g, color.b, 1 - startAlpha);
309 gl.glVertex3d(p3.x, p3.y, p3.z + SPHERE_RADIUS);
310 gl.glVertex3d(p4.x, p4.y, p4.z + SPHERE_RADIUS);
311 }
312
313
314
315
316
317
318
319
320
321
322
323 private void renderInfo(GL gla, GlColor color, Location location) {
324
325 GL2 gl = gla.getGL2();
326
327
328 List<String> infos = new ArrayList<String>(agent.getAssociatedInfo());
329 infos.add(0, '*' + agent.getName() + '*');
330
331 Location topHead = new Location(location.x, location.y, location.z + 2 * SPHERE_RADIUS * 1.1);
332
333 Location top2d = GLTools.getScreenCoordinates(gl, glu, topHead);
334
335 int lineGap = 12;
336 int font = GLUT.BITMAP_HELVETICA_10;
337
338 int maxWidth = 0;
339 for (String line : infos) {
340 int lineWidth = glut.glutBitmapLength(font, line);
341 if (lineWidth > maxWidth) {
342 maxWidth = lineWidth;
343 }
344 }
345
346
347 top2d = new Location(top2d.x - maxWidth / 2, top2d.y + (infos.size() - 1) * lineGap, top2d.z);
348
349 GlColor textColor = color.getMixedWith(new GlColor(0, 0, 0), 80);
350
351 gl.glColor3d(textColor.r, textColor.g, textColor.b);
352 for (int i = 0; i < infos.size(); i++) {
353 String text = infos.get(i);
354 if (i == 0) {
355 gl.glColor3d(color.r, color.g, color.b);
356 } else {
357 gl.glColor3d(textColor.r, textColor.g, textColor.b);
358
359 }
360 Location textPos = GLTools.getWorldCoordinates(gl, glu, top2d);
361 gl.glRasterPos3d(textPos.x, textPos.y, textPos.z);
362 glut.glutBitmapString(font, text);
363
364 top2d = top2d.addY(-lineGap);
365 }
366 }
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413 @Override
414 public List<BlendTriangle> getBlendedTris() {
415 return new LinkedList<BlendTriangle>();
416 }
417 }