View Javadoc

1   package com.insanityengine.ghia.libograf;
2   
3   import java.util.Stack;
4   
5   import java.awt.*;
6   
7   import java.applet.Applet;
8   import java.awt.Component;
9   import java.awt.image.ImageObserver;
10  
11  import com.insanityengine.ghia.m3.*;
12  import com.insanityengine.ghia.pixels.*;
13  import com.insanityengine.ghia.renderer.*;
14  
15  /***
16   *
17   * <P>
18   * Very, very, very loosely based on openGL, very loosely! The largest
19   * similarity are the matrix stack a similarity in the polygon handling
20   * </P>
21   *
22   * @author BrianHammond
23   *
24   * $Header: /usr/local/cvsroot/ghia/src/java/com/insanityengine/ghia/libograf/LiboGraf.java,v 1.11 2005/03/19 17:50:02 brian Exp $
25   *
26   */
27  
28  public class LiboGraf extends RendererConsumer implements LiboGrafInterface {
29  
30  	////////////////////////////////////////////////////////
31  
32  	/***
33  	 *
34  	 * Constructor
35  	 *
36  	 */
37  	public LiboGraf() {
38  		init( 0, 0, null );
39  	}
40  
41  	/***
42  	 *
43  	 * Constructor
44  	 *
45  	 * @param width of the display
46  	 * @param height of the display
47  	 * @param component to use for graphics (yuck!)
48  	 *
49  	 */
50  	public LiboGraf( int width, int height, java.awt.Component component ) {
51  		init( width, height, component );
52  	}
53  
54  	/***
55  	 *
56  	 * Constructor, if m3_renderName parameter is defined for the 
57  	 * Applet, it will attempt to use it with the createRenderer
58  	 * method
59  	 *
60  	 * @param applet which provides context
61  	 *
62  	 */
63  	public LiboGraf( Applet applet ) {
64  		init( applet );
65  	}
66  
67  	/***
68  	 * Initialize this LiboGraf
69   	 *
70  	 * @param width of the display
71  	 * @param height of the display
72  	 * @param component to use
73  	 *
74  	 */
75  	public final void init( int width, int height, java.awt.Component component ) {
76  		init();
77  		super.init( width, height, component );
78  		Imago.setComponent( component );
79  		identity();
80  	}
81  	
82  	/***
83  	 *
84  	 * Rotate the current state
85  	 *
86  	 * @param angle
87  	 * 
88  	 * @return a State
89  	 * 
90  	 */
91  	public final State rotate( Pt3 angle ) {
92  		return curr.rotate( angle );
93  	}
94  
95  	/***
96  	 *
97  	 * Translate the current state
98  	 * 
99  	 * @param displacement
100 	 * 
101 	 * @return a State
102 	 * 
103 	 */
104 	public final State translate( Pt3 displacement ) {
105 		return curr.translate( displacement );
106 	}
107 	
108 	/***
109 	 *
110 	 * Scale the current state
111 	 *
112 	 * @param ratio
113 	 * 
114 	 * @return a State
115 	 * 
116 	 */
117 	public final State scale( Pt3 ratio ) {
118 		return curr.scale( ratio );
119 	}
120 	
121 	/***
122 	 *
123 	 * Load the current state with the identity state
124 	 * 
125 	 * @return a State
126 	 *
127 	 */
128 	public final State identity() {
129 		return curr.identity();
130 	}
131 
132 	/***
133 	 *
134 	 * Push the current state down on the stack
135 	 *
136 	 */
137 	public void push() {
138 		if ( mat_idx >= 32 ) return;
139 		stack[ mat_idx++ ].set( curr );
140 	}
141 	
142 	/***
143 	 *
144 	 * Pop the current state off the stack
145 	 * 
146 	 * @return a State
147 	 *
148 	 */
149 	public final State pop() {
150 		if ( mat_idx > 0 ) {
151 			curr.set( stack[ --mat_idx ] );
152 		}
153 		if ( mat_idx < 0 ) mat_idx = 0;
154 		return curr;
155 	}
156 
157 	/***
158 	 *
159 	 * Get the current state
160 	 *
161 	 * @return the current state 
162 	 *
163 	 */
164 	public final State get() { 
165 		return curr; 
166 	}
167 
168 	/***
169 	 *
170 	 * Set the current state
171 	 *
172 	 * @param state
173 	 *
174 	 * @return the current state 
175 	 *
176 	 */
177 	public State set( State state ) {
178 		return curr.set( state );
179 	}
180 
181 
182 	/*** 
183 	 * 
184 	 * multiply
185 	 * 
186 	 * @param state
187 	 *
188 	 * @return the current state 
189 	 * 
190 	 */
191 	public State multiply( State state ) {
192 		return curr.multiply( state );
193 	}
194 
195 	/***
196 	 *
197 	 * Use the Imago to skin an image
198 	 *
199 	 * @param href to load 
200 	 *
201 	 * @return an ImageSkin, or null on fail
202 	 *
203 	 */
204 	public final ImageSkin skinImage( String href ) {
205 		return Imago.skinImage( href );
206 	}
207 
208 	/***
209 	 *
210 	 * Start a new polygon
211 	 *
212 	 */
213 	public final void startPolygon() {
214 		pt_idx = 0;
215 		unseen = false;
216 	}
217 	
218 	/***
219 	 *
220 	 * Set the texture coordinate for the current point
221 	 *
222 	 * @param s coordinate in texture space 
223 	 * @param t coordinate in texture space
224 	 *
225 	 */
226 	public final void textCoord( float s, float t ) {
227 		pt_storage[ pt_idx ].setS( s );
228 		pt_storage[ pt_idx ].setT( t );
229 	}
230 
231 	/***
232 	 *
233 	 * Add a point (to the current polygon)
234 	 *
235 	 * @param x coordinate of the point
236 	 * @param y coordinate of the point
237 	 * @param z coordinate of the point
238 	 *
239 	 */
240 	public final void addPoint( float x, float y, float z ) {
241 		if ( !unseen ) {
242 			tmp_pt.set( x, y, z );
243 			curr.multiply( tmp_pt, pt_storage[ pt_idx++ ] );
244 			
245 			if ( pt_idx == pt_max ) pt_idx = 0;
246 		}
247 	}
248 	
249 	/***
250 	 *
251 	 * Add a point (to the current polygon)
252 	 *
253 	 * @param point to add
254 	 *
255 	 */
256 	public final void addPoint( Pt3 point ) {
257 		curr.multiply( point, pt_storage[ pt_idx++ ] );
258 		if ( pt_idx == pt_max ) pt_idx = 0;
259 
260 		if ( pt_idx == 3 ) {
261 			norm.normal(  
262 				pt_storage[ 0 ],
263 				pt_storage[ 1 ],
264 				pt_storage[ 2 ]
265 			);
266 			getRenderer().setNormal( norm );
267 		}
268 	}
269 
270 	/***
271 	 *	  
272 	 * Get the normal of the current polygon
273 	 *	  
274 	 * @return the normal of the current polygon
275 	 *	  
276 	 */
277 	public final Pt3 getNormal() {
278 		return norm;
279 	}
280 	
281 	/***
282 	 *
283 	 * Finish the current polygon, invokes the drawPolygon method
284 	 * on the renderer
285 	 *
286 	 */
287 	public final void stopPolygon() {
288 		if ( false ) {
289 
290 			// this doesn't seem to work...
291 			if ( norm.z >= 0 ) {
292 				getRenderer().drawPolygon( pt_idx, pt_storage );
293 			}
294 			
295 		} else {
296 			getRenderer().drawPolygon( pt_idx, pt_storage );
297 		}
298 		
299 		pt_idx = 0;
300 		norm.set( 0 );
301 	}
302 
303 	/***
304 	 *
305 	 * Get the maximum number of points a polygon can have
306 	 *
307 	 * @return the maximum number of points a polygon can have
308 	 *
309 	 */
310 	public final int getPolygonPointMax() {
311 		return pt_max;
312 	}
313 		
314 	/***
315 	 *
316 	 * Get the size of the matrix stack
317 	 *
318 	 * @return the size of the matrix stack
319 	 *
320 	 */
321 	public final int getStackSize() { 
322 		return mat_max;
323 	}
324 
325 	/***
326 	 *
327 	 * Silly conveinence method to draw a buncha polygons
328 	 *
329 	 * @param polygon array of array of Pt3 representing the polygons
330 	 *
331 	 */
332 	public final void drawPolygons( Pt3 [][] polygon ) {
333 		int i, j;
334 		for ( i = 0 ; i < polygon.length ; i++ ) {
335 			startPolygon();
336 			for ( j = 0 ; j < polygon[ i ].length ; j++ ) {
337 				textCoord( polygon[ i ][ j ].x, polygon[ i ][ j ].y );
338 				addPoint( polygon[ i ][ j ] );
339 			}
340 			stopPolygon();
341 		}
342 	}
343 
344 	/***
345 	 *
346 	 *
347 	 *
348 	 *
349 	 */
350 	public void render() {
351 		render( this );
352 	}
353 
354 	/***
355 	 *
356 	 *
357 	 *
358 	 *
359 	 */
360 	public void render( Graphics graphics ) {
361 		setGraphics( graphics );
362 		render();
363 	}
364 
365 	/***
366 	 * 
367 	 * Try to create a LiboGraf given the name of the class 
368 	 * It will be initialized with the values passed into the init
369 	 * method of this LiboGraf instance
370 	 *
371 	 * @param nameOfLiboGraf to try to use
372 	 *
373 	 * @return instance of the LiboGraf on success, null on fail
374 	 *
375 	 */
376 	public final static LiboGrafInterface getLiboGrafByName( String nameOfLiboGraf ) {
377 
378 		String cause = "uh...";
379 		LiboGrafInterface yourLiboGraf = null;
380 
381 		Class theClass = com.insanityengine.ghia.util.DocReflect.forName( nameOfLiboGraf );
382 		if ( null == theClass ) {
383 			cause = "class for name failed for " + nameOfLiboGraf;
384 		} else {
385 
386 			String interfaceName = "com.insanityengine.ghia.libograf.LiboGrafInterface";
387 			Class[] interfaces = theClass.getInterfaces();
388 			cause = nameOfLiboGraf + " does not implement " + interfaceName;
389 
390 			try {
391 				yourLiboGraf = ( LiboGrafInterface ) theClass.newInstance();
392 			} catch ( Exception e ) {
393 				e.printStackTrace();
394 				cause = "didn't you see the stacktrace?";
395 			}
396 		}
397 
398 		if ( null == yourLiboGraf ) {
399 			System.err.println( 
400 				"LiboGraf.getLiboGrafByName failed: " + cause 
401 			);
402 		} else {
403 			System.err.println( 
404 				"LiboGraf.getLiboGrafByName succeeded: " + nameOfLiboGraf 
405 			);
406 		}
407 
408 		return yourLiboGraf;
409 	}
410 
411 	/***
412 	 *
413 	 * Get an instance of the default LiboGrafInterface implementation
414 	 *
415 	 * @return an instance of the default LiboGrafInterface implementation
416 	 *
417 	 */
418 	public final static LiboGrafInterface getDefaultLiboGraf() {
419 		return new LiboGraf();
420 	}
421 
422 	/***
423 	 *
424 	 * Create a new LiboGrafInterface using the component
425 	 *
426 	 * @param component to use 
427 	 *
428 	 */
429 	public final static LiboGrafInterface createLiboGrafInterface( Component component ) {
430 		LiboGrafInterface impl = null;
431 		String rname = null;
432 		String pname = "m3_libografName";
433 
434 		if ( component instanceof Applet ) {
435 			try {
436 				rname = ( ( Applet ) component ).getParameter( pname );
437 			} catch ( Exception e ) {
438 			}
439 		}
440 
441 		try {
442 			if ( null == rname ) rname = System.getProperty( pname );
443 		} catch ( Exception e ) {
444 		}
445 
446 		if ( null == rname ) rname = "com.insanityengine.ghia.libograf.LiboGraf";
447 		return getLiboGrafByName( rname );
448 	}
449 	
450 	/***
451 	 *
452 	 * Create a new LiboGrafInterface 
453 	 *
454 	 */
455 	public final static LiboGrafInterface createLiboGrafInterface() {
456 		return createLiboGrafInterface( null );
457 	}
458 
459 	////////////////////////////////////////////////////////
460 	
461 	private static final int pt_max = 8;
462 	private static final int mat_max = 32;
463 
464 	private State curr;
465 	private int mat_idx = 0;
466 	private State[] stack;
467 
468 	// space for addPoint familia
469 	private int pt_idx;
470 	private Pt3 pt_storage[];
471 
472 	private boolean unseen = false;
473 
474 	private Pt3 tmp_pt;
475 	private Pt3 norm;
476 
477 	private void init() {
478 
479 		mat_idx = 0;
480 		pt_idx = 0;
481 
482 		unseen = false;
483 
484 		tmp_pt = new Pt3();
485 		norm = new Pt3();
486 
487 		pt_storage = new Pt3[ pt_max ];
488 		for ( int i = 0 ; i < pt_storage.length ; i++ ) {
489 			pt_storage[ i ] = new Pt3();
490 		}
491 
492 		if ( true ) {
493 			curr = new Matrix();
494 			stack = new Matrix[ mat_max ];
495 			for ( int i = 0 ; i < stack.length ; i ++ ) {
496 				stack[ i ] = new Matrix();
497 			}
498 		} else {
499 			curr = new Quaternion();
500 			stack = new Quaternion[ mat_max ];
501 			for ( int i = 0 ; i < stack.length ; i ++ ) {
502 				stack[ i ] = new Quaternion();
503 			}
504 		}
505 	}
506 };
507 
508 /***
509  *
510  * $Log: LiboGraf.java,v $
511  * Revision 1.11  2005/03/19 17:50:02  brian
512  * repackaging
513  *
514  * Revision 1.10  2005/03/12 04:58:08  brian
515  * quatz are broke, but provide mechanism to use 'em...
516  *
517  * Revision 1.9  2005/03/11 23:35:31  brian
518  * major refactoring to add in com.insanityengine.ghia.libograf.State bitz
519  *
520  * Revision 1.8  2005/03/10 13:31:19  brian
521  * introduce com.insanityengine.ghia/libograf/State to pave the way for quaternions based LiboGrafInterface implementation
522  *
523  * Revision 1.7  2004/09/22 03:03:32  brian
524  * added setMatrix and multiply methods
525  *
526  * Revision 1.6  2004/09/11 19:32:29  brian
527  * effects of adding LiboGrafInterface
528  *
529  * Revision 1.5  2004/09/11 16:23:07  brian
530  * added getLiboGrafByName and getDefaultLiboGraf static methods
531  *
532  * Revision 1.4  2004/09/11 14:42:32  brian
533  * cleanup
534  *
535  * Revision 1.3  2004/09/11 14:37:21  brian
536  * added RendererConsumer and stuff
537  *
538  *
539  */