View Javadoc

1   package com.insanityengine.ghia.renderer;
2   
3   import java.awt.*;
4   import java.awt.image.*;
5   import java.awt.event.*;
6   import java.applet.*;
7   
8   import com.insanityengine.ghia.m3.*;
9   import com.insanityengine.ghia.libograf.*;
10  import com.insanityengine.ghia.pixels.*;
11  
12  /***
13   *
14   * <P>
15   * This renderer uses the BufferBase for the bulk of it's functionality
16   * but implements the tricky drawPolygon method
17   * </P>
18   *
19   * <P>
20   * It uses two buffers the height of the display and uses a simplistic
21   * line drawing algorithm to update the maximum and mininum x values 
22   * for each scanline as well as information about the depth and texture
23   * coordinate at each point. (scanPolyEdge)
24   * </P>
25   *
26   * <P>
27   * Obviously this algorithm only works for concave polygons. If you have
28   * convex polygons, you are a freak. I'm sorry, but it's true.
29   * </P>
30   *
31   * <P>
32   * Once each edge of the polygon have been scanned, each scanline is 
33   * rasterized with an embarrasingly bad implementation which uses the 
34   * information gathered above, the current skin, shading mode, etc
35   * to raster the scanline with zbuffer lovin'.  (rasterPoly)
36   * </P>
37   *
38   * <P>
39   * I'm sure your implementation will be much better, all you need to do is
40   * derive a class from BufferBase and implement the drawPolygon method or 
41   * implement RendererInterface.
42   * </P>
43   *
44   * <table border="1">
45   *  <topic>TestResults</topic>
46   *	<TH>TestName</TH>
47   *	<TH>Results</TH>
48   *	<TH>SnapShot</TH>
49   *  <TR valign="top">
50   *   <TD>Light</TD>
51   *   <TD>51fps</TD>
52   *   <TD><img src="http://ghia.sourceforge.net/images/old_snaps/Memagery_Light.gif"/></TD>
53   *  </TR>
54   *  <TR valign="top">
55   *   <TD>GeomLoader</TD>
56   *   <TD>1102/61.640=17.878002 * 4725 =  84475 tps =  84 kts</TD>
57   *   <TD><img src="http://ghia.sourceforge.net/images/old_snaps/Memagery_Geom.gif"/></TD>
58   *  </TR>
59   * </TABLE>
60   *
61   * @author BrianHammond
62   *
63   * $Header: /usr/local/cvsroot/ghia/src/java/com/insanityengine/ghia/renderer/Memagery.java,v 1.9 2005/03/26 23:42:41 brian Exp $
64   *
65   */
66  public class Memagery extends RendererBase {
67  
68  	/***
69    	 *	  
70    	 * Constructor	  
71    	 *	  
72    	 */
73  	public Memagery() {
74  	}
75  
76  	/***
77  	 *
78  	 * Draw a polygon
79  	 *
80  	 * @param count of points
81  	 * @param ptz the array of Pt3 to draw
82  	 *
83  	 */
84  	public void drawPolygon( int number, Pt3 ptz[] ) {
85  
86  		if ( normal.z < 0 ) return;
87  		
88  		// convert to screen coordinate
89  		frustrum.toScreen( number, ptz );	
90  		if ( frustrum.offScreen( number, ptz ) ) return;
91  
92  		initScantron(); 
93  
94  		// scan the polygon edges
95  		float maxz, minz;
96  		maxz = minz = ptz[ number - 1 ].z;
97  
98  		int i, j;	
99  		for ( i = 0 ; i < number ; i++ ) {
100 			j = i + 1;
101 			if ( j >= number ) j = 0;
102 			
103 			scannie.scanPolyEdge( ptz[ i ], ptz[ j ] );	
104 			
105 			if ( ptz[ i ].z > maxz ) maxz = ptz[ i ].z;
106 			if ( ptz[ i ].z < minz ) minz = ptz[ i ].z;
107 		}
108 
109 		// draw the actual scanlines
110 		rasterPoly( minz, maxz );
111 	}
112 
113 	///////////////////////////////////////////////////////////
114 
115 	/*** 
116 	 * 
117 	 * rasterPoly: blech
118 	 * 
119 	 * @param minz
120 	 * @param maxz
121 	 * 
122 	 */
123 	private final void rasterPoly( float minz, float maxz ) {
124 		int i, j, n;
125 		float diffz = maxz - minz;
126 
127 		if ( 0 == diffz ) diffz = 1;
128 
129 		int x0, x1, xd;
130 		float z, zinc, fz = 1;
131 
132 		// so colorful!
133 		int pix =  0xFF00FF00;
134 
135 		int idx, edx, bidx, pidx;
136 
137 		// texture and image space coord respectively
138 		float tx, ty, txi, tyi;
139 		int isx, isy, iidx;
140 		
141 		// pukey!
142 		int ix, iy;
143 		int img_w = 0, img_h = 0;
144 
145 		int shadeMask;
146 
147 		if ( null != skin ) {
148 			img_w = skin.getWidth();
149 			img_h = skin.getHeight();
150 		}
151 		
152 		if ( M3_Constants.NORM_SHADE == shade_method ) fz = 0.1f + 0.9f * normal.z;
153 
154 		for ( i = 0, bidx = 0 ; i < h ; i++, bidx += w ) {
155 			if ( !scannie.hasCandy( i ) ) continue;
156 		
157 			xd = ( int ) scannie.getDistance( i );
158 			
159 			// move in z
160 			z = scannie.getLz( i );
161 			zinc = ( scannie.getRz( i ) - scannie.getLz( i ) ) / xd;
162 
163 			// move in texture space
164 			tx = ( scannie.getLtx( i )* img_w );
165 			ty = ( scannie.getLty( i )* img_h );
166 
167 			txi = ( scannie.getRtx( i ) * img_w - tx ) / xd;
168 			tyi = ( scannie.getRty( i ) * img_h - ty ) / xd;
169 
170 			// shading for each pixel on the scanline
171 			z = scannie.getLz( i );
172 			j = ( int ) scannie.getLx( i );
173 			
174 			idx = bidx + j;
175 			edx = idx + xd;
176 			for ( 
177 				;
178 				idx <= edx && j < w ; 
179 				idx++, j++, z += zinc,
180 				tx += txi, ty += tyi
181 			) {
182 				if ( j < 0 ) continue;
183 
184 				if ( !zbuffer.set( idx, z ) ) continue;
185 				
186 				if ( null != skin ) {
187 					pix = ( int ) skin.getPixelAt( ( int ) ( tx ), ( int ) ( ty ) );
188 				}
189 
190 				switch( shade_method ) {
191 						
192 					//case NONE_SHADE: 
193 					default:
194 						shadeMask = 0xFFFFFFFF;
195 						break;
196 
197 					case M3_Constants.NORM_SHADE:
198 						n = ( int ) ( 255 * fz );
199 						shadeMask = ( 0xFF << 24 | n << 16 | n << 8 | n );
200 						break;
201 
202 					case M3_Constants.DEPTH_SHADE:
203 						if ( 0 == diffz ) fz = 0.1f;
204 						else fz = ( z - minz ) / diffz;
205 						if ( fz < 0.1 ) fz = 0.1f;
206 
207 						n = ( int ) ( 255 * fz );
208 						shadeMask = ( 0xFF << 24 | n << 16 | n << 8 | n );
209 						break;
210 						
211 					case M3_Constants.PHONG_SHADE:
212 						if ( 0 == diffz ) fz = 1;
213 						else fz = ( z - minz ) / diffz;
214 
215 						pidx = ( int ) ( 255 * fz );
216 
217 						if ( pidx < 0 ) pidx = 0;
218 						if ( pidx > 255 ) pidx = 255;
219 
220 						n = ( int ) phongo[ pidx ];
221 						shadeMask = ( 0xFF << 24 | n << 16 | n << 8 | n );
222 						break;
223 				}
224 
225 				// set the pixel
226 				pixels[ idx ] = pix & shadeMask;
227 			}
228 		}
229 	}
230 
231 	//////////////////////////////////
232 
233 	private Scantron scannie;
234 	private DrawerRegistry registry = new DrawerRegistry();
235 
236 	/*** 
237 	 * 
238 	 * initScantron
239 	 * 
240 	 */
241 	final private void initScantron() {
242 		if ( null == scannie ) {
243 			scannie = new Scantron( w, h );
244 		}
245 		scannie.reset();
246 	}
247 };
248 
249 /***
250  *
251  * $Log: Memagery.java,v $
252  * Revision 1.9  2005/03/26 23:42:41  brian
253  * fix links
254  *
255  * Revision 1.8  2005/03/25 03:07:54  brian
256  * centralize more cruft
257  *
258  * Revision 1.7  2005/03/25 02:45:25  brian
259  * split up a bit
260  *
261  * Revision 1.6  2005/03/19 17:50:02  brian
262  * repackaging
263  *
264  * Revision 1.5  2005/02/17 03:31:13  brian
265  * good stuff???
266  *
267  * Revision 1.4  2004/09/11 19:40:57  brian
268  * use normal.z to bail early
269  *
270  * Revision 1.3  2004/09/11 14:37:21  brian
271  * added RendererConsumer and stuff
272  *
273  * Revision 1.2  2004/09/05 03:41:31  brian
274  * refactored to have the render method of the renderers invoke the drawingIfz
275  *
276  * Revision 1.1  2004/09/02 13:17:16  brian
277  * the big reorg
278  *
279  * Revision 1.10  2004/09/01 01:52:47  brian
280  * added test results (ok, and images) to javadoc
281  *
282  * Revision 1.9  2004/09/01 01:10:42  brian
283  * fix class level javadoc placement
284  *
285  * Revision 1.8  2004/09/01 00:11:06  brian
286  * author, log and header stuff
287  *
288  *
289  */