View Javadoc

1   package com.insanityengine.ghia.renderer.Edjo;
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.renderer.*;
9   import com.insanityengine.ghia.m3.*;
10  import com.insanityengine.ghia.libograf.*;
11  import com.insanityengine.ghia.pixels.*;
12  
13  /***
14   *
15   * <P>
16   * This renderer uses the BufferBase for the bulk of it's functionality
17   * but implements the tricky drawPolygon method
18   * </P>
19   *
20   *
21   * @author BrianHammond
22   *
23   * $Header: /usr/local/cvsroot/ghia/src/java/com/insanityengine/ghia/renderer/Edjo/Edjo.java,v 1.7 2005/03/26 04:59:18 brian Exp $
24   *
25   */
26  public class Edjo extends RendererBase {
27  
28  	/***
29    	 *	  
30    	 * Constructor	  
31    	 *	  
32    	 */
33  	public Edjo() {
34  	}
35  
36  	/***
37  	 *
38  	 * Draw a polygon
39  	 *
40  	 * @param count of points
41  	 * @param ptz the array of Pt3 to draw
42  	 *
43  	 */
44  	public void drawPolygon( int number, Pt3 ptz[] ) {
45  		if ( onScreen( number, ptz ) ) {
46  			setupEdges( number, ptz );
47  			scanEdges();
48  		}
49  	}
50  
51  	////////////////////////////////////////
52  
53  	private int edgeCount;
54  	private Edge edges[] = null;
55  
56  	private Hit minHit = new Hit();
57  	private Hit maxHit = new Hit();
58  	private Hit tmpHit = new Hit();
59  
60  	Hit texStart = new Hit();
61  	Hit texStop  = new Hit();
62  
63  	private int shadeMask;
64  
65  	/*** 
66  	 * 
67  	 * onScreen
68  	 * 
69  	 * @param number
70  	 * @param ptz
71  	 * 
72  	 * @return a boolean
73  	 * 
74  	 */
75  	private final boolean onScreen( int number, Pt3 ptz[] ) {
76  		if ( normal.z < 0 ) return false;
77  		frustrum.toScreen( number, ptz );
78  		if ( frustrum.offScreen( number, ptz ) ) return false;
79  		return true;
80  	}
81  
82  	/*** 
83  	 * 
84  	 * setupEdges
85  	 * 
86  	 * @param number
87  	 * @param ptz
88  	 * 
89  	 */
90  	private final void setupEdges( int number, Pt3 ptz[] ) {
91  		if ( null == edges ) {
92  			edges = new Edge[ ptz.length ];
93  			for ( int i = 0 ; i < edges.length ; i++ ) {
94  				edges[ i ] = new Edge();
95  			}
96  		}
97  		
98  		edgeCount = 0;
99  		for ( int i = 0, next ; i < number ; i++ ) {
100 
101 			next = i + 1;
102 			if ( next >= number ) {
103 				next = 0;
104 			}
105 			edges[ edgeCount++ ].set( ptz[ i ], ptz[ next ] );
106 		}
107 	
108 		// setup the shading mask	
109 		int n = ( int ) ( 255 * normal.z );
110 		shadeMask = ( 0xFF << 24 | n << 16 | n << 8 | n );
111 	}
112 
113 	/*** 
114 	 * 
115 	 * scanEdges
116 	 * 
117 	 */
118 	private final void scanEdges() {
119 
120 		int y = ( int ) findMin();
121 		int maxY = ( int ) ( findMax() );
122 
123 		if ( 0 == y && 0 == maxY ) return;
124 
125 		if ( ++maxY >= h ) maxY = h - 1;
126 
127 		for ( ; y < maxY ; y++ ) {
128 			if ( 0 <= y && findHits( y ) ) {
129 				scanLine( y );
130 			}
131 		}
132 	}
133 
134 	/*** 
135 	 * 
136 	 * findMin
137 	 * 
138 	 * @return a float
139 	 * 
140 	 */
141 	private final float findMin() {
142 		float min = edges[ 0 ].getMin();
143 		for ( int i = 1 ; i < edgeCount ; i++ ) {
144 			if ( edges[ i ].getMin() < min ) {
145 				min = edges[ i ].getMin();
146 			}
147 		}
148 		return min;
149 	}
150 
151 	/*** 
152 	 * 
153 	 * findMax
154 	 * 
155 	 * @return a float
156 	 * 
157 	 */
158 	private final float findMax() {
159 		float max = edges[ 0 ].getMax();
160 		for ( int i = 1 ; i < edgeCount ; i++ ) {
161 			if ( edges[ i ].getMax() > max ) {
162 				max = edges[ i ].getMax();
163 			}
164 		}
165 		return max;
166 	}
167 	
168 	/*** 
169 	 * 
170 	 * findHits
171 	 * 
172 	 * @return a boolean
173 	 * 
174 	 */
175 	public final boolean findHits( int y ) {
176 		boolean found = false;
177 		for ( int i = 0 ; i < edgeCount ; i++ ) {
178 			if ( edges[ i ].hit( y, tmpHit ) ) {
179 				if ( !found ) {
180 					found = true;
181 					maxHit.copy( tmpHit );
182 					minHit.copy( tmpHit );
183 				} else {
184 					if ( tmpHit.min < minHit.min ) minHit.copy( tmpHit );
185 					if ( tmpHit.max > minHit.max ) maxHit.copy( tmpHit );
186 				}
187 			}
188 			
189 		}
190 		return found;
191 	}
192 
193 	/*** 
194 	 * 
195 	 * scanLine
196 	 * 
197 	 * @param y
198 	 * 
199 	 */
200 	private final void scanLine( int y ) {
201 		if ( skin == null ) {
202 			simpleScanLine( y );
203 		} else {
204 			textureScanLine( y );
205 		}
206 	}
207 	
208 	/*** 
209 	 * 
210 	 * simpleScanLine
211 	 * 
212 	 * @param y
213 	 * 
214 	 */
215 	private void simpleScanLine( int y ) {
216 		
217 		// first and last x values at this line...
218 		int min = ( int ) minHit.min;
219 		int max = ( int ) maxHit.max;
220 
221 		int len = max - min;
222 		
223 		// walk the z
224 		float zstart = minHit.what.zAt( minHit.when );
225 		float zstop  = maxHit.what.zAt( maxHit.when );
226 		float zstep  = ( zstop - zstart ) / len;
227 
228 		// move up to zero and adjust starting texture coordinates
229 		// appropriately
230 		if ( min < 0 ) {
231 			zstart += zstep * -min;
232 			min = 0;
233 		} 
234 		
235 		// don't draw past the end of the line
236 		if ( max >= w ) max = w - 1;
237 
238 		// pixel index
239 		int idx = y * w + min;
240 		max = idx + max - min;
241 
242 		for ( ; idx < max ; idx++, zstart += zstep ) {
243 			if ( zbuffer.set( idx, zstart ) ) {
244 				pixels[ idx ] = 0xFF0000FF & shadeMask;
245 			}
246 		}
247 	}
248 	
249 	/*** 
250 	 * 
251 	 * textureScanLine
252 	 * 
253 	 * @param y
254 	 * 
255 	 */
256 	private final void textureScanLine( int y ) {
257 		
258 		// first and last x values at this line...
259 		int min = ( int ) minHit.min;
260 		int max = ( int ) maxHit.max;
261 
262 		int len = max - min;
263 		
264 		// walk the z
265 		float zstart = minHit.what.zAt( minHit.when );
266 		float zstop  = maxHit.what.zAt( maxHit.when );
267 		float zstep  = ( zstop - zstart ) / len;
268 
269 		// get the texture coordinates
270 		minHit.tex( texStart );
271 		maxHit.tex( texStop );
272 
273 		// calculate the texture steps
274 		float sStep = ( texStop.min - texStart.min ) / len;
275 		float tStep = ( texStop.max - texStart.max ) / len;
276 
277 		// move up to zero and adjust starting texture coordinates
278 		// appropriately
279 		if ( min < 0 ) {
280 			texStart.min += sStep * -min;
281 			texStart.max += tStep * -min;
282 			zstart += zstep * -min;
283 			min = 0;
284 		} 
285 		
286 		// don't draw past the end of the line
287 		if ( max >= w ) max = w - 1;
288 
289 		// pixel index
290 		int idx = y * w + min;
291 		max = idx + max - min;
292 
293 		/*
294 		// some texturing slyness
295 		int textIdx = skin.getScaledIdx( texStart.min, texStart.max );
296 		int textInc = skin.getScaledIdx( sStep, tStep );
297 		int maxText = skin.getMax();
298 		*/
299 
300 		for ( 
301 			; 
302 			idx < max 
303 			; 
304 			idx++,
305 			zstart += zstep,
306 			//textIdx += textInc
307 			texStart.min += sStep, texStart.max += tStep
308 		) {
309 			if ( zbuffer.set( idx, zstart ) ) {
310 				/*
311 					if ( textIdx >= maxText ) {
312 						textIdx %= maxText;
313 					} else 
314 					if ( textIdx < 0 ) {
315 						textIdx = ( textIdx + maxText ) % maxText;
316 					}
317 					
318 					pixels[ idx ] = skin.getPixels()[ textIdx ] & shadeMask ;
319 				*/
320 				pixels[ idx ] = skin.getPixelAtCoord( texStart.min, texStart.max ) & shadeMask;
321 			}
322 		}
323 	}
324 
325 };
326 
327 /***
328  *
329  * $Log: Edjo.java,v $
330  * Revision 1.7  2005/03/26 04:59:18  brian
331  * got too fancy with textures in this spot...
332  *
333  * Revision 1.6  2005/03/26 03:46:55  brian
334  * break it up a bit
335  *
336  * Revision 1.5  2005/03/26 03:35:45  brian
337  * texturing strongly broken...
338  *
339  * Revision 1.4  2005/03/25 13:42:41  brian
340  * actually works
341  *
342  * Revision 1.3  2005/03/25 13:37:55  brian
343  * significantly less broken
344  *
345  * Revision 1.2  2005/03/25 04:13:20  brian
346  * still does not work
347  *
348  * Revision 1.1  2005/03/25 04:02:19  brian
349  * does not work
350  *
351  *
352  */