View Javadoc

1   package nl.tudelft.goal.ut2004.visualizer.timeline.map;
2   
3   import static javax.media.opengl.GL.GL_COLOR_BUFFER_BIT;
4   import static javax.media.opengl.GL.GL_DEPTH_TEST;
5   import static javax.media.opengl.GL.GL_VIEWPORT;
6   import static javax.media.opengl.GL2.GL_RENDER;
7   import static javax.media.opengl.GL2.GL_SELECT;
8   import static javax.media.opengl.fixedfunc.GLLightingFunc.GL_LIGHTING;
9   import static javax.media.opengl.fixedfunc.GLLightingFunc.GL_SMOOTH;
10  import static javax.media.opengl.fixedfunc.GLMatrixFunc.GL_MODELVIEW;
11  import static javax.media.opengl.fixedfunc.GLMatrixFunc.GL_PROJECTION;
12  
13  import java.awt.Point;
14  import java.nio.IntBuffer;
15  import java.util.Arrays;
16  
17  import javax.media.opengl.GL;
18  import javax.media.opengl.GL2;
19  import javax.media.opengl.GLAutoDrawable;
20  import javax.media.opengl.GLEventListener;
21  import javax.media.opengl.glu.GLU;
22  import javax.vecmath.Vector3d;
23  
24  import com.jogamp.common.nio.Buffers;
25  import com.jogamp.opengl.util.gl2.GLUT;
26  
27  import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
28  import cz.cuni.amis.pogamut.unreal.communication.messages.gbinfomessages.IPlayer;
29  
30  /**
31   * Renderer renders the environment of the unreal map according to passed
32   * arguments in the constructor. It renders the map, agents inside from
33   * specified viewpoint.
34   * 
35   * @author Honza
36   */
37  public class EnvironmentRenderer implements GLEventListener {
38  	private static GLU glu = new GLU();
39  	private static GLUT glut = new GLUT();
40  
41  	private MapViewpoint viewpoint;
42  	private CollectionRenderer<IPlayer> agentRenderes;
43  	private CollectionRenderer<Object> objectRenderes;
44  	private MapRenderer mapRenderer;
45  
46  	public EnvironmentRenderer(MapViewpoint viewpoint, CollectionRenderer<IPlayer> agentRenderes,
47  			CollectionRenderer<Object> objectRenderes, MapRenderer mapRenderer) {
48  		this.viewpoint = viewpoint;
49  		this.agentRenderes = agentRenderes;
50  		this.objectRenderes = objectRenderes;
51  		this.mapRenderer = mapRenderer;
52  
53  	}
54  
55  	@Override
56  	public synchronized void init(GLAutoDrawable glDrawable) {
57  		GL2 gl = glDrawable.getGL().getGL2();
58  
59  		gl.glMatrixMode(GL_PROJECTION);
60  		gl.glLoadIdentity();
61  		gl.glMatrixMode(GL_MODELVIEW);
62  		gl.glLoadIdentity();
63  
64  		gl.glEnable(GL.GL_DEPTH_TEST);
65  		gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
66  
67  		gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
68  		gl.glClearDepth(1.0);
69  		gl.glShadeModel(GL_SMOOTH); // try setting this to GL_FLAT and see
70  										// what happens.
71  
72  		/*
73  		 * float[] lightAmbient = new float[]{0.5f, 0.5f, 0.5f, 1.0f}; float[]
74  		 * lightDiffuse = new float[]{1.0f, 1.0f, 1.0f, 1.0f}; float[]
75  		 * lightPosition = new float[]{ 0, 0, 0, //
76  		 * (float)levelBox.getFlag().getCenterX(), //
77  		 * (float)levelBox.getFlag().getCenterY(), //
78  		 * (float)levelBox.getFlag().getCenterZ() +
79  		 * (float)levelBox.getFlag().getDeltaZ(), 1.0f};
80  		 * gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT,
81  		 * FloatBuffer.wrap(lightAmbient)); gl.glLightfv(GL.GL_LIGHT0,
82  		 * GL.GL_DIFFUSE, FloatBuffer.wrap(lightDiffuse));
83  		 * gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION,
84  		 * FloatBuffer.wrap(lightPosition)); gl.glEnable(GL.GL_LIGHT0);
85  		 */
86  		gl.glDisable(GL_LIGHTING);
87  
88  		// Now preprocess our data for rendering
89  		agentRenderes.prepare(gl);
90  		objectRenderes.prepare(gl);
91  		mapRenderer.prepare(gl);
92  	}
93  
94  	@Override
95  	public synchronized void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
96  		GL2 gl = drawable.getGL().getGL2();
97  		setProjection(gl, x, y, width, height);
98  	}
99  
100 	/**
101 	 * Set projection, viewpoinbt and so on. Used every rendered frame.
102 	 */
103 	private synchronized void setProjection(GL2 gl, int x, int y, int width, int height) {
104 		if (height <= 0) { // avoid a divide by zero error!
105 			height = 1;
106 		}
107 		float h = (float) width / (float) height;
108 		gl.glViewport(0, 0, width, height);
109 		gl.glMatrixMode(GL_PROJECTION);
110 		gl.glLoadIdentity();
111 		glu.gluPerspective(viewpoint.getViewAngle(), h, 10.0, 100000.0);
112 		gl.glMatrixMode(GL_MODELVIEW);
113 		gl.glLoadIdentity();
114 	}
115 
116 	/**
117 	 * Clear the screen, set up correct observer position and other stuff
118 	 * 
119 	 * @param gl
120 	 */
121 	private synchronized void prepareCanvas(GL2 gl) {
122 		// Clear the drawing area
123 		gl.glEnable(GL_DEPTH_TEST); // GL.GL_NORMALIZE|
124 		gl.glClearColor(0.45f, 0.45f, 0.45f, 0f);
125 
126 		gl.glClear(GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
127 
128 		// Reset the modelview to the "identity"
129 		gl.glMatrixMode(GL_MODELVIEW);
130 		gl.glLoadIdentity();
131 
132 		// Move the "drawing cursor" around
133 		Location observerLoc = viewpoint.getLocation();
134 		Location eyeLoc = viewpoint.getEye();
135 		Vector3d upVec = viewpoint.getUp();
136 		// gl.glTranslated(observerLocation.x, observerLocation.y,
137 		// observerLocation.z);
138 		glu.gluLookAt(eyeLoc.x, eyeLoc.y, eyeLoc.z, observerLoc.x, observerLoc.y, observerLoc.z, upVec.x, upVec.y,
139 				upVec.z);
140 
141 		gl.glScaled(1., 1., -1.);
142 	}
143 
144 	@Override
145 	public synchronized void display(GLAutoDrawable glDrawable) {
146 		GL2 gl = glDrawable.getGL().getGL2();
147 
148 		int viewport[] = new int[4];
149 		gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
150 
151 		// render using selection mode
152 
153 		// Assign a buffer for selection mode values, the buffer is later used
154 		// to retrieve name stack. Has to be prepared before GL_SELECT mode
155 		int[] selectBufferArray = new int[512];
156 		IntBuffer selectBuffer = Buffers.newDirectIntBuffer(selectBufferArray.length);
157 
158 		gl.glSelectBuffer(selectBufferArray.length, selectBuffer); // size of
159 																	// buffer,
160 																	// buffer
161 																	// itself
162 
163 		gl.glRenderMode(GL_SELECT); // has to be enabled before any
164 										// manipulation with selection buffer
165 
166 		// initialize name stack to empty stack
167 		gl.glInitNames();
168 		gl.glPushName(-1); // because glLoadName replaces top position on stack,
169 							// we have to have something there.
170 
171 		// pick only in small view volume
172 		gl.glMatrixMode(GL_PROJECTION);
173 		gl.glPushMatrix();
174 		{
175 			gl.glLoadIdentity();
176 			// synchronized because setSelectpoint can occur and we want only
177 			// one thing
178 			glu.gluPickMatrix(selectPoint.x, viewport[3] - selectPoint.y, 1.0f, 1.0f, viewport, 0);
179 			glu.gluPerspective(viewpoint.getViewAngle(), (float) viewport[2] / (float) viewport[3], 10.0, 100000.0);
180 
181 			prepareCanvas(gl);
182 			mapRenderer.render(gl);
183 			agentRenderes.render(gl);
184 			objectRenderes.render(gl);
185 			gl.glMatrixMode(GL_PROJECTION);
186 		}
187 		gl.glPopMatrix();
188 
189 		gl.glMatrixMode(GL_MODELVIEW);
190 		// now that everything was rendered I should have all objects that would
191 		// be in view volume in selectBuffer in following format:
192 		// * [i*4+0] - number of names on the name stack when the hit occured
193 		// * [i*4+1] - minimum z
194 		// * [i*4+2] - maximum z
195 		// * [i*4+3] - name of object (integer id)
196 		int numOfHits = gl.glRenderMode(GL_RENDER);
197 		selectBuffer.get(selectBufferArray);
198 
199 		// stuff it to selectedObjects
200 		selectedObjects = new int[numOfHits];
201 		for (int hitIndex = 0; hitIndex < numOfHits; hitIndex++) {
202 			selectedObjects[hitIndex] = selectBufferArray[hitIndex * 4 + 3];
203 		}
204 
205 		this.selectDirtyFlag = false;
206 
207 		prepareCanvas(gl);
208 
209 		// Render all stuff to screen
210 		mapRenderer.render(gl);
211 		agentRenderes.render(gl);
212 		objectRenderes.render(gl);
213 
214 
215 		// render debug text
216 		String res = "[" + selectPoint.x + ", " + selectPoint.y + "] # " + numOfHits;
217 		for (int objId : selectedObjects) {
218 			res += ":" + objId;
219 		}
220 		renderText(gl, res, 0, 0, GLUT.BITMAP_HELVETICA_12);
221 
222 	}
223 
224 	private void renderText(GL2 gl, String text, int x, int y, int font) {
225 		int viewport[] = new int[4];
226 		gl.glGetIntegerv(GL_VIEWPORT, viewport, 0);
227 
228 		gl.glMatrixMode(GL_MODELVIEW);
229 		gl.glPushMatrix();
230 		gl.glLoadIdentity();
231 		gl.glMatrixMode(GL_PROJECTION);
232 		gl.glPushMatrix();
233 		gl.glLoadIdentity();
234 		{
235 			gl.glOrtho(0, viewport[2], 0, viewport[3], -1, 1);
236 			gl.glColor3d(1, 1, 1);
237 			gl.glRasterPos3d(0, 0, 0);
238 			glut.glutBitmapString(font, text);
239 		}
240 		gl.glMatrixMode(GL_PROJECTION);
241 		gl.glPopMatrix();
242 		gl.glMatrixMode(GL_MODELVIEW);
243 		gl.glPopMatrix();
244 
245 	}
246 
247 	// Flag if the stored selected objects are valid for select point
248 	private boolean selectDirtyFlag = true;
249 	// what point in viewport do we want objects from. In window mode, so change
250 	// when want to use
251 	private Point selectPoint = new Point();
252 	// list of objects from selectPoint, if selectDirtyFlag is false
253 	private int[] selectedObjects = new int[0];
254 
255 	public synchronized int[] getSelectedObjects() throws IllegalStateException {
256 		if (selectDirtyFlag) {
257 			throw new IllegalStateException(
258 					"Not objects from selected point. Did you call display() after setSelectPoint()?");
259 		}
260 
261 		return Arrays.copyOf(selectedObjects, selectedObjects.length);
262 	}
263 
264 	/**
265 	 * Set select point you want rendered objects list from.
266 	 * 
267 	 * @param point
268 	 *            point we want objects from. In Window mode = left top is [0,0]
269 	 */
270 	public synchronized void setSelectPoint(Point point) {
271 		if (point == null) {
272 			throw new IllegalArgumentException("Point cannot be null");
273 		}
274 
275 		this.selectPoint = new Point(point);
276 		this.selectDirtyFlag = true;
277 	}
278 
279 
280 	@Override
281 	public void dispose(GLAutoDrawable arg0) {
282 		// TODO Auto-generated method stub
283 
284 	}
285 }