/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