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