/Users/lyon/j4p/src/ip/raul/Applet3d.java

1    // | The idx3d engine (and this source code) is (c)1998 by Peter Walser 
2    // | Feel free to use this 3d engine for non-commercial purpose, 
3    // | and please set a link to my homepage. 
4    // | If you have any questions concerning the source code the 
5    // | methods and algorithms: send me e-mail. 
6    // | 
7    // | Peter Walser 
8    // | proxima@active.ch 
9    // | http://www.vis.inf.ethz.ch/~pwalser 
10   // | ------------------------------------------------------------- 
11   package ip.raul; 
12    
13   import java.applet.Applet; 
14   import java.awt.Image; 
15   import java.awt.image.ColorModel; 
16   import java.awt.image.MemoryImageSource; 
17   import java.awt.image.PixelGrabber; 
18   import java.util.Date; 
19    
20   public class Applet3d extends Applet { 
21       // Copyright information 
22       public String info = new String( 
23               "idx3d Java 3d ENGINE"); 
24       public String copyright = new String( 
25               "©1998 by Peter Walser"); 
26       public String version = new String( 
27               "Version 2.0 BETA"); 
28       public String build = new String( 
29               "06.10.1998"); 
30       public String sysinfo; 
31    
32       //Scene attributes 
33       int w; 
34       int h; 
35       float centerx; 
36       float centery; 
37    
38       //Objects and Lights 
39       public idx3d_object object[]; 
40       public idx3d_light light[]; 
41       public idx3d_texture texture[]; 
42       public int objects = 0; 
43       public int lights = 0; 
44       public int textures = 0; 
45       public int maxobjects = 0; 
46       public int maxlights = 0; 
47       public int maxtextures = 0; 
48       private idx3d_matrix worldmatrix = new idx3d_matrix(); 
49    
50       //Color management 
51       public int bgcolor; 
52       int alpha = 0xff000000; 
53       int rbit = 0x00ff0000; 
54       int gbit = 0x0000ff00; 
55       int bbit = 0x000000ff; 
56       private ColorModel idx_cm = ColorModel.getRGBdefault(); 
57    
58       //Trigonometry 
59       float sinus[] = new float[360]; 
60       float cosinus[] = new float[360]; 
61       final float pi = (float) 3.14159265; 
62       final float deg2rad = pi / 180; 
63    
64       //Scene parameters 
65       public float perspective = (float) 8; 
66       public float zoomcorrection = (float) 0.72; 
67       public int ambient = 0;  //0..255 
68       public int phong = 80; //0..255 
69       public int reflectivity = 255; //0..255 
70       public boolean staticLight = false; 
71    
72       //Render structures 
73       int LightMap[][] = new int[256][256]; 
74       int ColorMap[][] = new int[256][256]; 
75       int EnvMap[][] = new int[256][256]; 
76       int StaticLightMap[][] = new int[256][256]; 
77       int StaticEnvMap[][] = new int[256][256]; 
78       int zBuffer[][]; 
79       int LEdgeBuffer[]; 
80       int REdgeBuffer[]; 
81       int ZEdgeBufferL[]; 
82       int ZEdgeBufferR[]; 
83       int IEdgeBufferL[]; 
84       int IEdgeBufferR[]; 
85       int NXEdgeBufferL[]; 
86       int NYEdgeBufferL[]; 
87       int NXEdgeBufferR[]; 
88       int NYEdgeBufferR[]; 
89       int TXEdgeBufferL[]; 
90       int TYEdgeBufferL[]; 
91       int TXEdgeBufferR[]; 
92       int TYEdgeBufferR[]; 
93       int zInfinite = 1000 << 16; 
94       int zNear = -1 << 16; 
95    
96       //Output 
97       Image DoubleBuffer = null; 
98       int TargetPixel[]; 
99       int Background[]; 
100   
101      // GENERAL METHODS 
102   
103      public Applet3d(int width, int height) { 
104          myResize(width, height); 
105      } 
106   
107      public void myResize(int width, int height) { 
108          w = width; 
109          h = height; 
110          centerx = (float) w / 2; 
111          centery = (float) h / 2; 
112          sysinfo = getSysInfo(); 
113          TargetPixel = new int[w * h]; 
114          Background = new int[w * h]; 
115          LEdgeBuffer = new int[h]; 
116          REdgeBuffer = new int[h]; 
117          zBuffer = new int[w][h]; 
118          ZEdgeBufferL = new int[h]; 
119          ZEdgeBufferR = new int[h]; 
120          IEdgeBufferL = new int[h]; 
121          IEdgeBufferR = new int[h]; 
122          NXEdgeBufferL = new int[h]; 
123          NYEdgeBufferL = new int[h]; 
124          NXEdgeBufferR = new int[h]; 
125          NYEdgeBufferR = new int[h]; 
126          TXEdgeBufferL = new int[h]; 
127          TYEdgeBufferL = new int[h]; 
128          TXEdgeBufferR = new int[h]; 
129          TYEdgeBufferR = new int[h]; 
130   
131          bgcolor = getIntColor(0, 0, 0); 
132          clearBackground(); 
133          init_LightMap(); 
134          init_ColorMap(); 
135          init_TrigTables(); 
136      } 
137   
138      private String getSysInfo() { 
139          return (System.getProperty("os.arch") + 
140                  " on " + 
141                  System.getProperty("os.name")); 
142      } 
143   
144      private void init_LightMap() { 
145          float NX; 
146          float NY; 
147          float NZ; 
148          for (int j = 0; j < 256; j++) { 
149              for (int i = 0; i < 256; i++) { 
150                  NX = ((float) i - 127) / 127; 
151                  NY = ((float) j - 127) / 127; 
152                  NZ = 
153                  (float) (1 - 
154                           Math.sqrt( 
155                                   NX * NX + 
156                                   NY * NY)); 
157                  LightMap[i][j] = 
158                  crop((int) (NZ * 255), 0, 255); 
159              } 
160          } 
161      } 
162   
163      public void setStatic() { 
164          for (int j = 0; j < 256; j++) { 
165              for (int i = 0; i < 256; i++) { 
166                  StaticLightMap[i][j] = 
167                  getIntensity(2 * i - 255, 
168                               2 * j - 255); 
169                  StaticEnvMap[i][j] = 
170                  getEnvironment(2 * i - 255, 
171                                 2 * j - 255); 
172              } 
173          } 
174          staticLight = true; 
175      } 
176   
177      private void init_ColorMap() { 
178          int H2 = 255 - phong; 
179          for (int x = 0; x < 256; x++) { 
180              for (int y = 0; y < H2; y++) { 
181                  ColorMap[y][x] = (x * y / H2); 
182              } 
183              for (int y = H2; y < 256; y++) { 
184                  ColorMap[y][x] = 
185                  (y + 
186                   (255 - y) * (x - H2) / phong); 
187              } 
188          } 
189      } 
190   
191      private void init_TrigTables() { 
192          for (int i = 0; i < 360; i++) { 
193              sinus[i] = 
194              (float) Math.sin(deg2rad * (float) i); 
195              cosinus[i] = 
196              (float) Math.cos(deg2rad * (float) i); 
197          } 
198      } 
199   
200      public void setPhong(int p) { 
201          phong = p; 
202          init_ColorMap(); 
203      } 
204   
205      public float crop(float a, float b, float c) { 
206          if (a < b) return (b); 
207          if (a > c - 1) return (c - 1); 
208          return a; 
209      } 
210   
211      public int crop(int a, int b, int c) { 
212          if (a < b) return (b); 
213          if (a > c - 1) return (c - 1); 
214          return a; 
215      } 
216   
217      public boolean inrange(int a, int b, int c) { 
218          return ((a >= b) && (a < c)); 
219      } 
220   
221      public boolean inrange(float a, 
222                             float b, 
223                             float c) { 
224          return ((a >= b) && (a < c)); 
225      } 
226   
227      public float rnd() { 
228          return ((float) Math.random() * 2 - 1); 
229      } 
230   
231      public idx3d_node rndNode() { 
232          idx3d_vector v = new idx3d_vector(); 
233          v = rndVector(); 
234          idx3d_node r = new idx3d_node(v.x, 
235                                        v.y, 
236                                        v.z); 
237          r.n = normalize(rndVector()); 
238          return r; 
239      } 
240   
241      public idx3d_vector rndVector() { 
242          idx3d_vector v = new idx3d_vector(); 
243          v.x = rnd(); 
244          v.y = rnd(); 
245          v.z = rnd(); 
246          return v; 
247      } 
248   
249      public int rndColor() { 
250          int r = (int) (Math.random() * 255); 
251          int g = (int) (Math.random() * 255); 
252          int b = (int) (Math.random() * 255); 
253          return getIntColor(r, g, b); 
254      } 
255   
256      // GEOMETRY FUNCTIONS 
257   
258      public idx3d_vector vectordist( 
259              idx3d_vector v1, idx3d_vector v2) { 
260          return new idx3d_vector(v1.x - v2.x, 
261                                  v1.y - v2.y, 
262                                  v1.z - v2.z); 
263      } 
264   
265      public float vectorlength(idx3d_vector v) { 
266          return (float) Math.sqrt( 
267                  v.x * v.x + v.y * v.y + 
268                  v.z * v.z); 
269      } 
270   
271      public idx3d_vector normalize(idx3d_vector v) { 
272          float length = vectorlength(v); 
273          return new idx3d_vector(v.x / length, 
274                                  v.y / length, 
275                                  v.z / length); 
276      } 
277   
278      public idx3d_vector getNormal(idx3d_vector a, 
279                                    idx3d_vector b, 
280                                    idx3d_vector c) { 
281          idx3d_vector n = new idx3d_vector(); 
282          float ax = b.x - a.x; 
283          float ay = b.y - a.y; 
284          float az = b.z - a.z; 
285          float bx = c.x - a.x; 
286          float by = c.y - a.y; 
287          float bz = c.z - a.z; 
288          n.x = ay * bz - by * az; 
289          n.y = az * bx - bz * ax; 
290          n.z = ax * by - bx * ay; 
291          return normalize(n); 
292      } 
293   
294      public idx3d_matrix crossproduct( 
295              idx3d_matrix a, idx3d_matrix b) { 
296          idx3d_matrix c = new idx3d_matrix(); 
297          c.matrix[0][0] = 
298          a.matrix[0][0] * b.matrix[0][0] + 
299          a.matrix[0][1] * b.matrix[1][0] + 
300          a.matrix[0][2] * b.matrix[2][0] + 
301          a.matrix[0][3] * b.matrix[3][0]; 
302          c.matrix[0][1] = 
303          a.matrix[0][0] * b.matrix[0][1] + 
304          a.matrix[0][1] * b.matrix[1][1] + 
305          a.matrix[0][2] * b.matrix[2][1] + 
306          a.matrix[0][3] * b.matrix[3][1]; 
307          c.matrix[0][2] = 
308          a.matrix[0][0] * b.matrix[0][2] + 
309          a.matrix[0][1] * b.matrix[1][2] + 
310          a.matrix[0][2] * b.matrix[2][2] + 
311          a.matrix[0][3] * b.matrix[3][2]; 
312          c.matrix[0][3] = 
313          a.matrix[0][0] * b.matrix[0][3] + 
314          a.matrix[0][1] * b.matrix[1][3] + 
315          a.matrix[0][2] * b.matrix[2][3] + 
316          a.matrix[0][3] * b.matrix[3][3]; 
317          c.matrix[1][0] = 
318          a.matrix[1][0] * b.matrix[0][0] + 
319          a.matrix[1][1] * b.matrix[1][0] + 
320          a.matrix[1][2] * b.matrix[2][0] + 
321          a.matrix[1][3] * b.matrix[3][0]; 
322          c.matrix[1][1] = 
323          a.matrix[1][0] * b.matrix[0][1] + 
324          a.matrix[1][1] * b.matrix[1][1] + 
325          a.matrix[1][2] * b.matrix[2][1] + 
326          a.matrix[1][3] * b.matrix[3][1]; 
327          c.matrix[1][2] = 
328          a.matrix[1][0] * b.matrix[0][2] + 
329          a.matrix[1][1] * b.matrix[1][2] + 
330          a.matrix[1][2] * b.matrix[2][2] + 
331          a.matrix[1][3] * b.matrix[3][2]; 
332          c.matrix[1][3] = 
333          a.matrix[1][0] * b.matrix[0][3] + 
334          a.matrix[1][1] * b.matrix[1][3] + 
335          a.matrix[1][2] * b.matrix[2][3] + 
336          a.matrix[1][3] * b.matrix[3][3]; 
337          c.matrix[2][0] = 
338          a.matrix[2][0] * b.matrix[0][0] + 
339          a.matrix[2][1] * b.matrix[1][0] + 
340          a.matrix[2][2] * b.matrix[2][0] + 
341          a.matrix[2][3] * b.matrix[3][0]; 
342          c.matrix[2][1] = 
343          a.matrix[2][0] * b.matrix[0][1] + 
344          a.matrix[2][1] * b.matrix[1][1] + 
345          a.matrix[2][2] * b.matrix[2][1] + 
346          a.matrix[2][3] * b.matrix[3][1]; 
347          c.matrix[2][2] = 
348          a.matrix[2][0] * b.matrix[0][2] + 
349          a.matrix[2][1] * b.matrix[1][2] + 
350          a.matrix[2][2] * b.matrix[2][2] + 
351          a.matrix[2][3] * b.matrix[3][2]; 
352          c.matrix[2][3] = 
353          a.matrix[2][0] * b.matrix[0][3] + 
354          a.matrix[2][1] * b.matrix[1][3] + 
355          a.matrix[2][2] * b.matrix[2][3] + 
356          a.matrix[2][3] * b.matrix[3][3]; 
357          return c; 
358      } 
359   
360      public idx3d_vector matrixvectorproduct( 
361              idx3d_matrix b, idx3d_vector a) { 
362          idx3d_vector c = new idx3d_vector(); 
363          c.x = a.x * b.matrix[0][0] + 
364                a.y * b.matrix[0][1] + 
365                a.z * b.matrix[0][2] + 
366                b.matrix[0][3]; 
367          c.y = a.x * b.matrix[1][0] + 
368                a.y * b.matrix[1][1] + 
369                a.z * b.matrix[1][2] + 
370                b.matrix[1][3]; 
371          c.z = a.x * b.matrix[2][0] + 
372                a.y * b.matrix[2][1] + 
373                a.z * b.matrix[2][2] + 
374                b.matrix[2][3]; 
375          return c; 
376      } 
377   
378      // DATA MANAGEMENT 
379   
380      public void addObject(int rendermode, 
381                            int color) { 
382          objects += 1; 
383   
384          if (objects >= maxobjects) { 
385              if (object == null) { 
386                  maxobjects = 2; 
387                  object = new idx3d_object[11]; 
388              } else { 
389                  maxobjects *= 2; 
390                  idx3d_object temp[] = new idx3d_object[maxobjects + 
391                                                         1]; 
392                  System.arraycopy(object, 
393                                   1, 
394                                   temp, 
395                                   1, 
396                                   objects); 
397                  object = temp; 
398              } 
399          } 
400          object[objects] = 
401          new idx3d_object(rendermode, color); 
402      } 
403   
404      public void addLight(idx3d_vector v, 
405                           int mode, 
406                           int intensity) { 
407          lights += 1; 
408   
409          if (lights >= maxlights) { 
410              if (light == null) { 
411                  maxlights = 10; 
412                  light = new idx3d_light[11]; 
413              } else { 
414                  maxlights += 10; 
415                  idx3d_light temp[] = new idx3d_light[maxlights + 
416                                                       1]; 
417                  System.arraycopy(light, 
418                                   1, 
419                                   temp, 
420                                   1, 
421                                   lights); 
422                  light = temp; 
423              } 
424          } 
425          if (mode == 1) v = normalize(v); 
426          light[lights] = 
427          new idx3d_light(v, mode, intensity); 
428      } 
429   
430      public void addTexture(Image img) { 
431          textures += 1; 
432   
433          if (textures >= maxtextures) { 
434              if (texture == null) { 
435                  maxtextures = 20; 
436                  texture = new idx3d_texture[21]; 
437              } else { 
438                  maxtextures *= 2; 
439                  idx3d_texture temp[] = new idx3d_texture[maxtextures + 
440                                                           1]; 
441                  System.arraycopy(texture, 
442                                   1, 
443                                   temp, 
444                                   1, 
445                                   textures); 
446                  texture = temp; 
447              } 
448          } 
449          texture[textures] = new idx3d_texture(); 
450          while (img.getWidth(this) < 0 || 
451                 img.getHeight(this) < 0) { 
452          } 
453          int width = img.getWidth(this); 
454          int height = img.getHeight(this); 
455          texture[textures].w = width; 
456          texture[textures].h = height; 
457          texture[textures].pixel = 
458          new int[width][height]; 
459          int temp2[] = new int[width * height]; 
460          PixelGrabber pg = new PixelGrabber(img, 
461                                             0, 
462                                             0, 
463                                             width, 
464                                             height, 
465                                             temp2, 
466                                             0, 
467                                             width); 
468          try { 
469              pg.grabPixels(); 
470          } catch (InterruptedException e) { 
471          } 
472          for (int j = 0; j < height; j++) { 
473              for (int i = 0; i < width; i++) { 
474                  texture[textures].pixel[i][j] = 
475                  temp2[i + j * width]; 
476              } 
477          } 
478      } 
479   
480      public void addTriangle(int objectNr, 
481                              int p1, 
482                              int p2, 
483                              int p3) { 
484          object[objectNr].triangles += 1; 
485   
486          if (object[objectNr].triangles >= 
487              object[objectNr].maxtriangles) { 
488              if (object[objectNr].triangle == 
489                  null) { 
490                  object[objectNr].maxtriangles = 
491                  2; 
492                  object[objectNr].triangle = 
493                  new idx3d_triangle[11]; 
494              } else { 
495                  object[objectNr].maxtriangles *= 
496                  2; 
497                  idx3d_triangle temp[] = new idx3d_triangle[object[objectNr].maxtriangles + 
498                                                             1]; 
499                  System.arraycopy( 
500                          object[objectNr].triangle, 
501                          1, 
502                          temp, 
503                          1, 
504                          object[objectNr].triangles); 
505                  object[objectNr].triangle = temp; 
506              } 
507          } 
508          object[objectNr].triangle[object[objectNr].triangles] = 
509          new idx3d_triangle(p1, p2, p3); 
510          object[objectNr].triangle[object[objectNr].triangles].n = 
511          getNormal(object[objectNr].node[p1].v, 
512                    object[objectNr].node[p3].v, 
513                    object[objectNr].node[p2].v); 
514      } 
515   
516      public void addNode(int objectNr, 
517                          idx3d_node t) { 
518          object[objectNr].nodes += 1; 
519   
520          if (object[objectNr].nodes >= 
521              object[objectNr].maxnodes) { 
522              if (object[objectNr].node == null) { 
523                  object[objectNr].maxnodes = 2; 
524                  object[objectNr].node = 
525                  new idx3d_node[11]; 
526              } else { 
527                  object[objectNr].maxnodes *= 2; 
528                  idx3d_node temp[] = new idx3d_node[object[objectNr].maxnodes + 
529                                                     1]; 
530                  System.arraycopy( 
531                          object[objectNr].node, 
532                          1, 
533                          temp, 
534                          1, 
535                          object[objectNr].nodes); 
536                  object[objectNr].node = temp; 
537              } 
538          } 
539          t.n = normalize(t.n); 
540          object[objectNr].node[object[objectNr].nodes] = 
541          t; 
542      } 
543   
544      public void addNode(int objectNr, 
545                          float x, 
546                          float y, 
547                          float z) { 
548          addNode(objectNr, 
549                  new idx3d_node(x, y, z)); 
550      } 
551   
552      // OBJECT MANIPULATION 
553   
554      public idx3d_matrix shiftMatrix(float dx, 
555                                      float dy, 
556                                      float dz) { 
557          idx3d_matrix m = new idx3d_matrix(); 
558          m.matrix[0][3] = dx; 
559          m.matrix[1][3] = dy; 
560          m.matrix[2][3] = dz; 
561          return m; 
562      } 
563   
564      public idx3d_matrix scaleMatrix(float dx, 
565                                      float dy, 
566                                      float dz) { 
567          idx3d_matrix m = new idx3d_matrix(); 
568          m.matrix[0][0] = dx; 
569          m.matrix[1][1] = dy; 
570          m.matrix[2][2] = dz; 
571          return m; 
572      } 
573   
574      public idx3d_matrix rotateMatrix(float dx, 
575                                       float dy, 
576                                       float dz) { 
577          float SIN; 
578          float COS; 
579          int angle; 
580          idx3d_matrix out = new idx3d_matrix(); 
581   
582          if (dx != 0) { 
583              idx3d_matrix m = new idx3d_matrix(); 
584              angle = ((int) dx + 1440) % 360; 
585              SIN = sinus[angle]; 
586              COS = cosinus[angle]; 
587              m.matrix[1][1] = COS; 
588              m.matrix[1][2] = SIN; 
589              m.matrix[2][1] = -SIN; 
590              m.matrix[2][2] = COS; 
591              out = crossproduct(m, out); 
592          } 
593          if (dy != 0) { 
594              idx3d_matrix m = new idx3d_matrix(); 
595              angle = ((int) dy + 720) % 360; 
596              SIN = sinus[angle]; 
597              COS = cosinus[angle]; 
598              m.matrix[0][0] = COS; 
599              m.matrix[0][2] = SIN; 
600              m.matrix[2][0] = -SIN; 
601              m.matrix[2][2] = COS; 
602              out = crossproduct(m, out); 
603          } 
604          if (dz != 0) { 
605              idx3d_matrix m = new idx3d_matrix(); 
606              angle = ((int) dz + 720) % 360; 
607              SIN = sinus[angle]; 
608              COS = cosinus[angle]; 
609              m.matrix[0][0] = COS; 
610              m.matrix[0][1] = SIN; 
611              m.matrix[1][0] = -SIN; 
612              m.matrix[1][1] = COS; 
613              out = crossproduct(m, out); 
614          } 
615          return out; 
616      } 
617   
618      public void shiftObject(int o, 
619                              float dx, 
620                              float dy, 
621                              float dz) { 
622          object[o].matrix = 
623          crossproduct(shiftMatrix(dx, dy, dz), 
624                       object[o].matrix); 
625      } 
626   
627      public void scaleObject(int o, 
628                              float dx, 
629                              float dy, 
630                              float dz) { 
631          object[o].matrix = 
632          crossproduct(scaleMatrix(dx, dy, dz), 
633                       object[o].matrix); 
634      } 
635   
636      public void rotateObject(int o, 
637                               float dx, 
638                               float dy, 
639                               float dz) { 
640          object[o].matrix = 
641          crossproduct(object[o].matrix, 
642                       rotateMatrix(dx, dy, dz)); 
643      } 
644   
645      public void rotateObjectWorld(int o, 
646                                    float dx, 
647                                    float dy, 
648                                    float dz) { 
649          object[o].matrix = 
650          crossproduct(rotateMatrix(dx, dy, dz), 
651                       object[o].matrix); 
652      } 
653   
654      public void rotateObject(int obj, 
655                               float px, 
656                               float py, 
657                               float pz, 
658                               float dx, 
659                               float dy, 
660                               float dz) { 
661          shiftObject(obj, -px, -py, -pz); 
662          rotateObject(obj, dx, dy, dz); 
663          shiftObject(obj, px, py, pz); 
664      } 
665   
666      public void shiftWorld(float dx, 
667                             float dy, 
668                             float dz) { 
669          worldmatrix = 
670          crossproduct(shiftMatrix(dx, dy, dz), 
671                       worldmatrix); 
672      } 
673   
674      public void scaleWorld(float dx, 
675                             float dy, 
676                             float dz) { 
677          worldmatrix = 
678          crossproduct(scaleMatrix(dx, dy, dz), 
679                       worldmatrix); 
680      } 
681   
682      public void rotateWorld(float dx, 
683                              float dy, 
684                              float dz) { 
685          worldmatrix = 
686          crossproduct(rotateMatrix(dx, dy, dz), 
687                       worldmatrix); 
688      } 
689   
690      public void scaleObject(int obj, float d) { 
691          scaleObject(obj, d, d, d); 
692      } 
693   
694      public void scaleWorld(float d) { 
695          scaleWorld(d, d, d); 
696      } 
697   
698      // RENDERING 
699   
700      public Image renderScene() { 
701          clearDoubleBuffer(); 
702          paintObjects(); 
703          paintImage(); 
704          return DoubleBuffer; 
705      } 
706   
707      private void clearDoubleBuffer() { 
708          for (int j = 0; j < h; j++) { 
709              for (int i = 0; i < w; i++) { 
710                  zBuffer[i][j] = zInfinite; 
711              } 
712          } 
713          for (int i = 0; i < w * h; i++) { 
714              TargetPixel[i] = Background[i]; 
715          } 
716      } 
717   
718      private void clearBackground() { 
719          for (int i = 0; i < w * h; i++) { 
720              Background[i] = bgcolor; 
721          } 
722      } 
723   
724      private void paintObjects() { 
725          for (int i = 1; i <= objects; i++) { 
726              object[i].matrix2 = 
727              crossproduct(worldmatrix, 
728                           object[i].matrix); 
729              for (int j = 1; j <= object[i].nodes; j++) { 
730                  object[i].node[j] = 
731                  projectNode(i, 
732                              object[i].node[j]); 
733              } 
734              for (int j = 1; j <= 
735                              object[i].triangles; j++) { 
736                  if (object[i].mode == 1) drawWireframe( 
737                          i, 
738                          object[i].triangle[j]); 
739                  if (object[i].mode == 2) drawFlatshaded( 
740                          i, 
741                          object[i].triangle[j]); 
742                  if (object[i].mode == 3) drawGouraud( 
743                          i, 
744                          object[i].triangle[j]); 
745                  if (object[i].mode == 4) drawPhong( 
746                          i, 
747                          object[i].triangle[j]); 
748                  if (object[i].mode == 5) drawEnvmapped( 
749                          i, 
750                          object[i].triangle[j]); 
751                  if (object[i].mode == 6) drawGouraudTexture( 
752                          i, 
753                          object[i].triangle[j]); 
754                  if (object[i].mode == 7) drawPhongTexture( 
755                          i, 
756                          object[i].triangle[j]); 
757                  if (object[i].mode == 8) drawEnvmappedTexture( 
758                          i, 
759                          object[i].triangle[j]); 
760              } 
761          } 
762      } 
763   
764      private void paintImage() { 
765          DoubleBuffer = 
766          createImage( 
767                  new MemoryImageSource(w, 
768                                        h, 
769                                        idx_cm, 
770                                        TargetPixel, 
771                                        0, 
772                                        w)); 
773      } 
774   
775      private idx3d_node projectNode(int obj, 
776                                     idx3d_node q) { 
777          idx3d_node w = q; 
778          idx3d_vector mvect = matrixvectorproduct( 
779                  object[obj].matrix2, w.v); 
780          w.n2 = 
781          normalize( 
782                  matrixvectorproduct( 
783                          object[obj].matrix2, 
784                          w.n)); 
785   
786          float zoom = perspective / 
787                       (perspective + mvect.z) * 
788                       zoomcorrection; 
789          w.xx = 
790          (int) (mvect.x * zoom * centerx + 
791                 centerx); 
792          w.yy = 
793          (int) (mvect.y * zoom * centery + 
794                 centery); 
795          w.zz = (int) (mvect.z * 65536); 
796          return w; 
797      } 
798   
799      private int getIntensity(int nx, int ny) { 
800          if (staticLight) return StaticLightMap[nx / 
801                                                 2 + 
802                                                 127][ny / 
803                                                      2 + 
804                                                      127]; 
805          int nz = LightMap[nx / 2 + 127][ny / 2 + 
806                                          127]; 
807          int intensity = ambient; 
808          for (int i = 1; i <= lights; i++) { 
809              if (light[i].mode == 1) { 
810                  intensity += 
811                  crop( 
812                          (light[i].intensity * 
813                           (int) Math.abs( 
814                                   nx * light[i].x + 
815                                   ny * light[i].y + 
816                                   nz * light[i].z) >> 
817                           8) >> 
818                          8, 
819                          0, 
820                          255); 
821              } 
822              if (light[i].mode == 2) { 
823                  // POINT LIGHT ALGORITHM TO BE IMPLEMENTED HERE 
824              } 
825          } 
826          return crop(intensity, 0, 255); 
827      } 
828   
829      private int getIntensity(idx3d_vector v) { 
830          return getIntensity((int) (v.x * 255), 
831                              (int) (v.y * 255)); 
832      } 
833   
834      private int getEnvironment(int nx, int ny) { 
835          if (staticLight) return StaticEnvMap[nx / 
836                                               2 + 
837                                               127][ny / 
838                                                    2 + 
839                                                    127]; 
840          int env = EnvMap[nx / 2 + 127][ny / 2 + 
841                                         127]; 
842          return crop( 
843                  ambient + 
844                  getIntensity(nx, ny) * env * 
845                  reflectivity / 
846                  65536, 
847                  0, 
848                  255); 
849      } 
850   
851      public int getIntColor(int r, int g, int b) { 
852          return alpha | (r << 16) | (g << 8) | b; 
853      } 
854   
855      private int getColor(int c, int intensity) { 
856          int r = ColorMap[intensity][(rbit & c) >> 
857                                      16]; 
858          int g = ColorMap[intensity][(gbit & c) >> 
859                                      8]; 
860          int b = ColorMap[intensity][(bbit & c)]; 
861          return getIntColor(r, g, b); 
862      } 
863   
864      private int getGray(int c) { 
865          return (((rbit & c) >> 16) + 
866                  ((gbit & c) >> 8) + 
867                  (bbit & c)) / 
868                 3; 
869          //return (bbit&c); 
870      } 
871   
872      public void setBackground(Image TempImage) { 
873          PixelGrabber pg = new PixelGrabber( 
874                  TempImage, 
875                  0, 
876                  0, 
877                  w, 
878                  h, 
879                  Background, 
880                  0, 
881                  w); 
882          try { 
883              pg.grabPixels(); 
884          } catch (InterruptedException e) { 
885          } 
886      } 
887   
888      public void setEnvironment(Image TempImage) { 
889          int temp[] = new int[256 * 256]; 
890          PixelGrabber pg = new PixelGrabber( 
891                  TempImage, 
892                  0, 
893                  0, 
894                  256, 
895                  256, 
896                  temp, 
897                  0, 
898                  256); 
899          try { 
900              pg.grabPixels(); 
901          } catch (InterruptedException e) { 
902          } 
903          for (int i = 0; i < 256; i++) { 
904              for (int j = 0; j < 256; j++) { 
905                  EnvMap[i][j] = 
906                  getGray(temp[i + j * 256]); 
907              } 
908          } 
909      } 
910   
911      // RENDERMODES 
912   
913      private void drawLine(idx3d_node q1, 
914                            idx3d_node q2, 
915                            int color) { 
916          idx3d_node temp; 
917          int dx = (int) Math.abs(q1.xx - q2.xx); 
918          int dy = (int) Math.abs(q1.yy - q2.yy); 
919          int dz = 0; 
920          int x, y, z; 
921          int x2, y2; 
922   
923          if (dx > dy) { 
924              if (q1.xx > q2.xx) { 
925                  temp = q1; 
926                  q1 = q2; 
927                  q2 = temp; 
928              } 
929              if (dx > 0) { 
930                  dz = (q2.zz - q1.zz) / dx; 
931                  dy = ((q2.yy - q1.yy) << 16) / 
932                       dx; 
933              } 
934              z = q1.zz; 
935              y = q1.yy << 16; 
936              for (x = q1.xx; x <= q2.xx; x++) { 
937                  y2 = y >> 16; 
938                  if (inrange(x, 0, w) && 
939                      inrange(y2, 0, h)) { 
940                      if (z < zBuffer[x][y2]) { 
941                          TargetPixel[x + y2 * w] = 
942                          color; 
943                          zBuffer[x][y2] = z; 
944                      } 
945                  } 
946                  z += dz; 
947                  y += dy; 
948              } 
949          } else { 
950              if (q1.yy > q2.yy) { 
951                  temp = q1; 
952                  q1 = q2; 
953                  q2 = temp; 
954              } 
955              if (dy > 0) { 
956                  dz = (q2.zz - q1.zz) / dy; 
957                  dx = ((q2.xx - q1.xx) << 16) / 
958                       dy; 
959              } 
960              z = q1.zz; 
961              x = q1.xx << 16; 
962              for (y = q1.yy; y <= q2.yy; y++) { 
963                  x2 = x >> 16; 
964                  if (inrange(x2, 0, w) && 
965                      inrange(y, 0, h)) { 
966                      if (z < zBuffer[x2][y]) { 
967                          TargetPixel[x2 + y * w] = 
968                          color; 
969                          zBuffer[x2][y] = z; 
970                      } 
971                  } 
972                  z += dz; 
973                  x += dx; 
974              } 
975          } 
976      } 
977   
978      private void drawWireframe(int obj, 
979                                 idx3d_triangle t) { 
980   
981          int c = object[obj].color; 
982   
983          idx3d_node p1 = object[obj].node[t.p1]; 
984          idx3d_node p2 = object[obj].node[t.p2]; 
985          idx3d_node p3 = object[obj].node[t.p3]; 
986   
987          drawLine(p1, p2, c); 
988          drawLine(p2, p3, c); 
989          drawLine(p1, p3, c); 
990      } 
991   
992      private void drawFlatshaded(int obj, 
993                                  idx3d_triangle t) { 
994          idx3d_vector n = normalize( 
995                  matrixvectorproduct( 
996                          object[obj].matrix, t.n)); 
997   
998   
999          idx3d_node temp1; 
1000  
1001         idx3d_node p1 = object[obj].node[t.p1]; 
1002         idx3d_node p2 = object[obj].node[t.p2]; 
1003         idx3d_node p3 = object[obj].node[t.p3]; 
1004  
1005         if (p1.yy > p2.yy) { 
1006             temp1 = p1; 
1007             p1 = p2; 
1008             p2 = temp1; 
1009         } 
1010         if (p2.yy > p3.yy) { 
1011             temp1 = p2; 
1012             p2 = p3; 
1013             p3 = temp1; 
1014         } 
1015         if (p1.yy > p2.yy) { 
1016             temp1 = p1; 
1017             p1 = p2; 
1018             p2 = temp1; 
1019         } 
1020  
1021         int x1 = p1.xx << 16; 
1022         int x2 = p2.xx << 16; 
1023         int x3 = p3.xx << 16; 
1024         int y1 = p1.yy << 16; 
1025         int y2 = p2.yy << 16; 
1026         int y3 = p3.yy << 16; 
1027  
1028         int dx1 = 0; 
1029         int dx2 = 0; 
1030         int dx3 = 0; 
1031         int dz1 = 0; 
1032         int dz2 = 0; 
1033         int dz3 = 0; 
1034         int dy; 
1035         if (y2 != y1) { 
1036             dy = (y2 - y1) >> 16; 
1037             dx1 = (x2 - x1) / dy; 
1038             dz1 = (p2.zz - p1.zz) / dy; 
1039         } 
1040         if (y3 != y2) { 
1041             dy = (y3 - y2) >> 16; 
1042             dx2 = (x3 - x2) / dy; 
1043             dz2 = (p3.zz - p2.zz) / dy; 
1044         } 
1045         if (y3 != y1) { 
1046             dy = (y3 - y1) >> 16; 
1047             dx3 = (x3 - x1) / dy; 
1048             dz3 = (p3.zz - p1.zz) / dy; 
1049         } 
1050  
1051         int xL = x1; 
1052         int xR = x1; 
1053         int zL = p1.zz; 
1054         int zR = p1.zz; 
1055  
1056         y1 = y1 >> 16; 
1057         y2 = y2 >> 16; 
1058         y3 = y3 >> 16; 
1059  
1060         for (int k = y1; k < y2; k++) { 
1061             if ((k >= 0) && (k < h)) { 
1062                 LEdgeBuffer[k] = xL >> 16; 
1063                 REdgeBuffer[k] = xR >> 16; 
1064                 ZEdgeBufferL[k] = zL; 
1065                 ZEdgeBufferR[k] = zR; 
1066             } 
1067             xL += dx1; 
1068             xR += dx3; 
1069             zL += dz1; 
1070             zR += dz3; 
1071         } 
1072         xL = x2; 
1073         zL = p2.zz; 
1074         for (int k = y2; k <= y3; k++) { 
1075             if ((k >= 0) && (k < h)) { 
1076                 LEdgeBuffer[k] = xL >> 16; 
1077                 REdgeBuffer[k] = xR >> 16; 
1078                 ZEdgeBufferL[k] = zL; 
1079                 ZEdgeBufferR[k] = zR; 
1080             } 
1081             xL += dx2; 
1082             xR += dx3; 
1083             zL += dz2; 
1084             zR += dz3; 
1085         } 
1086  
1087         y1 = crop(y1, 0, h); 
1088         y3 = crop(y3, 0, h); 
1089  
1090         for (int j = y1; j <= y3; j++) drawFlatshadedLine( 
1091                 j, 
1092                 getColor(object[obj].color, 
1093                          getIntensity(n))); 
1094     } 
1095  
1096     private void drawGouraud(int obj, 
1097                              idx3d_triangle t) { 
1098  
1099         idx3d_node temp1; 
1100  
1101         idx3d_node p1 = object[obj].node[t.p1]; 
1102         idx3d_node p2 = object[obj].node[t.p2]; 
1103         idx3d_node p3 = object[obj].node[t.p3]; 
1104  
1105         if (p1.yy > p2.yy) { 
1106             temp1 = p1; 
1107             p1 = p2; 
1108             p2 = temp1; 
1109         } 
1110         if (p2.yy > p3.yy) { 
1111             temp1 = p2; 
1112             p2 = p3; 
1113             p3 = temp1; 
1114         } 
1115         if (p1.yy > p2.yy) { 
1116             temp1 = p1; 
1117             p1 = p2; 
1118             p2 = temp1; 
1119         } 
1120  
1121         int i1 = getIntensity(p1.n2) << 8; 
1122         int i2 = getIntensity(p2.n2) << 8; 
1123         int i3 = getIntensity(p3.n2) << 8; 
1124  
1125         int x1 = p1.xx << 16; 
1126         int x2 = p2.xx << 16; 
1127         int x3 = p3.xx << 16; 
1128         int y1 = p1.yy << 16; 
1129         int y2 = p2.yy << 16; 
1130         int y3 = p3.yy << 16; 
1131  
1132         int dx1 = 0; 
1133         int dx2 = 0; 
1134         int dx3 = 0; 
1135         int dz1 = 0; 
1136         int dz2 = 0; 
1137         int dz3 = 0; 
1138         int di1 = 0; 
1139         int di2 = 0; 
1140         int di3 = 0; 
1141         int dy; 
1142         if (y2 != y1) { 
1143             dy = (y2 - y1) >> 16; 
1144             dx1 = (x2 - x1) / dy; 
1145             dz1 = (p2.zz - p1.zz) / dy; 
1146             di1 = (i2 - i1) / dy; 
1147         } 
1148         if (y3 != y2) { 
1149             dy = (y3 - y2) >> 16; 
1150             dx2 = (x3 - x2) / dy; 
1151             dz2 = (p3.zz - p2.zz) / dy; 
1152             di2 = (i3 - i2) / dy; 
1153         } 
1154         if (y3 != y1) { 
1155             dy = (y3 - y1) >> 16; 
1156             dx3 = (x3 - x1) / dy; 
1157             dz3 = (p3.zz - p1.zz) / dy; 
1158             di3 = (i3 - i1) / dy; 
1159         } 
1160  
1161         int xL = x1; 
1162         int xR = x1; 
1163         int zL = p1.zz; 
1164         int zR = p1.zz; 
1165         int iL = i1; 
1166         int iR = i1; 
1167  
1168         y1 = y1 >> 16; 
1169         y2 = y2 >> 16; 
1170         y3 = y3 >> 16; 
1171  
1172         for (int k = y1; k < y2; k++) { 
1173             if ((k >= 0) && (k < h)) { 
1174                 LEdgeBuffer[k] = xL >> 16; 
1175                 REdgeBuffer[k] = xR >> 16; 
1176                 ZEdgeBufferL[k] = zL; 
1177                 ZEdgeBufferR[k] = zR; 
1178                 IEdgeBufferL[k] = iL; 
1179                 IEdgeBufferR[k] = iR; 
1180             } 
1181             xL += dx1; 
1182             xR += dx3; 
1183             zL += dz1; 
1184             zR += dz3; 
1185             iL += di1; 
1186             iR += di3; 
1187         } 
1188         xL = x2; 
1189         zL = p2.zz; 
1190         iL = i2; 
1191         for (int k = y2; k <= y3; k++) { 
1192             if ((k >= 0) && (k < h)) { 
1193                 LEdgeBuffer[k] = xL >> 16; 
1194                 REdgeBuffer[k] = xR >> 16; 
1195                 ZEdgeBufferL[k] = zL; 
1196                 ZEdgeBufferR[k] = zR; 
1197                 IEdgeBufferL[k] = iL; 
1198                 IEdgeBufferR[k] = iR; 
1199             } 
1200             xL += dx2; 
1201             xR += dx3; 
1202             zL += dz2; 
1203             zR += dz3; 
1204             iL += di2; 
1205             iR += di3; 
1206         } 
1207  
1208         y1 = crop(y1, 0, h); 
1209         y3 = crop(y3, 0, h); 
1210  
1211         for (int j = y1; j <= y3; j++) drawGouraudLine( 
1212                 j, object[obj].color); 
1213     } 
1214  
1215     private void drawPhong(int obj, 
1216                            idx3d_triangle t) { 
1217  
1218         idx3d_node temp1; 
1219  
1220         idx3d_node p1 = object[obj].node[t.p1]; 
1221         idx3d_node p2 = object[obj].node[t.p2]; 
1222         idx3d_node p3 = object[obj].node[t.p3]; 
1223  
1224         if (p1.yy > p2.yy) { 
1225             temp1 = p1; 
1226             p1 = p2; 
1227             p2 = temp1; 
1228         } 
1229         if (p2.yy > p3.yy) { 
1230             temp1 = p2; 
1231             p2 = p3; 
1232             p3 = temp1; 
1233         } 
1234         if (p1.yy > p2.yy) { 
1235             temp1 = p1; 
1236             p1 = p2; 
1237             p2 = temp1; 
1238         } 
1239  
1240         int x1 = p1.xx << 16; 
1241         int x2 = p2.xx << 16; 
1242         int x3 = p3.xx << 16; 
1243         int y1 = p1.yy << 16; 
1244         int y2 = p2.yy << 16; 
1245         int y3 = p3.yy << 16; 
1246  
1247         int nx1 = (int) (65536 * p1.n2.x); 
1248         int nx2 = (int) (65536 * p2.n2.x); 
1249         int nx3 = (int) (65536 * p3.n2.x); 
1250         int ny1 = (int) (65536 * p1.n2.y); 
1251         int ny2 = (int) (65536 * p2.n2.y); 
1252         int ny3 = (int) (65536 * p3.n2.y); 
1253  
1254         int dx1 = 0; 
1255         int dx2 = 0; 
1256         int dx3 = 0; 
1257         int dz1 = 0; 
1258         int dz2 = 0; 
1259         int dz3 = 0; 
1260         int dnx1 = 0; 
1261         int dnx2 = 0; 
1262         int dnx3 = 0; 
1263         int dny1 = 0; 
1264         int dny2 = 0; 
1265         int dny3 = 0; 
1266         int dy; 
1267         if (y2 != y1) { 
1268             dy = (y2 - y1) >> 16; 
1269             dx1 = (x2 - x1) / dy; 
1270             dz1 = (p2.zz - p1.zz) / dy; 
1271             dnx1 = (nx2 - nx1) / dy; 
1272             dny1 = (ny2 - ny1) / dy; 
1273         } 
1274         if (y3 != y2) { 
1275             dy = (y3 - y2) >> 16; 
1276             dx2 = (x3 - x2) / dy; 
1277             dz2 = (p3.zz - p2.zz) / dy; 
1278             dnx2 = (nx3 - nx2) / dy; 
1279             dny2 = (ny3 - ny2) / dy; 
1280         } 
1281         if (y3 != y1) { 
1282             dy = (y3 - y1) >> 16; 
1283             dx3 = (x3 - x1) / dy; 
1284             dz3 = (p3.zz - p1.zz) / dy; 
1285             dnx3 = (nx3 - nx1) / dy; 
1286             dny3 = (ny3 - ny1) / dy; 
1287         } 
1288  
1289         int xL = x1; 
1290         int xR = x1; 
1291         int zL = p1.zz; 
1292         int zR = p1.zz; 
1293         int nxL = nx1; 
1294         int nxR = nx1; 
1295         int nyL = ny1; 
1296         int nyR = ny1; 
1297  
1298         y1 = y1 >> 16; 
1299         y2 = y2 >> 16; 
1300         y3 = y3 >> 16; 
1301  
1302         for (int k = y1; k < y2; k++) { 
1303             if ((k >= 0) && (k < h)) { 
1304                 LEdgeBuffer[k] = xL >> 16; 
1305                 REdgeBuffer[k] = xR >> 16; 
1306                 ZEdgeBufferL[k] = zL; 
1307                 ZEdgeBufferR[k] = zR; 
1308                 NXEdgeBufferL[k] = nxL; 
1309                 NXEdgeBufferR[k] = nxR; 
1310                 NYEdgeBufferL[k] = nyL; 
1311                 NYEdgeBufferR[k] = nyR; 
1312             } 
1313             xL += dx1; 
1314             xR += dx3; 
1315             zL += dz1; 
1316             zR += dz3; 
1317             nxL += dnx1; 
1318             nxR += dnx3; 
1319             nyL += dny1; 
1320             nyR += dny3; 
1321         } 
1322         xL = x2; 
1323         zL = p2.zz; 
1324         nxL = nx2; 
1325         nyL = ny2; 
1326         for (int k = y2; k <= y3; k++) { 
1327             if ((k >= 0) && (k < h)) { 
1328                 LEdgeBuffer[k] = xL >> 16; 
1329                 REdgeBuffer[k] = xR >> 16; 
1330                 ZEdgeBufferL[k] = zL; 
1331                 ZEdgeBufferR[k] = zR; 
1332                 NXEdgeBufferL[k] = nxL; 
1333                 NXEdgeBufferR[k] = nxR; 
1334                 NYEdgeBufferL[k] = nyL; 
1335                 NYEdgeBufferR[k] = nyR; 
1336             } 
1337             xL += dx2; 
1338             xR += dx3; 
1339             zL += dz2; 
1340             zR += dz3; 
1341             nxL += dnx2; 
1342             nxR += dnx3; 
1343             nyL += dny2; 
1344             nyR += dny3; 
1345         } 
1346  
1347         y1 = crop(y1, 0, h); 
1348         y3 = crop(y3, 0, h); 
1349  
1350         for (int j = y1; j <= y3; j++) drawPhongLine( 
1351                 j, object[obj].color); 
1352     } 
1353  
1354     private void drawEnvmapped(int obj, 
1355                                idx3d_triangle t) { 
1356  
1357         idx3d_node temp1; 
1358  
1359         idx3d_node p1 = object[obj].node[t.p1]; 
1360         idx3d_node p2 = object[obj].node[t.p2]; 
1361         idx3d_node p3 = object[obj].node[t.p3]; 
1362  
1363         if (p1.yy > p2.yy) { 
1364             temp1 = p1; 
1365             p1 = p2; 
1366             p2 = temp1; 
1367         } 
1368         if (p2.yy > p3.yy) { 
1369             temp1 = p2; 
1370             p2 = p3; 
1371             p3 = temp1; 
1372         } 
1373         if (p1.yy > p2.yy) { 
1374             temp1 = p1; 
1375             p1 = p2; 
1376             p2 = temp1; 
1377         } 
1378  
1379         int x1 = p1.xx << 16; 
1380         int x2 = p2.xx << 16; 
1381         int x3 = p3.xx << 16; 
1382         int y1 = p1.yy << 16; 
1383         int y2 = p2.yy << 16; 
1384         int y3 = p3.yy << 16; 
1385  
1386         int nx1 = (int) (65536 * p1.n2.x); 
1387         int nx2 = (int) (65536 * p2.n2.x); 
1388         int nx3 = (int) (65536 * p3.n2.x); 
1389         int ny1 = (int) (65536 * p1.n2.y); 
1390         int ny2 = (int) (65536 * p2.n2.y); 
1391         int ny3 = (int) (65536 * p3.n2.y); 
1392  
1393         int dx1 = 0; 
1394         int dx2 = 0; 
1395         int dx3 = 0; 
1396         int dz1 = 0; 
1397         int dz2 = 0; 
1398         int dz3 = 0; 
1399         int dnx1 = 0; 
1400         int dnx2 = 0; 
1401         int dnx3 = 0; 
1402         int dny1 = 0; 
1403         int dny2 = 0; 
1404         int dny3 = 0; 
1405         int dy; 
1406         if (y2 != y1) { 
1407             dy = (y2 - y1) >> 16; 
1408             dx1 = (x2 - x1) / dy; 
1409             dz1 = (p2.zz - p1.zz) / dy; 
1410             dnx1 = (nx2 - nx1) / dy; 
1411             dny1 = (ny2 - ny1) / dy; 
1412         } 
1413         if (y3 != y2) { 
1414             dy = (y3 - y2) >> 16; 
1415             dx2 = (x3 - x2) / dy; 
1416             dz2 = (p3.zz - p2.zz) / dy; 
1417             dnx2 = (nx3 - nx2) / dy; 
1418             dny2 = (ny3 - ny2) / dy; 
1419         } 
1420         if (y3 != y1) { 
1421             dy = (y3 - y1) >> 16; 
1422             dx3 = (x3 - x1) / dy; 
1423             dz3 = (p3.zz - p1.zz) / dy; 
1424             dnx3 = (nx3 - nx1) / dy; 
1425             dny3 = (ny3 - ny1) / dy; 
1426         } 
1427  
1428         int xL = x1; 
1429         int xR = x1; 
1430         int zL = p1.zz; 
1431         int zR = p1.zz; 
1432         int nxL = nx1; 
1433         int nxR = nx1; 
1434         int nyL = ny1; 
1435         int nyR = ny1; 
1436  
1437         y1 = y1 >> 16; 
1438         y2 = y2 >> 16; 
1439         y3 = y3 >> 16; 
1440  
1441         for (int k = y1; k < y2; k++) { 
1442             if ((k >= 0) && (k < h)) { 
1443                 LEdgeBuffer[k] = xL >> 16; 
1444                 REdgeBuffer[k] = xR >> 16; 
1445                 ZEdgeBufferL[k] = zL; 
1446                 ZEdgeBufferR[k] = zR; 
1447                 NXEdgeBufferL[k] = nxL; 
1448                 NXEdgeBufferR[k] = nxR; 
1449                 NYEdgeBufferL[k] = nyL; 
1450                 NYEdgeBufferR[k] = nyR; 
1451             } 
1452             xL += dx1; 
1453             xR += dx3; 
1454             zL += dz1; 
1455             zR += dz3; 
1456             nxL += dnx1; 
1457             nxR += dnx3; 
1458             nyL += dny1; 
1459             nyR += dny3; 
1460         } 
1461         xL = x2; 
1462         zL = p2.zz; 
1463         nxL = nx2; 
1464         nyL = ny2; 
1465         for (int k = y2; k <= y3; k++) { 
1466             if ((k >= 0) && (k < h)) { 
1467                 LEdgeBuffer[k] = xL >> 16; 
1468                 REdgeBuffer[k] = xR >> 16; 
1469                 ZEdgeBufferL[k] = zL; 
1470                 ZEdgeBufferR[k] = zR; 
1471                 NXEdgeBufferL[k] = nxL; 
1472                 NXEdgeBufferR[k] = nxR; 
1473                 NYEdgeBufferL[k] = nyL; 
1474                 NYEdgeBufferR[k] = nyR; 
1475             } 
1476             xL += dx2; 
1477             xR += dx3; 
1478             zL += dz2; 
1479             zR += dz3; 
1480             nxL += dnx2; 
1481             nxR += dnx3; 
1482             nyL += dny2; 
1483             nyR += dny3; 
1484         } 
1485  
1486         y1 = crop(y1, 0, h); 
1487         y3 = crop(y3, 0, h); 
1488  
1489         for (int j = y1; j <= y3; j++) drawEnvmappedLine( 
1490                 j, object[obj].color); 
1491     } 
1492  
1493     private void drawGouraudTexture(int obj, 
1494                                     idx3d_triangle t) { 
1495  
1496         idx3d_node temp1; 
1497  
1498         idx3d_node p1 = object[obj].node[t.p1]; 
1499         idx3d_node p2 = object[obj].node[t.p2]; 
1500         idx3d_node p3 = object[obj].node[t.p3]; 
1501  
1502         if (p1.yy > p2.yy) { 
1503             temp1 = p1; 
1504             p1 = p2; 
1505             p2 = temp1; 
1506         } 
1507         if (p2.yy > p3.yy) { 
1508             temp1 = p2; 
1509             p2 = p3; 
1510             p3 = temp1; 
1511         } 
1512         if (p1.yy > p2.yy) { 
1513             temp1 = p1; 
1514             p1 = p2; 
1515             p2 = temp1; 
1516         } 
1517  
1518         int i1 = getIntensity(p1.n2) << 8; 
1519         int i2 = getIntensity(p2.n2) << 8; 
1520         int i3 = getIntensity(p3.n2) << 8; 
1521  
1522         int x1 = p1.xx << 16; 
1523         int x2 = p2.xx << 16; 
1524         int x3 = p3.xx << 16; 
1525         int y1 = p1.yy << 16; 
1526         int y2 = p2.yy << 16; 
1527         int y3 = p3.yy << 16; 
1528         float tw = (float) texture[object[obj].texture].w * 
1529                    65536; 
1530         float th = (float) texture[object[obj].texture].h * 
1531                    65536; 
1532         int tx1 = (int) (tw * p1.tx); 
1533         int tx2 = (int) (tw * p2.tx); 
1534         int tx3 = (int) (tw * p3.tx); 
1535         int ty1 = (int) (th * p1.ty); 
1536         int ty2 = (int) (th * p2.ty); 
1537         int ty3 = (int) (th * p3.ty); 
1538  
1539         int dx1 = 0; 
1540         int dx2 = 0; 
1541         int dx3 = 0; 
1542         int dz1 = 0; 
1543         int dz2 = 0; 
1544         int dz3 = 0; 
1545         int di1 = 0; 
1546         int di2 = 0; 
1547         int di3 = 0; 
1548         int dtx1 = 0; 
1549         int dtx2 = 0; 
1550         int dtx3 = 0; 
1551         int dty1 = 0; 
1552         int dty2 = 0; 
1553         int dty3 = 0; 
1554         int dy; 
1555         if (y2 != y1) { 
1556             dy = (y2 - y1) >> 16; 
1557             dx1 = (x2 - x1) / dy; 
1558             dz1 = (p2.zz - p1.zz) / dy; 
1559             di1 = (i2 - i1) / dy; 
1560             dtx1 = (tx2 - tx1) / dy; 
1561             dty1 = (ty2 - ty1) / dy; 
1562         } 
1563         if (y3 != y2) { 
1564             dy = (y3 - y2) >> 16; 
1565             dx2 = (x3 - x2) / dy; 
1566             dz2 = (p3.zz - p2.zz) / dy; 
1567             di2 = (i3 - i2) / dy; 
1568             dtx2 = (tx3 - tx2) / dy; 
1569             dty2 = (ty3 - ty2) / dy; 
1570         } 
1571         if (y3 != y1) { 
1572             dy = (y3 - y1) >> 16; 
1573             dx3 = (x3 - x1) / dy; 
1574             dz3 = (p3.zz - p1.zz) / dy; 
1575             di3 = (i3 - i1) / dy; 
1576             dtx3 = (tx3 - tx1) / dy; 
1577             dty3 = (ty3 - ty1) / dy; 
1578         } 
1579  
1580         int xL = x1; 
1581         int xR = x1; 
1582         int zL = p1.zz; 
1583         int zR = p1.zz; 
1584         int iL = i1; 
1585         int iR = i1; 
1586         int txL = tx1; 
1587         int txR = tx1; 
1588         int tyL = ty1; 
1589         int tyR = ty1; 
1590  
1591         y1 = y1 >> 16; 
1592         y2 = y2 >> 16; 
1593         y3 = y3 >> 16; 
1594  
1595         for (int k = y1; k < y2; k++) { 
1596             if ((k >= 0) && (k < h)) { 
1597                 LEdgeBuffer[k] = xL >> 16; 
1598                 REdgeBuffer[k] = xR >> 16; 
1599                 ZEdgeBufferL[k] = zL; 
1600                 ZEdgeBufferR[k] = zR; 
1601                 IEdgeBufferL[k] = iL; 
1602                 IEdgeBufferR[k] = iR; 
1603                 TXEdgeBufferL[k] = txL; 
1604                 TXEdgeBufferR[k] = txR; 
1605                 TYEdgeBufferL[k] = tyL; 
1606                 TYEdgeBufferR[k] = tyR; 
1607             } 
1608             xL += dx1; 
1609             xR += dx3; 
1610             zL += dz1; 
1611             zR += dz3; 
1612             iL += di1; 
1613             iR += di3; 
1614             txL += dtx1; 
1615             txR += dtx3; 
1616             tyL += dty1; 
1617             tyR += dty3; 
1618         } 
1619         xL = x2; 
1620         zL = p2.zz; 
1621         iL = i2; 
1622         txL = tx2; 
1623         tyL = ty2; 
1624         for (int k = y2; k <= y3; k++) { 
1625             if ((k >= 0) && (k < h)) { 
1626                 LEdgeBuffer[k] = xL >> 16; 
1627                 REdgeBuffer[k] = xR >> 16; 
1628                 ZEdgeBufferL[k] = zL; 
1629                 ZEdgeBufferR[k] = zR; 
1630                 IEdgeBufferL[k] = iL; 
1631                 IEdgeBufferR[k] = iR; 
1632                 TXEdgeBufferL[k] = txL; 
1633                 TXEdgeBufferR[k] = txR; 
1634                 TYEdgeBufferL[k] = tyL; 
1635                 TYEdgeBufferR[k] = tyR; 
1636             } 
1637             xL += dx2; 
1638             xR += dx3; 
1639             zL += dz2; 
1640             zR += dz3; 
1641             iL += di2; 
1642             iR += di3; 
1643             txL += dtx2; 
1644             txR += dtx3; 
1645             tyL += dty2; 
1646             tyR += dty3; 
1647         } 
1648  
1649         y1 = crop(y1, 0, h); 
1650         y3 = crop(y3, 0, h); 
1651  
1652         for (int j = y1; j <= y3; j++) drawGouraudTextureLine( 
1653                 j, object[obj].texture); 
1654     } 
1655  
1656     private void drawPhongTexture(int obj, 
1657                                   idx3d_triangle t) { 
1658  
1659         idx3d_node temp1; 
1660  
1661         idx3d_node p1 = object[obj].node[t.p1]; 
1662         idx3d_node p2 = object[obj].node[t.p2]; 
1663         idx3d_node p3 = object[obj].node[t.p3]; 
1664  
1665         if (p1.yy > p2.yy) { 
1666             temp1 = p1; 
1667             p1 = p2; 
1668             p2 = temp1; 
1669         } 
1670         if (p2.yy > p3.yy) { 
1671             temp1 = p2; 
1672             p2 = p3; 
1673             p3 = temp1; 
1674         } 
1675         if (p1.yy > p2.yy) { 
1676             temp1 = p1; 
1677             p1 = p2; 
1678             p2 = temp1; 
1679         } 
1680  
1681         int x1 = p1.xx << 16; 
1682         int x2 = p2.xx << 16; 
1683         int x3 = p3.xx << 16; 
1684         int y1 = p1.yy << 16; 
1685         int y2 = p2.yy << 16; 
1686         int y3 = p3.yy << 16; 
1687  
1688         int nx1 = (int) (65536 * p1.n2.x); 
1689         int nx2 = (int) (65536 * p2.n2.x); 
1690         int nx3 = (int) (65536 * p3.n2.x); 
1691         int ny1 = (int) (65536 * p1.n2.y); 
1692         int ny2 = (int) (65536 * p2.n2.y); 
1693         int ny3 = (int) (65536 * p3.n2.y); 
1694  
1695         float tw = (float) texture[object[obj].texture].w * 
1696                    65536; 
1697         float th = (float) texture[object[obj].texture].h * 
1698                    65536; 
1699         int tx1 = (int) (tw * p1.tx); 
1700         int tx2 = (int) (tw * p2.tx); 
1701         int tx3 = (int) (tw * p3.tx); 
1702         int ty1 = (int) (th * p1.ty); 
1703         int ty2 = (int) (th * p2.ty); 
1704         int ty3 = (int) (th * p3.ty); 
1705  
1706         int dx1 = 0; 
1707         int dx2 = 0; 
1708         int dx3 = 0; 
1709         int dz1 = 0; 
1710         int dz2 = 0; 
1711         int dz3 = 0; 
1712         int dnx1 = 0; 
1713         int dnx2 = 0; 
1714         int dnx3 = 0; 
1715         int dny1 = 0; 
1716         int dny2 = 0; 
1717         int dny3 = 0; 
1718         int dtx1 = 0; 
1719         int dtx2 = 0; 
1720         int dtx3 = 0; 
1721         int dty1 = 0; 
1722         int dty2 = 0; 
1723         int dty3 = 0; 
1724         int dy; 
1725         if (y2 != y1) { 
1726             dy = (y2 - y1) >> 16; 
1727             dx1 = (x2 - x1) / dy; 
1728             dz1 = (p2.zz - p1.zz) / dy; 
1729             dnx1 = (nx2 - nx1) / dy; 
1730             dny1 = (ny2 - ny1) / dy; 
1731             dtx1 = (tx2 - tx1) / dy; 
1732             dty1 = (ty2 - ty1) / dy; 
1733         } 
1734         if (y3 != y2) { 
1735             dy = (y3 - y2) >> 16; 
1736             dx2 = (x3 - x2) / dy; 
1737             dz2 = (p3.zz - p2.zz) / dy; 
1738             dnx2 = (nx3 - nx2) / dy; 
1739             dny2 = (ny3 - ny2) / dy; 
1740             dtx2 = (tx3 - tx2) / dy; 
1741             dty2 = (ty3 - ty2) / dy; 
1742         } 
1743         if (y3 != y1) { 
1744             dy = (y3 - y1) >> 16; 
1745             dx3 = (x3 - x1) / dy; 
1746             dz3 = (p3.zz - p1.zz) / dy; 
1747             dnx3 = (nx3 - nx1) / dy; 
1748             dny3 = (ny3 - ny1) / dy; 
1749             dtx3 = (tx3 - tx1) / dy; 
1750             dty3 = (ty3 - ty1) / dy; 
1751         } 
1752  
1753         int xL = x1; 
1754         int xR = x1; 
1755         int zL = p1.zz; 
1756         int zR = p1.zz; 
1757         int nxL = nx1; 
1758         int nxR = nx1; 
1759         int nyL = ny1; 
1760         int nyR = ny1; 
1761         int txL = tx1; 
1762         int txR = tx1; 
1763         int tyL = ty1; 
1764         int tyR = ty1; 
1765  
1766         y1 = y1 >> 16; 
1767         y2 = y2 >> 16; 
1768         y3 = y3 >> 16; 
1769  
1770         for (int k = y1; k < y2; k++) { 
1771             if ((k >= 0) && (k < h)) { 
1772                 LEdgeBuffer[k] = xL >> 16; 
1773                 REdgeBuffer[k] = xR >> 16; 
1774                 ZEdgeBufferL[k] = zL; 
1775                 ZEdgeBufferR[k] = zR; 
1776                 NXEdgeBufferL[k] = nxL; 
1777                 NXEdgeBufferR[k] = nxR; 
1778                 NYEdgeBufferL[k] = nyL; 
1779                 NYEdgeBufferR[k] = nyR; 
1780                 TXEdgeBufferL[k] = txL; 
1781                 TXEdgeBufferR[k] = txR; 
1782                 TYEdgeBufferL[k] = tyL; 
1783                 TYEdgeBufferR[k] = tyR; 
1784             } 
1785             xL += dx1; 
1786             xR += dx3; 
1787             zL += dz1; 
1788             zR += dz3; 
1789             nxL += dnx1; 
1790             nxR += dnx3; 
1791             nyL += dny1; 
1792             nyR += dny3; 
1793             txL += dtx1; 
1794             txR += dtx3; 
1795             tyL += dty1; 
1796             tyR += dty3; 
1797         } 
1798         xL = x2; 
1799         zL = p2.zz; 
1800         nxL = nx2; 
1801         nyL = ny2; 
1802         txL = tx2; 
1803         tyL = ty2; 
1804         for (int k = y2; k <= y3; k++) { 
1805             if ((k >= 0) && (k < h)) { 
1806                 LEdgeBuffer[k] = xL >> 16; 
1807                 REdgeBuffer[k] = xR >> 16; 
1808                 ZEdgeBufferL[k] = zL; 
1809                 ZEdgeBufferR[k] = zR; 
1810                 NXEdgeBufferL[k] = nxL; 
1811                 NXEdgeBufferR[k] = nxR; 
1812                 NYEdgeBufferL[k] = nyL; 
1813                 NYEdgeBufferR[k] = nyR; 
1814                 TXEdgeBufferL[k] = txL; 
1815                 TXEdgeBufferR[k] = txR; 
1816                 TYEdgeBufferL[k] = tyL; 
1817                 TYEdgeBufferR[k] = tyR; 
1818             } 
1819             xL += dx2; 
1820             xR += dx3; 
1821             zL += dz2; 
1822             zR += dz3; 
1823             nxL += dnx2; 
1824             nxR += dnx3; 
1825             nyL += dny2; 
1826             nyR += dny3; 
1827             txL += dtx2; 
1828             txR += dtx3; 
1829             tyL += dty2; 
1830             tyR += dty3; 
1831         } 
1832  
1833         y1 = crop(y1, 0, h); 
1834         y3 = crop(y3, 0, h); 
1835  
1836         for (int j = y1; j <= y3; j++) drawPhongTextureLine( 
1837                 j, object[obj].texture); 
1838     } 
1839  
1840     private void drawEnvmappedTexture(int obj, 
1841                                       idx3d_triangle t) { 
1842  
1843         idx3d_node temp1; 
1844  
1845         idx3d_node p1 = object[obj].node[t.p1]; 
1846         idx3d_node p2 = object[obj].node[t.p2]; 
1847         idx3d_node p3 = object[obj].node[t.p3]; 
1848  
1849         if (p1.yy > p2.yy) { 
1850             temp1 = p1; 
1851             p1 = p2; 
1852             p2 = temp1; 
1853         } 
1854         if (p2.yy > p3.yy) { 
1855             temp1 = p2; 
1856             p2 = p3; 
1857             p3 = temp1; 
1858         } 
1859         if (p1.yy > p2.yy) { 
1860             temp1 = p1; 
1861             p1 = p2; 
1862             p2 = temp1; 
1863         } 
1864  
1865         int x1 = p1.xx << 16; 
1866         int x2 = p2.xx << 16; 
1867         int x3 = p3.xx << 16; 
1868         int y1 = p1.yy << 16; 
1869         int y2 = p2.yy << 16; 
1870         int y3 = p3.yy << 16; 
1871  
1872         int nx1 = (int) (65536 * p1.n2.x); 
1873         int nx2 = (int) (65536 * p2.n2.x); 
1874         int nx3 = (int) (65536 * p3.n2.x); 
1875         int ny1 = (int) (65536 * p1.n2.y); 
1876         int ny2 = (int) (65536 * p2.n2.y); 
1877         int ny3 = (int) (65536 * p3.n2.y); 
1878  
1879         float tw = (float) texture[object[obj].texture].w * 
1880                    65536; 
1881         float th = (float) texture[object[obj].texture].h * 
1882                    65536; 
1883         int tx1 = (int) (tw * p1.tx); 
1884         int tx2 = (int) (tw * p2.tx); 
1885         int tx3 = (int) (tw * p3.tx); 
1886         int ty1 = (int) (th * p1.ty); 
1887         int ty2 = (int) (th * p2.ty); 
1888         int ty3 = (int) (th * p3.ty); 
1889  
1890         int dx1 = 0; 
1891         int dx2 = 0; 
1892         int dx3 = 0; 
1893         int dz1 = 0; 
1894         int dz2 = 0; 
1895         int dz3 = 0; 
1896         int dnx1 = 0; 
1897         int dnx2 = 0; 
1898         int dnx3 = 0; 
1899         int dny1 = 0; 
1900         int dny2 = 0; 
1901         int dny3 = 0; 
1902         int dtx1 = 0; 
1903         int dtx2 = 0; 
1904         int dtx3 = 0; 
1905         int dty1 = 0; 
1906         int dty2 = 0; 
1907         int dty3 = 0; 
1908         int dy; 
1909         if (y2 != y1) { 
1910             dy = (y2 - y1) >> 16; 
1911             dx1 = (x2 - x1) / dy; 
1912             dz1 = (p2.zz - p1.zz) / dy; 
1913             dnx1 = (nx2 - nx1) / dy; 
1914             dny1 = (ny2 - ny1) / dy; 
1915             dtx1 = (tx2 - tx1) / dy; 
1916             dty1 = (ty2 - ty1) / dy; 
1917         } 
1918         if (y3 != y2) { 
1919             dy = (y3 - y2) >> 16; 
1920             dx2 = (x3 - x2) / dy; 
1921             dz2 = (p3.zz - p2.zz) / dy; 
1922             dnx2 = (nx3 - nx2) / dy; 
1923             dny2 = (ny3 - ny2) / dy; 
1924             dtx2 = (tx3 - tx2) / dy; 
1925             dty2 = (ty3 - ty2) / dy; 
1926         } 
1927         if (y3 != y1) { 
1928             dy = (y3 - y1) >> 16; 
1929             dx3 = (x3 - x1) / dy; 
1930             dz3 = (p3.zz - p1.zz) / dy; 
1931             dnx3 = (nx3 - nx1) / dy; 
1932             dny3 = (ny3 - ny1) / dy; 
1933             dtx3 = (tx3 - tx1) / dy; 
1934             dty3 = (ty3 - ty1) / dy; 
1935         } 
1936  
1937         int xL = x1; 
1938         int xR = x1; 
1939         int zL = p1.zz; 
1940         int zR = p1.zz; 
1941         int nxL = nx1; 
1942         int nxR = nx1; 
1943         int nyL = ny1; 
1944         int nyR = ny1; 
1945         int txL = tx1; 
1946         int txR = tx1; 
1947         int tyL = ty1; 
1948         int tyR = ty1; 
1949  
1950         y1 = y1 >> 16; 
1951         y2 = y2 >> 16; 
1952         y3 = y3 >> 16; 
1953  
1954         for (int k = y1; k < y2; k++) { 
1955             if ((k >= 0) && (k < h)) { 
1956                 LEdgeBuffer[k] = xL >> 16; 
1957                 REdgeBuffer[k] = xR >> 16; 
1958                 ZEdgeBufferL[k] = zL; 
1959                 ZEdgeBufferR[k] = zR; 
1960                 NXEdgeBufferL[k] = nxL; 
1961                 NXEdgeBufferR[k] = nxR; 
1962                 NYEdgeBufferL[k] = nyL; 
1963                 NYEdgeBufferR[k] = nyR; 
1964                 TXEdgeBufferL[k] = txL; 
1965                 TXEdgeBufferR[k] = txR; 
1966                 TYEdgeBufferL[k] = tyL; 
1967                 TYEdgeBufferR[k] = tyR; 
1968             } 
1969             xL += dx1; 
1970             xR += dx3; 
1971             zL += dz1; 
1972             zR += dz3; 
1973             nxL += dnx1; 
1974             nxR += dnx3; 
1975             nyL += dny1; 
1976             nyR += dny3; 
1977             txL += dtx1; 
1978             txR += dtx3; 
1979             tyL += dty1; 
1980             tyR += dty3; 
1981         } 
1982         xL = x2; 
1983         zL = p2.zz; 
1984         nxL = nx2; 
1985         nyL = ny2; 
1986         txL = tx2; 
1987         tyL = ty2; 
1988         for (int k = y2; k <= y3; k++) { 
1989             if ((k >= 0) && (k < h)) { 
1990                 LEdgeBuffer[k] = xL >> 16; 
1991                 REdgeBuffer[k] = xR >> 16; 
1992                 ZEdgeBufferL[k] = zL; 
1993                 ZEdgeBufferR[k] = zR; 
1994                 NXEdgeBufferL[k] = nxL; 
1995                 NXEdgeBufferR[k] = nxR; 
1996                 NYEdgeBufferL[k] = nyL; 
1997                 NYEdgeBufferR[k] = nyR; 
1998                 TXEdgeBufferL[k] = txL; 
1999                 TXEdgeBufferR[k] = txR; 
2000                 TYEdgeBufferL[k] = tyL; 
2001                 TYEdgeBufferR[k] = tyR; 
2002             } 
2003             xL += dx2; 
2004             xR += dx3; 
2005             zL += dz2; 
2006             zR += dz3; 
2007             nxL += dnx2; 
2008             nxR += dnx3; 
2009             nyL += dny2; 
2010             nyR += dny3; 
2011             txL += dtx2; 
2012             txR += dtx3; 
2013             tyL += dty2; 
2014             tyR += dty3; 
2015         } 
2016  
2017         y1 = crop(y1, 0, h); 
2018         y3 = crop(y3, 0, h); 
2019  
2020         for (int j = y1; j <= y3; j++) drawEnvmappedTextureLine( 
2021                 j, object[obj].texture); 
2022     } 
2023  
2024  
2025     private void drawFlatshadedLine(int y, 
2026                                     int color) { 
2027         if ((y >= 0) && (y < h)) { 
2028             int xL = LEdgeBuffer[y]; 
2029             int xR = REdgeBuffer[y]; 
2030             int zL = ZEdgeBufferL[y]; 
2031             int zR = ZEdgeBufferR[y]; 
2032             if ((xL != xR)) { 
2033                 if (xL > xR) { 
2034                     int temp; 
2035                     temp = xL; 
2036                     xL = xR; 
2037                     xR = temp; 
2038                     temp = zL; 
2039                     zL = zR; 
2040                     zR = temp; 
2041                 } 
2042                 int dz = (zR - zL) / (xR - xL); 
2043                 int z = zL; 
2044  
2045                 xL = crop(xL, 0, w); 
2046                 xR = crop(xR, 0, w); 
2047  
2048                 int offset = y * w; 
2049  
2050                 for (int x = xL; x < xR; x++) { 
2051                     if (z < zBuffer[x][y]) { 
2052                         TargetPixel[x + offset] = 
2053                         color; 
2054                         zBuffer[x][y] = z; 
2055                     } 
2056                     z += dz; 
2057                 } 
2058             } 
2059         } 
2060     } 
2061  
2062     private void drawGouraudLine(int y, 
2063                                  int color) { 
2064         if ((y >= 0) && (y < h)) { 
2065             int xL = LEdgeBuffer[y]; 
2066             int xR = REdgeBuffer[y]; 
2067             int zL = ZEdgeBufferL[y]; 
2068             int zR = ZEdgeBufferR[y]; 
2069             int iL = IEdgeBufferL[y]; 
2070             int iR = IEdgeBufferR[y]; 
2071             if ((xL != xR)) { 
2072                 if (xL > xR) { 
2073                     int temp; 
2074                     temp = xL; 
2075                     xL = xR; 
2076                     xR = temp; 
2077                     temp = zL; 
2078                     zL = zR; 
2079                     zR = temp; 
2080                     temp = iL; 
2081                     iL = iR; 
2082                     iR = temp; 
2083                 } 
2084                 int dx = (xR - xL); 
2085                 int dz = (zR - zL) / dx; 
2086                 int di = (iR - iL) / dx; 
2087                 int z = zL; 
2088                 int i = iL; 
2089  
2090                 xL = crop(xL, 0, w); 
2091                 xR = crop(xR, 0, w); 
2092  
2093                 int offset = y * w; 
2094  
2095                 for (int x = xL; x < xR; x++) { 
2096                     if (z < zBuffer[x][y]) { 
2097                         TargetPixel[x + offset] = 
2098                         getColor(color, i >> 8); 
2099                         zBuffer[x][y] = z; 
2100                     } 
2101                     z += dz; 
2102                     i += di; 
2103                 } 
2104             } 
2105         } 
2106     } 
2107  
2108     private void drawPhongLine(int y, int color) { 
2109         if ((y >= 0) && (y < h)) { 
2110             int xL = LEdgeBuffer[y]; 
2111             int xR = REdgeBuffer[y]; 
2112             int zL = ZEdgeBufferL[y]; 
2113             int zR = ZEdgeBufferR[y]; 
2114             int nxL = NXEdgeBufferL[y]; 
2115             int nxR = NXEdgeBufferR[y]; 
2116             int nyL = NYEdgeBufferL[y]; 
2117             int nyR = NYEdgeBufferR[y]; 
2118             if ((xL != xR)) { 
2119                 if (xL > xR) { 
2120                     int temp; 
2121                     temp = xL; 
2122                     xL = xR; 
2123                     xR = temp; 
2124                     temp = zL; 
2125                     zL = zR; 
2126                     zR = temp; 
2127                     temp = nxL; 
2128                     nxL = nxR; 
2129                     nxR = temp; 
2130                     temp = nyL; 
2131                     nyL = nyR; 
2132                     nyR = temp; 
2133                 } 
2134                 int dx = (xR - xL); 
2135                 int dz = (zR - zL) / dx; 
2136                 int dnx = (nxR - nxL) / dx; 
2137                 int dny = (nyR - nyL) / dx; 
2138                 int z = zL; 
2139                 int nx = nxL; 
2140                 int ny = nyL; 
2141  
2142                 xL = crop(xL, 0, w); 
2143                 xR = crop(xR, 0, w); 
2144  
2145                 int offset = y * w; 
2146  
2147                 for (int x = xL; x < xR; x++) { 
2148                     if (z < zBuffer[x][y]) { 
2149                         TargetPixel[x + offset] = 
2150                         getColor(color, 
2151                                  getIntensity( 
2152                                          nx / 
2153                                          256, 
2154                                          ny / 
2155                                          256)); 
2156                         zBuffer[x][y] = z; 
2157                     } 
2158                     z += dz; 
2159                     nx += dnx; 
2160                     ny += dny; 
2161                 } 
2162             } 
2163         } 
2164     } 
2165  
2166     private void drawEnvmappedLine(int y, 
2167                                    int color) { 
2168         if ((y >= 0) && (y < h)) { 
2169             int xL = LEdgeBuffer[y]; 
2170             int xR = REdgeBuffer[y]; 
2171             int zL = ZEdgeBufferL[y]; 
2172             int zR = ZEdgeBufferR[y]; 
2173             int nxL = NXEdgeBufferL[y]; 
2174             int nxR = NXEdgeBufferR[y]; 
2175             int nyL = NYEdgeBufferL[y]; 
2176             int nyR = NYEdgeBufferR[y]; 
2177             if ((xL != xR)) { 
2178                 if (xL > xR) { 
2179                     int temp; 
2180                     temp = xL; 
2181                     xL = xR; 
2182                     xR = temp; 
2183                     temp = zL; 
2184                     zL = zR; 
2185                     zR = temp; 
2186                     temp = nxL; 
2187                     nxL = nxR; 
2188                     nxR = temp; 
2189                     temp = nyL; 
2190                     nyL = nyR; 
2191                     nyR = temp; 
2192                 } 
2193                 int dx = (xR - xL); 
2194                 int dz = (zR - zL) / dx; 
2195                 int dnx = (nxR - nxL) / dx; 
2196                 int dny = (nyR - nyL) / dx; 
2197                 int z = zL; 
2198                 int nx = nxL; 
2199                 int ny = nyL; 
2200  
2201                 xL = crop(xL, 0, w); 
2202                 xR = crop(xR, 0, w); 
2203  
2204                 int offset = y * w; 
2205  
2206                 for (int x = xL; x < xR; x++) { 
2207                     if (z < zBuffer[x][y]) { 
2208                         TargetPixel[x + offset] = 
2209                         getColor(color, 
2210                                  getEnvironment( 
2211                                          nx / 
2212                                          256, 
2213                                          ny / 
2214                                          256)); 
2215                         zBuffer[x][y] = z; 
2216                     } 
2217                     z += dz; 
2218                     nx += dnx; 
2219                     ny += dny; 
2220                 } 
2221             } 
2222         } 
2223     } 
2224  
2225     private void drawGouraudTextureLine(int y, 
2226                                         int t) { 
2227         if ((y >= 0) && (y < h)) { 
2228             int xL = LEdgeBuffer[y]; 
2229             int xR = REdgeBuffer[y]; 
2230             int zL = ZEdgeBufferL[y]; 
2231             int zR = ZEdgeBufferR[y]; 
2232             int iL = IEdgeBufferL[y]; 
2233             int iR = IEdgeBufferR[y]; 
2234             int txL = TXEdgeBufferL[y]; 
2235             int txR = TXEdgeBufferR[y]; 
2236             int tyL = TYEdgeBufferL[y]; 
2237             int tyR = TYEdgeBufferR[y]; 
2238             if ((xL != xR)) { 
2239                 if (xL > xR) { 
2240                     int temp; 
2241                     temp = xL; 
2242                     xL = xR; 
2243                     xR = temp; 
2244                     temp = zL; 
2245                     zL = zR; 
2246                     zR = temp; 
2247                     temp = iL; 
2248                     iL = iR; 
2249                     iR = temp; 
2250                     temp = txL; 
2251                     txL = txR; 
2252                     txR = temp; 
2253                     temp = tyL; 
2254                     tyL = tyR; 
2255                     tyR = temp; 
2256                 } 
2257                 int dx = (xR - xL); 
2258                 int dz = (zR - zL) / dx; 
2259                 int di = (iR - iL) / dx; 
2260                 int dtx = (txR - txL) / dx; 
2261                 int dty = (tyR - tyL) / dx; 
2262                 int z = zL; 
2263                 int i = iL; 
2264                 int tx = txL; 
2265                 int ty = tyL; 
2266  
2267                 xL = crop(xL, 0, w); 
2268                 xR = crop(xR, 0, w); 
2269  
2270                 int offset = y * w; 
2271  
2272                 for (int x = xL; x < xR; x++) { 
2273                     if (z < zBuffer[x][y]) { 
2274                         tx = (int) Math.abs(tx); 
2275                         ty = (int) Math.abs(ty); 
2276                         TargetPixel[x + offset] = 
2277                         getColor( 
2278                                 texture[t].pixel[(tx >> 
2279                                                   16) % 
2280                                                  texture[t].w][(ty >> 
2281                                                                 16) % 
2282                                                                texture[t].h], 
2283                                 i >> 8); 
2284                         zBuffer[x][y] = z; 
2285                     } 
2286                     z += dz; 
2287                     i += di; 
2288                     tx += dtx; 
2289                     ty += dty; 
2290                 } 
2291             } 
2292         } 
2293     } 
2294  
2295     private void drawPhongTextureLine(int y, 
2296                                       int t) { 
2297         if ((y >= 0) && (y < h)) { 
2298             int xL = LEdgeBuffer[y]; 
2299             int xR = REdgeBuffer[y]; 
2300             int zL = ZEdgeBufferL[y]; 
2301             int zR = ZEdgeBufferR[y]; 
2302             int nxL = NXEdgeBufferL[y]; 
2303             int nxR = NXEdgeBufferR[y]; 
2304             int nyL = NYEdgeBufferL[y]; 
2305             int nyR = NYEdgeBufferR[y]; 
2306             int txL = TXEdgeBufferL[y]; 
2307             int txR = TXEdgeBufferR[y]; 
2308             int tyL = TYEdgeBufferL[y]; 
2309             int tyR = TYEdgeBufferR[y]; 
2310             if ((xL != xR)) { 
2311                 if (xL > xR) { 
2312                     int temp; 
2313                     temp = xL; 
2314                     xL = xR; 
2315                     xR = temp; 
2316                     temp = zL; 
2317                     zL = zR; 
2318                     zR = temp; 
2319                     temp = nxL; 
2320                     nxL = nxR; 
2321                     nxR = temp; 
2322                     temp = nyL; 
2323                     nyL = nyR; 
2324                     nyR = temp; 
2325                     temp = txL; 
2326                     txL = txR; 
2327                     txR = temp; 
2328                     temp = tyL; 
2329                     tyL = tyR; 
2330                     tyR = temp; 
2331                 } 
2332                 int dx = (xR - xL); 
2333                 int dz = (zR - zL) / dx; 
2334                 int dtx = (txR - txL) / dx; 
2335                 int dty = (tyR - tyL) / dx; 
2336                 int dnx = (nxR - nxL) / dx; 
2337                 int dny = (nyR - nyL) / dx; 
2338                 int z = zL; 
2339                 int nx = nxL; 
2340                 int ny = nyL; 
2341                 int tx = txL; 
2342                 int ty = tyL; 
2343  
2344                 xL = crop(xL, 0, w); 
2345                 xR = crop(xR, 0, w); 
2346  
2347                 int offset = y * w; 
2348  
2349                 for (int x = xL; x < xR; x++) { 
2350                     if (z < zBuffer[x][y]) { 
2351                         tx = (int) Math.abs(tx); 
2352                         ty = (int) Math.abs(ty); 
2353                         TargetPixel[x + offset] = 
2354                         getColor( 
2355                                 texture[t].pixel[(tx >> 
2356                                                   16) % 
2357                                                  texture[t].w][(ty >> 
2358                                                                 16) % 
2359                                                                texture[t].h], 
2360                                 getIntensity( 
2361                                         nx / 256, 
2362                                         ny / 256)); 
2363                         zBuffer[x][y] = z; 
2364                     } 
2365                     z += dz; 
2366                     nx += dnx; 
2367                     ny += dny; 
2368                     tx += dtx; 
2369                     ty += dty; 
2370                 } 
2371             } 
2372         } 
2373     } 
2374  
2375     private void drawEnvmappedTextureLine(int y, 
2376                                           int t) { 
2377         if ((y >= 0) && (y < h)) { 
2378             int xL = LEdgeBuffer[y]; 
2379             int xR = REdgeBuffer[y]; 
2380             int zL = ZEdgeBufferL[y]; 
2381             int zR = ZEdgeBufferR[y]; 
2382             int nxL = NXEdgeBufferL[y]; 
2383             int nxR = NXEdgeBufferR[y]; 
2384             int nyL = NYEdgeBufferL[y]; 
2385             int nyR = NYEdgeBufferR[y]; 
2386             int txL = TXEdgeBufferL[y]; 
2387             int txR = TXEdgeBufferR[y]; 
2388             int tyL = TYEdgeBufferL[y]; 
2389             int tyR = TYEdgeBufferR[y]; 
2390             if ((xL != xR)) { 
2391                 if (xL > xR) { 
2392                     int temp; 
2393                     temp = xL; 
2394                     xL = xR; 
2395                     xR = temp; 
2396                     temp = zL; 
2397                     zL = zR; 
2398                     zR = temp; 
2399                     temp = nxL; 
2400                     nxL = nxR; 
2401                     nxR = temp; 
2402                     temp = nyL; 
2403                     nyL = nyR; 
2404                     nyR = temp; 
2405                     temp = txL; 
2406                     txL = txR; 
2407                     txR = temp; 
2408                     temp = tyL; 
2409                     tyL = tyR; 
2410                     tyR = temp; 
2411                 } 
2412                 int dx = (xR - xL); 
2413                 int dz = (zR - zL) / dx; 
2414                 int dtx = (txR - txL) / dx; 
2415                 int dty = (tyR - tyL) / dx; 
2416                 int dnx = (nxR - nxL) / dx; 
2417                 int dny = (nyR - nyL) / dx; 
2418                 int z = zL; 
2419                 int nx = nxL; 
2420                 int ny = nyL; 
2421                 int tx = txL; 
2422                 int ty = tyL; 
2423  
2424                 xL = crop(xL, 0, w); 
2425                 xR = crop(xR, 0, w); 
2426  
2427                 int offset = y * w; 
2428  
2429                 for (int x = xL; x < xR; x++) { 
2430                     if (z < zBuffer[x][y]) { 
2431                         tx = (int) Math.abs(tx); 
2432                         ty = (int) Math.abs(ty); 
2433                         TargetPixel[x + offset] = 
2434                         getColor( 
2435                                 texture[t].pixel[(tx >> 
2436                                                   16) % 
2437                                                  texture[t].w][(ty >> 
2438                                                                 16) % 
2439                                                                texture[t].h], 
2440                                 getEnvironment( 
2441                                         nx / 256, 
2442                                         ny / 256)); 
2443                         zBuffer[x][y] = z; 
2444                     } 
2445                     z += dz; 
2446                     nx += dnx; 
2447                     ny += dny; 
2448                     tx += dtx; 
2449                     ty += dty; 
2450                 } 
2451             } 
2452         } 
2453     } 
2454  
2455     // SPECIAL FUNCTIONS TO CREATE OBJECTS 
2456  
2457     public void generateField(float data[][], 
2458                               int xmax, 
2459                               int ymax, 
2460                               int rm, 
2461                               int c) { 
2462         float xtemp; 
2463         float ytemp; 
2464         float ztemp; 
2465         int q1; 
2466         int q2; 
2467         int q3; 
2468         int q4; 
2469         idx3d_node v; 
2470         addObject(rm, c); 
2471         rotateObject(objects, (float) 90, 0, 0); 
2472         float xscale = 2 / (float) (xmax - 1); 
2473         float yscale = 2 / (float) (ymax - 1); 
2474         for (int i = 0; i < xmax; i++) { 
2475             for (int j = 0; j < ymax; j++) { 
2476                 xtemp = -1 + xscale * (float) i; 
2477                 ytemp = -1 + yscale * (float) j; 
2478                 ztemp = data[i][j]; 
2479                 v = 
2480                 new idx3d_node(xtemp, 
2481                                ytemp, 
2482                                ztemp); 
2483                 if ((j > 0) && (i > 0)) { 
2484                     v.n.x = (data[i - 1][j] - 
2485                              data[i][j]) / 
2486                             xscale; 
2487                     v.n.y = (data[i][j - 1] - 
2488                              data[i][j]) / 
2489                             yscale; 
2490                     v.n.z = (float) 1; 
2491                 } 
2492                 v.n.z = (float) 1; 
2493                 v.tx = (float) i / 
2494                        (float) (xmax - 1); 
2495                 v.ty = (float) j / 
2496                        (float) (ymax - 1); 
2497                 addNode(objects, v); 
2498             } 
2499         } 
2500         for (int i = 0; i < (xmax - 1); i++) { 
2501             for (int j = 0; j < (ymax - 1); j++) { 
2502                 q1 = j + xmax * i + 1; 
2503                 q2 = j + 1 + xmax * i + 1; 
2504                 q3 = j + xmax * (i + 1) + 1; 
2505                 q4 = j + 1 + xmax * (i + 1) + 1; 
2506  
2507                 addTriangle(objects, q1, q2, q3); 
2508                 addTriangle(objects, q3, q2, q4); 
2509             } 
2510         } 
2511     } 
2512  
2513     public void generateScanObject(int obj, 
2514                                    int rows, 
2515                                    int cols) { 
2516  
2517         int k; 
2518         int sw = 0; 
2519  
2520  
2521         float tmpx, tmpz, dx, dy; 
2522  
2523         //normalize the whole thing 
2524         for (int j = 0; j < cols; j++) 
2525             for (int i = 1; i < rows; i++) { 
2526                 k = j * rows + i; 
2527                 tmpx = object[obj].node[k].v.x; 
2528                 tmpz = object[obj].node[k].v.z; 
2529                 if (i == 1) 
2530                     object[obj].node[k].n = 
2531                     normalize( 
2532                             new idx3d_vector( 
2533                                     tmpx, 
2534                                     1, 
2535                                     tmpz)); 
2536                 else if (i == rows - 1) 
2537                     object[obj].node[k].n = 
2538                     normalize( 
2539                             new idx3d_vector( 
2540                                     tmpx, 
2541                                     -1, 
2542                                     tmpz)); 
2543                 else { 
2544                     dx = 
2545                     object[obj].node[k - 1].v.x - 
2546                     object[obj].node[k + 1].v.x; 
2547                     dy = 
2548                     object[obj].node[k - 1].v.y - 
2549                     object[obj].node[k + 1].v.y; 
2550                     object[obj].node[k].n = 
2551                     normalize( 
2552                             new idx3d_vector( 
2553                                     tmpx, 
2554                                     dx / dy, 
2555                                     tmpz)); 
2556                 } 
2557                 object[obj].node[k].tx = 
2558                 (float) (j) / 
2559                 (float) (cols - 1); 
2560                 object[obj].node[k].ty = 
2561                 (float) (i - 1) / 
2562                 (float) (rows - 1); 
2563             } 
2564  
2565         // Create triangles 
2566  
2567         for (int col = 0; col < cols; col++) { 
2568             for (int row = 1; row < rows; row++) { 
2569                 //don't add triangles if the x or z of it are 0, thus solving the holes 
2570                 sw = 0; 
2571                 k = col * rows + row; 
2572                 tmpx = object[obj].node[k].v.x; 
2573                 tmpz = object[obj].node[k].v.z; 
2574                 if ((tmpx == 0) || (tmpz == 0)) sw = 
2575                                                 1; 
2576                 k = (col + 1) * rows + row; 
2577                 tmpx = object[obj].node[k].v.x; 
2578                 tmpz = object[obj].node[k].v.z; 
2579                 if ((tmpx == 0) || (tmpz == 0)) sw = 
2580                                                 1; 
2581                 k = col * rows + row + 1; 
2582                 tmpx = object[obj].node[k].v.x; 
2583                 tmpz = object[obj].node[k].v.z; 
2584                 if ((tmpx == 0) || (tmpz == 0)) sw = 
2585                                                 1; 
2586 //                  sw=0; 
2587                 if (sw == 0) { 
2588                     addTriangle(obj, 
2589                                 (rows * col + 
2590                                  row), 
2591                                 (rows * 
2592                                  (col + 1) + 
2593                                  row), 
2594                                 (rows * col + 
2595                                  row + 
2596                                  1)); 
2597                     addTriangle(obj, 
2598                                 (rows * col + 
2599                                  row + 
2600                                  1), 
2601                                 (rows * 
2602                                  (col + 1) + 
2603                                  row), 
2604                                 (rows * 
2605                                  (col + 1) + 
2606                                  row + 
2607                                  1)); 
2608                 } 
2609             } 
2610         } 
2611     } 
2612  
2613     public void generateScanObject1(int obj, 
2614                                     int rows, 
2615                                     int cols) { 
2616         int k; 
2617         float tmpx, tmpz, dx, dy; 
2618  
2619         //normalize the whole thing 
2620         for (int j = 0; j < cols; j++) 
2621             for (int i = 1; i < rows; i++) { 
2622                 k = j * rows + i; 
2623                 tmpx = object[obj].node[k].v.x; 
2624                 tmpz = object[obj].node[k].v.z; 
2625                 if (i == 1) 
2626                     object[obj].node[k].n = 
2627                     normalize( 
2628                             new idx3d_vector( 
2629                                     tmpx, 
2630                                     1, 
2631                                     tmpz)); 
2632                 else if (i == rows - 1) 
2633                     object[obj].node[k].n = 
2634                     normalize( 
2635                             new idx3d_vector( 
2636                                     tmpx, 
2637                                     -1, 
2638                                     tmpz)); 
2639                 else { 
2640                     dx = 
2641                     object[obj].node[k - 1].v.x - 
2642                     object[obj].node[k + 1].v.x; 
2643                     dy = 
2644                     object[obj].node[k - 1].v.y - 
2645                     object[obj].node[k + 1].v.y; 
2646                     object[obj].node[k].n = 
2647                     normalize( 
2648                             new idx3d_vector( 
2649                                     tmpx, 
2650                                     dx / dy, 
2651                                     tmpz)); 
2652                 } 
2653                 object[obj].node[k].tx = 
2654                 (float) (j) / 
2655                 (float) (cols - 1); 
2656                 object[obj].node[k].ty = 
2657                 (float) (i - 1) / 
2658                 (float) (rows - 1); 
2659             } 
2660  
2661         // Create triangles 
2662  
2663         for (int col = 0; col < cols; col++) { 
2664             for (int row = 1; row < rows; row++) { 
2665                 addTriangle(obj, 
2666                             (rows * col + row), 
2667                             (rows * (col + 1) + 
2668                              row), 
2669                             (rows * col + row + 
2670                              1)); 
2671                 addTriangle(obj, 
2672                             (rows * col + row + 
2673                              1), 
2674                             (rows * (col + 1) + 
2675                              row), 
2676                             (rows * (col + 1) + 
2677                              row + 
2678                              1)); 
2679             } 
2680         } 
2681     } 
2682  
2683     public void generateRotationObject(int obj, 
2684                                        int steps) { 
2685         double alpha = 2 * pi / ((double) steps); 
2686  
2687         int start = 1; 
2688         int end = object[obj].nodes + 1; 
2689         int t_nodes = object[obj].nodes; 
2690  
2691         //Adjust normals of existing points 
2692         object[obj].node[1].n = 
2693         normalize( 
2694                 new idx3d_vector( 
2695                         object[obj].node[1].v.x, 
2696                         (float) 1, 
2697                         object[obj].node[1].v.z)); 
2698         object[obj].node[t_nodes].n = 
2699         normalize( 
2700                 new idx3d_vector( 
2701                         object[obj].node[t_nodes].v.x, 
2702                         (float) -1, 
2703                         object[obj].node[t_nodes].v.z)); 
2704         for (int i = 2; i < t_nodes; i++) { 
2705             object[obj].node[i].n = 
2706             normalize( 
2707                     new idx3d_vector( 
2708                             object[obj].node[i].v.x, 
2709                             (object[obj].node[i - 
2710                                               1].v.x - 
2711                              object[obj].node[i + 
2712                                               1].v.x) / 
2713                             (object[obj].node[i - 
2714                                               1].v.y - 
2715                              object[obj].node[i + 
2716                                               1].v.y), 
2717                             object[obj].node[i].v.z)); 
2718             object[obj].node[i].tx = 0; 
2719             object[obj].node[i].ty = 
2720             (float) (i - 1) / 
2721             (float) (t_nodes - 1); 
2722         } 
2723  
2724         //Create new nodes 
2725  
2726         for (int j = 1; j < (steps + 1); j++) { 
2727             for (int i = start; i < end; i++) { 
2728                 float qx = (float) (object[obj].node[i].v.x * 
2729                                     Math.cos( 
2730                                             j * 
2731                                             alpha) + 
2732                                     object[obj].node[i].v.z * 
2733                                     Math.sin( 
2734                                             j * 
2735                                             alpha)); 
2736                 float qz = (float) (object[obj].node[i].v.z * 
2737                                     Math.cos( 
2738                                             j * 
2739                                             alpha) - 
2740                                     object[obj].node[i].v.x * 
2741                                     Math.sin( 
2742                                             j * 
2743                                             alpha)); 
2744                 idx3d_node w = new idx3d_node(qx, 
2745                                               object[obj].node[i].v.y, 
2746                                               qz); 
2747                 if (i == start) 
2748                     w.n = 
2749                     normalize( 
2750                             new idx3d_vector(qx, 
2751                                              1, 
2752                                              qz)); 
2753                 else if (i == end - 1) 
2754                     w.n = 
2755                     normalize( 
2756                             new idx3d_vector(qx, 
2757                                              -1, 
2758                                              qz)); 
2759                 else 
2760                     w.n = 
2761                     normalize( 
2762                             new idx3d_vector(qx, 
2763                                              (object[obj].node[i - 
2764                                                                1].v.x - 
2765                                               object[obj].node[i + 
2766                                                                1].v.x) / 
2767                                              (object[obj].node[i - 
2768                                                                1].v.y - 
2769                                               object[obj].node[i + 
2770                                                                1].v.y), 
2771                                              qz)); 
2772                 w.ty = (float) (i - 1) / 
2773                        (float) (t_nodes - 1); 
2774                 w.tx = (float) (j - 1) / 
2775                        (float) (steps - 1); 
2776                 addNode(obj, w); 
2777             } 
2778         } 
2779  
2780         // Create triangles 
2781         for (int col = 0; col < steps; col++) { 
2782             for (int row = 1; row < t_nodes; row++) { 
2783                 addTriangle(obj, 
2784                             (t_nodes * col + row), 
2785                             (t_nodes * (col + 1) + 
2786                              row), 
2787                             (t_nodes * col + row + 
2788                              1)); 
2789                 addTriangle(obj, 
2790                             (t_nodes * col + row + 
2791                              1), 
2792                             (t_nodes * (col + 1) + 
2793                              row), 
2794                             (t_nodes * (col + 1) + 
2795                              row + 
2796                              1)); 
2797             } 
2798         } 
2799     } 
2800  
2801     // BEMCHMARK 
2802  
2803     public String getFPS(int frames) { 
2804         long idx_time1; 
2805         long idx_time2; 
2806         double fps; 
2807  
2808  
2809         idx_time1 = new Date().getTime(); 
2810  
2811         for (int i = 0; i < frames; i++) { 
2812             rotateWorld((float) Math.random(), 
2813                         (float) Math.random(), 
2814                         (float) Math.random()); 
2815              renderScene(); 
2816         } 
2817  
2818         idx_time2 = new Date().getTime(); 
2819  
2820         fps = 
2821         (double) frames / 
2822         ((double) (idx_time2 - idx_time1) / 1000); 
2823         fps = (double) ((int) (fps * 100)) / 100; 
2824         return new String( 
2825                 "Benchmark: " + fps + " FPS"); 
2826     } 
2827 } 
2828  
2829  
2830 class idx3d_matrix { 
2831     float matrix[][] = new float[4][4]; 
2832  
2833     public idx3d_matrix() { 
2834         matrix[0][0] = (float) 1; 
2835         matrix[1][1] = (float) 1; 
2836         matrix[2][2] = (float) 1; 
2837         matrix[3][3] = (float) 1; 
2838     } 
2839 } 
2840  
2841 class idx3d_object { 
2842     int mode = 1; 
2843     int color; 
2844  
2845     idx3d_triangle triangle[]; 
2846     idx3d_node node[]; 
2847  
2848     int triangles = 0; 
2849     int maxtriangles = 0; 
2850     int nodes = 0; 
2851     int maxnodes = 0; 
2852     int texture; 
2853     idx3d_matrix matrix = new idx3d_matrix(); 
2854     idx3d_matrix matrix2 = new idx3d_matrix(); 
2855  
2856     public idx3d_object(int rm, int col) { 
2857         mode = rm; 
2858         color = col; 
2859     } 
2860 } 
2861  
2862 class idx3d_node { 
2863     idx3d_vector v = new idx3d_vector(); 
2864     idx3d_vector n = new idx3d_vector(); 
2865     idx3d_vector n2 = new idx3d_vector(); 
2866     int xx;   //Coordinates of the 
2867     int yy;   // screen projection 
2868     int zz;   //distance for z-buffer 
2869     float tx;    // Horizontal texture position (0..1+) 
2870     float ty;    // Vertical texture position   (0..1+) 
2871  
2872     public idx3d_node(float x, float y, float z) { 
2873         v.x = x; 
2874         v.y = y; 
2875         v.z = z; 
2876         n.x = (float) 0; 
2877         n.y = (float) 0; 
2878         n.z = (float) 1; 
2879     } 
2880 } 
2881  
2882 class idx3d_triangle { 
2883     int p1; 
2884     int p2; 
2885     int p3; 
2886     idx3d_vector n = new idx3d_vector(); 
2887  
2888     public idx3d_triangle(int q1, 
2889                           int q2, 
2890                           int q3) { 
2891         p1 = q1; 
2892         p2 = q2; 
2893         p3 = q3; 
2894     } 
2895 } 
2896  
2897 class idx3d_light { 
2898     int x; 
2899     int y; 
2900     int z; 
2901     int mode = 0;              //0=parallel light, 1=point light 
2902     int intensity = 255; 
2903  
2904     public idx3d_light(idx3d_vector lvect, 
2905                        int lmode, 
2906                        int lintensity) { 
2907         x = (int) (lvect.x * 255); 
2908         y = (int) (lvect.y * 255); 
2909         z = (int) (lvect.z * 255); 
2910         mode = lmode; 
2911         intensity = lintensity; 
2912     } 
2913 } 
2914  
2915 class idx3d_texture { 
2916     int w; 
2917     int h; 
2918     int pixel[][]; 
2919 } 
2920