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
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
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 */