View Javadoc

1   package com.insanityengine.ghia.renderer;
2   
3   import java.awt.*;
4   import java.awt.image.*;
5   
6   import java.util.*;
7   
8   import com.insanityengine.ghia.m3.*;
9   import com.insanityengine.ghia.libograf.*;
10  import com.insanityengine.ghia.pixels.*;
11  
12  import com.insanityengine.ghia.util.*;
13  
14  /***
15   *
16   * <P>
17   * This implementation of RendererInterface uses a zsorted list of polygons to make your
18   * fall in love with it! And you will!  Everyone will mock you because this peice of code
19   * holds your fancy! Bwhaahahahahhahaha!
20   * </P>
21   *
22   * <table border="1">
23   *  <topic>TestResults</topic>
24   *  <TH>TestName</TH>
25   *  <TH>Results</TH>
26   *  <TH>SnapShot</TH>
27   *  <TR valign="top">
28   *   <TD>Light</TD>
29   *   <TD>1646 fps</TD>
30   *   <TD><img src="http://ghia.sourceforge.net/images/old_snaps/ZortPolyRenderer_Light.gif"/></TD>
31   *  </TR>
32   *  <TR valign="top">
33   *   <TD>GeomLoader</TD>
34   *   <TD>97510/60.306=1616.9204 * 4725 = 7639948 tps = 76 kts</TD>
35   *   <TD><img src="http://ghia.sourceforge.net/images/old_snaps/ZortPolyRenderer_Geom.gif"/></TD>
36   *  </TR>
37   * </TABLE>
38   *
39   * @author BrianHammond
40   *
41   * $Header: /usr/local/cvsroot/ghia/src/java/com/insanityengine/ghia/renderer/ZortPolyRenderer.java,v 1.8 2005/03/26 23:42:41 brian Exp $
42   *
43   */
44  
45  public class ZortPolyRenderer implements RendererInterface, PixelBufferReadInterface {
46  
47  	/*** 
48  	 * 
49  	 * Constructor
50  	 * 
51  	 */
52  	public ZortPolyRenderer() {
53  		initColors();
54  	}
55  
56  	/*** 
57  	 * 
58  	 * Constructor
59  	 *
60  	 * @param width of the display
61  	 * @param height of the display
62  	 * @param component to use to create offscreen buffer
63  	 *
64  	 */
65  	public ZortPolyRenderer( int width, int height, Component component ) {
66  		initColors();
67  		init( width, height, component );
68  	}
69  
70  	/***
71  	 *
72  	 * Initialize this ZortPolyRenderer, call this *after* the component
73  	 * has been made visible or you will suffer!
74  	 *
75  	 * @param width of the display
76  	 * @param height of the display
77  	 * @param component to use to create offscreen buffer
78  	 *
79  	 */
80  	public void init( int width, int height, Component component ) {
81  		setObserver( component );
82  		
83  		w = width;
84  		h = height;
85  
86  		frustrum.setSize( width, height );
87  
88  		image = null;
89  		this.component = component;
90  	}
91  	
92  	/***
93  	 *
94  	 * Render the next scene
95  	 * 
96  	 * @param gl to use to render
97  	 *
98  	 */
99  	public void render( LiboGraf gl ) {
100 		if ( graphicsReady() ) {
101 			invokeDrawers( gl );
102 			happyPants( graphics );
103 			gl.getGraphics().drawImage( image, 0, 0, observer );
104 		}
105 	}
106 	
107 	/***
108 	 *
109 	 * Get the clear color
110 	 *
111 	 * @return the clear color
112 	 *
113 	 */
114 	public int getClearColor() {
115 		return 0;
116 	}
117 
118 	/***
119 	 *
120 	 * Set the clear color
121 	 *
122 	 * @return color to clear with
123 	 *
124 	 */
125 	public void setClearColor( int color ) {
126 	}
127 
128 	/***
129 	 *
130 	 * Set depth testing policy
131 	 *
132 	 * @param testDepth false disables test
133 	 *
134 	 */
135 	public void setDepthTesting( boolean testDepth ) { }
136 
137 	/***
138 	 *
139 	 * Clear the depth buffer
140 	 *
141 	 */
142 	public void clearDepthBuffer() { 
143 	}
144 
145 	/***
146 	 *
147 	 * Clear the pixel/color buffer
148 	 *
149 	 */
150 	public void clearColorBuffer() {
151 		clear();
152 	}
153 
154 	/***
155 	 *
156 	 * Set the shading method
157 	 *
158 	 * @param method may be listed in M3_Constants
159 	 *
160 	 */
161 	public void setShadingMethod( int method ) {
162 	}
163 
164 	/***
165 	 *
166 	 * Set the texture function
167 	 *
168 	 * @param function may be listed in M3_Constants
169 	 *
170 	 */
171 	public void setTextureFunction( int function ) {
172 	}
173 
174 	/***
175 	 *
176 	 * Draw a polygon
177 	 *
178 	 * @param count of points
179 	 * @param ptz the array of Pt3 to draw
180 	 *
181 	 */
182 	public void drawPolygon( int count, Pt3[] ptz ) {
183 
184 		if ( graphicsReady() ) {
185 			frustrum.toScreen( count, ptz );
186 
187 			if ( zcurr > 0 && !frustrum.offScreen( count, ptz ) ) {
188 				if ( true ) {
189 				
190 					polyz.add( new PrettyPoly( count, ptz, zcurr ) );
191 					
192 				} else {
193 					Polygon poly = mkPolygon( count, ptz );
194 
195 					int c = zToC( zcurr );
196 					c = 128 + c / 2;
197 					graphics.setColor( new Color( c, c, c ) );
198 					graphics.fillPolygon( poly );
199 				}
200 			}
201 
202 		}
203 	}
204 
205 	/***
206 	 *
207 	 * Set the current normal 
208 	 *
209 	 * @param point to use as the current normal
210 	 *
211 	 */
212 	public void setNormal( Pt3 point ) {
213 		zcurr = point.z;
214 		normal.set( point );
215 	}
216 	
217 	/***
218 	 *
219 	 * Set the current ImageSkin
220 	 *
221 	 * @param imageskin to use
222 	 *
223 	 */
224 	public void setSkin( ImageSkin skin ) {
225 	}
226 
227 	///////////////////////////////////////////////////////////////////////
228 	// PixelBufferInterface
229 	
230 	/***
231 	 *
232 	 * Clear the buffer
233 	 *
234 	 */
235 	public void clear() {
236 		if ( graphicsReady() ) {
237 			graphics.setColor( Color.black );
238 			graphics.fillRect( 0, 0, w, h );
239 		}
240 	}
241 
242 	/***
243 	 *
244 	 * Set the image observer
245 	 *
246 	 * @param observer to use
247 	 *
248 	 */
249 	public void setObserver( java.awt.image.ImageObserver observer ) {
250 		this.observer = observer;
251 	}
252 
253 	/***
254 	 *
255 	 * Determines the width of the buffer. 
256 	 *
257 	 * @return the width of this buffer
258 	 *
259 	 */
260 	public int getWidth() {
261 		return w;
262 	}
263 
264 	/***
265 	 *
266 	 * Determines the height of the buffer. 
267 	 *
268 	 * @return the height of this buffer
269 	 *
270 	 */
271 	public int getHeight() {
272 		return h;
273 	}
274 	
275 	/***
276 	 *
277 	 * Because this uses a PixelGrabber it may be slow-ish...
278 	 *
279 	 * @return array of pixel data
280 	 *
281 	 */
282 	public int[] getPixels() {
283 		ImageSkin skin = new ImageSkin( image, observer );
284 		return skin.getPixels();
285 	}
286 	
287 	//////////////////////////////////////////////////
288 	// DrawerRegistryInterface
289 	
290 	/***
291 	 *
292 	 * Some renderers are big babys about when it is ok to mess with their goodies.
293 	 * Hence this cheesy add/remove Drawer mess
294 	 *
295 	 * @param drawer to call per frame
296 	 *
297 	 */
298 	public void addDrawer( DrawingInterface drawer ) {
299 		registry.addDrawer( drawer );
300 	}
301 
302 	/***
303 	 *
304 	 * Some renderers are big babys about when it is ok to mess with their goodies.
305 	 * Hence this cheesy add/remove Drawer mess
306 	 *
307 	 * @param drawer to call per frame
308 	 *
309 	 */
310 	public void removeDrawer( DrawingInterface drawer ) {
311 		registry.removeDrawer( drawer );
312 	}
313 
314 	/***
315 	 *
316 	 * Invoke any registered DrawingInterfaces
317 	 *
318 	 */
319 	public void invokeDrawers( LiboGraf gl ) {
320 		registry.invokeDrawers( gl );
321 	}
322 
323 	///////////////////////////////////////////////////
324 
325 	private int w, h;
326 	private Image image = null; 
327 	private Graphics graphics = null;
328 	private ImageObserver observer = null;
329 	private Component component = null;
330 	
331 	private DrawerRegistry registry = new DrawerRegistry();
332 
333 	private Frustrum frustrum = new Frustrum();
334 	
335 	private ArrayList polyz = new ArrayList();
336 	private float zcurr = 1;
337 	private static Color [] colorz = null;
338 
339 	private Pt3 normal = new Pt3();
340 	
341 	///////////////////////////////////////////////////
342 	
343 	private final boolean graphicsReady() {
344 		boolean ok = false;
345 		if ( null == graphics ) {
346 			image = component.createImage( w, h );
347 			if ( null == image ) {
348 			} else {
349 				ok = true;
350 				graphics = image.getGraphics();
351 			}
352 			System.out.println( "" + " image = " + image  + " graphics = " + graphics );
353 		} else {
354 			ok = true;
355 		}
356 		return ok;
357 	}
358 
359 	private final void happyPants( LiboGraf gl ) {
360 		happyPants( gl.getGraphics() );
361 	}
362 
363 	private final void happyPants( Graphics graphics ) {
364 		Collections.sort( polyz );
365 		int sz = polyz.size();
366 		for ( int i = 0 ; i < sz ; ++i ) {
367 			( ( PrettyPoly ) polyz.get( i ) ).draw( graphics );
368 		}
369 		polyz.clear();
370 	}
371 
372 	private final static int zToC( float z ) {
373 		return 0 + ( int ) (
374 			255 * (
375 				( ( z + 0.4 ) * ( z + 0.4 ) / 1.96 )
376 			)
377 		);
378 	}
379 
380 	private final static Color zToColor( int n ) {
381 		return colorz[ n ];
382 	}
383 	
384 	private final static Color zToColor( float z ) {
385 		return zToColor( zToC( z ) );
386 	}
387 	
388 	synchronized private final static void initColors() {
389 		if ( null == colorz ) {
390 			colorz = new Color[ 255 ];
391 			for ( int i = 0 ; i < 255 ; ++i ) {
392 				colorz[ i ] = new Color( i, i / 2, 255 - i );
393 				/*
394 				colorz[ i ] = new Color(
395 					  i * i / 255
396 					, i * i / 255
397 					, i * i / 255
398 				);
399 				*/
400 			}
401 		}
402 	}
403 
404 	private static final Polygon mkPolygon( int count, Pt3[] ptz ) {
405 		Polygon poly = new Polygon();
406 		addToPolygon( poly, count, ptz );
407 		return poly;
408 	}
409 	
410 	private static final float addToPolygon( Polygon poly, int count, Pt3[] ptz ) {
411 		float zavg = 0;
412 		for ( int i = 0 ; i < count ; ++i ) {
413 			poly.addPoint( ( int ) ptz[ i ].x, ( int ) ptz[ i ].y );
414 			zavg += ptz[ i ].z;
415 		}
416 		return zavg / count;
417 	}
418 
419 	private class PrettyPoly implements Comparable {
420 		
421 		public PrettyPoly() {
422 		}
423 		
424 		public PrettyPoly( int count, Pt3[] ptz ) {
425 			init( count, ptz, 1 );
426 		}
427 		
428 		public PrettyPoly( int count, Pt3[] ptz, float z ) {
429 			init( count, ptz, z );
430 		}
431 
432 		public void init( int count, Pt3[] ptz, float z ) {
433 			this.poly = new Polygon();
434 			this.zpos = ZortPolyRenderer.addToPolygon( poly, count, ptz );
435 			this.z = z;
436 
437 			x = y = 0;
438 			for ( int i = 0 ; i < count ; ++i ) {
439 				x += ( int ) ptz[ i ].x;
440 				y += ( int ) ptz[ i ].y;
441 			}
442 			x /= count;
443 			y /= count;
444 		}
445 
446 		public void draw( Graphics graphics ) {
447 			graphics.setColor( ZortPolyRenderer.zToColor( z ) );
448 			graphics.fillPolygon( poly );
449 		}
450 
451 		public int compareTo( Object o ) {
452 			return ( int ) ( 100 * zpos - ( ( PrettyPoly ) o ).zpos );
453 		}
454 
455 		////
456 
457 		private Polygon poly;
458 		private float z = 0; // normal.z
459 		private float zpos;
460 
461 		int x, y;
462 	}
463 };
464 
465 /***
466  *
467  * $Log: ZortPolyRenderer.java,v $
468  * Revision 1.8  2005/03/26 23:42:41  brian
469  * fix links
470  *
471  * Revision 1.7  2005/03/19 17:50:02  brian
472  * repackaging
473  *
474  * Revision 1.6  2005/03/12 04:58:47  brian
475  * call the methods set instead of copy
476  *
477  * Revision 1.5  2004/09/16 11:00:20  brian
478  * added expensive getPixels impl... but how to mark it as such programmaticly?
479  *
480  * Revision 1.4  2004/09/11 14:37:21  brian
481  * added RendererConsumer and stuff
482  *
483  * Revision 1.3  2004/09/09 03:07:51  brian
484  * remove cool visual debugging
485  *
486  * Revision 1.2  2004/09/09 03:05:09  brian
487  * better with tuns of wacky debug visuals you'll love
488  *
489  * Revision 1.1  2004/09/09 00:14:56  brian
490  * barely works...
491  *
492  *
493  */