package graphics.idx;
import java.applet.Applet;
import java.awt.*;
import java.awt.image.ColorModel;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import java.util.Date;
class idx3d extends Applet {
public String info = new String("idx3d Java 3d ENGINE");
public String copyright = new String("©1998 by Peter Walser");
public String version = new String("Version 2.0 BETA");
public String build = new String("06.10.1998");
public String sysinfo;
int w;
int h;
float centerx;
float centery;
public idx3d_object object[];
public idx3d_light light[];
public idx3d_texture texture[];
public int objects = 0;
public int lights = 0;
public int textures = 0;
public int maxobjects = 0;
public int maxlights = 0;
public int maxtextures = 0;
private idx3d_matrix worldmatrix = new idx3d_matrix();
public int bgcolor;
int alpha = 0xff000000;
int rbit = 0x00ff0000;
int gbit = 0x0000ff00;
int bbit = 0x000000ff;
private ColorModel idx_cm = ColorModel.getRGBdefault();
float sinus[] = new float[360];
float cosinus[] = new float[360];
final float pi = (float) 3.14159265;
final float deg2rad = pi / 180;
public float perspective = (float) 8;
public float zoomcorrection = (float) 0.72;
public int ambient = 0; public int phong = 80; public int reflectivity = 255; public boolean staticLight = false;
int LightMap[][] = new int[256][256];
int ColorMap[][] = new int[256][256];
int EnvMap[][] = new int[256][256];
int StaticLightMap[][] = new int[256][256];
int StaticEnvMap[][] = new int[256][256];
int zBuffer[][];
int LEdgeBuffer[];
int REdgeBuffer[];
int ZEdgeBufferL[];
int ZEdgeBufferR[];
int IEdgeBufferL[];
int IEdgeBufferR[];
int NXEdgeBufferL[];
int NYEdgeBufferL[];
int NXEdgeBufferR[];
int NYEdgeBufferR[];
int TXEdgeBufferL[];
int TYEdgeBufferL[];
int TXEdgeBufferR[];
int TYEdgeBufferR[];
int zInfinite = 1000 << 16;
int zNear = -1 << 16;
Image DoubleBuffer = null;
int TargetPixel[];
int Background[];
public idx3d(int width, int height) {
myResize(width, height);
}
public void myResize(int width, int height) {
w = width;
h = height;
centerx = (float) w / 2;
centery = (float) h / 2;
sysinfo = getSysInfo();
TargetPixel = new int[w * h];
Background = new int[w * h];
LEdgeBuffer = new int[h];
REdgeBuffer = new int[h];
zBuffer = new int[w][h];
ZEdgeBufferL = new int[h];
ZEdgeBufferR = new int[h];
IEdgeBufferL = new int[h];
IEdgeBufferR = new int[h];
NXEdgeBufferL = new int[h];
NYEdgeBufferL = new int[h];
NXEdgeBufferR = new int[h];
NYEdgeBufferR = new int[h];
TXEdgeBufferL = new int[h];
TYEdgeBufferL = new int[h];
TXEdgeBufferR = new int[h];
TYEdgeBufferR = new int[h];
bgcolor = getIntColor(0, 0, 0);
clearBackground();
init_LightMap();
init_ColorMap();
init_TrigTables();
}
private String getSysInfo() {
return (System.getProperty("os.arch") + " on " + System.getProperty("os.name"));
}
private void init_LightMap() {
float NX;
float NY;
float NZ;
for (int j = 0; j < 256; j++) {
for (int i = 0; i < 256; i++) {
NX = ((float) i - 127) / 127;
NY = ((float) j - 127) / 127;
NZ = (float) (1 - Math.sqrt(NX * NX + NY * NY));
LightMap[i][j] = crop((int) (NZ * 255), 0, 255);
}
}
}
public void setStatic() {
for (int j = 0; j < 256; j++) {
for (int i = 0; i < 256; i++) {
StaticLightMap[i][j] = getIntensity(2 * i - 255, 2 * j - 255);
StaticEnvMap[i][j] = getEnvironment(2 * i - 255, 2 * j - 255);
}
}
staticLight = true;
}
private void init_ColorMap() {
int H2 = 255 - phong;
for (int x = 0; x < 256; x++) {
for (int y = 0; y < H2; y++) {
ColorMap[y][x] = (x * y / H2);
}
for (int y = H2; y < 256; y++) {
ColorMap[y][x] = (y + (255 - y) * (x - H2) / phong);
}
}
}
private void init_TrigTables() {
for (int i = 0; i < 360; i++) {
sinus[i] = (float) Math.sin(deg2rad * (float) i);
cosinus[i] = (float) Math.cos(deg2rad * (float) i);
}
}
public void setPhong(int p) {
phong = p;
init_ColorMap();
}
public float crop(float a, float b, float c) {
if (a < b) return (b);
if (a > c - 1) return (c - 1);
return a;
}
public int crop(int a, int b, int c) {
if (a < b) return (b);
if (a > c - 1) return (c - 1);
return a;
}
public boolean inrange(int a, int b, int c) {
return ((a >= b) && (a < c));
}
public boolean inrange(float a, float b, float c) {
return ((a >= b) && (a < c));
}
public float rnd() {
return ((float) Math.random() * 2 - 1);
}
public idx3d_node rndNode() {
idx3d_vector v = new idx3d_vector();
v = rndVector();
idx3d_node r = new idx3d_node(v.x, v.y, v.z);
r.n = normalize(rndVector());
return r;
}
public idx3d_vector rndVector() {
idx3d_vector v = new idx3d_vector();
v.x = rnd();
v.y = rnd();
v.z = rnd();
return v;
}
public int rndColor() {
int r = (int) (Math.random() * 255);
int g = (int) (Math.random() * 255);
int b = (int) (Math.random() * 255);
return getIntColor(r, g, b);
}
public idx3d_vector vectordist(idx3d_vector v1, idx3d_vector v2) {
return new idx3d_vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
}
public float vectorlength(idx3d_vector v) {
return (float) Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}
public idx3d_vector normalize(idx3d_vector v) {
float length = vectorlength(v);
return new idx3d_vector(v.x / length, v.y / length, v.z / length);
}
public idx3d_vector getNormal(idx3d_vector a, idx3d_vector b, idx3d_vector c) {
idx3d_vector n = new idx3d_vector();
float ax = b.x - a.x;
float ay = b.y - a.y;
float az = b.z - a.z;
float bx = c.x - a.x;
float by = c.y - a.y;
float bz = c.z - a.z;
n.x = ay * bz - by * az;
n.y = az * bx - bz * ax;
n.z = ax * by - bx * ay;
return normalize(n);
}
public idx3d_matrix crossproduct(idx3d_matrix a, idx3d_matrix b) {
idx3d_matrix c = new idx3d_matrix();
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];
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];
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];
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];
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];
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];
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];
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];
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];
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];
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];
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];
return c;
}
public idx3d_vector matrixvectorproduct(idx3d_matrix b, idx3d_vector a) {
idx3d_vector c = new idx3d_vector();
c.x = a.x * b.matrix[0][0] + a.y * b.matrix[0][1] + a.z * b.matrix[0][2] + b.matrix[0][3];
c.y = a.x * b.matrix[1][0] + a.y * b.matrix[1][1] + a.z * b.matrix[1][2] + b.matrix[1][3];
c.z = a.x * b.matrix[2][0] + a.y * b.matrix[2][1] + a.z * b.matrix[2][2] + b.matrix[2][3];
return c;
}
public void addObject(int rendermode, int color) {
objects += 1;
if (objects >= maxobjects) {
if (object == null) {
maxobjects = 2;
object = new idx3d_object[11];
} else {
maxobjects *= 2;
idx3d_object temp[] = new idx3d_object[maxobjects + 1];
System.arraycopy(object, 1, temp, 1, objects);
object = temp;
}
}
object[objects] = new idx3d_object(rendermode, color);
}
public void addLight(idx3d_vector v, int mode, int intensity) {
lights += 1;
if (lights >= maxlights) {
if (light == null) {
maxlights = 10;
light = new idx3d_light[11];
} else {
maxlights += 10;
idx3d_light temp[] = new idx3d_light[maxlights + 1];
System.arraycopy(light, 1, temp, 1, lights);
light = temp;
}
}
if (mode == 1) v = normalize(v);
light[lights] = new idx3d_light(v, mode, intensity);
}
public void addTexture(Image img) {
textures += 1;
if (textures >= maxtextures) {
if (texture == null) {
maxtextures = 20;
texture = new idx3d_texture[21];
} else {
maxtextures *= 2;
idx3d_texture temp[] = new idx3d_texture[maxtextures + 1];
System.arraycopy(texture, 1, temp, 1, textures);
texture = temp;
}
}
texture[textures] = new idx3d_texture();
while (img.getWidth(this) < 0 || img.getHeight(this) < 0) {
}
int width = img.getWidth(this);
int height = img.getHeight(this);
texture[textures].w = width;
texture[textures].h = height;
texture[textures].pixel = new int[width][height];
int temp2[] = new int[width * height];
PixelGrabber pg = new PixelGrabber(img, 0, 0, width, height, temp2, 0, width);
try {
pg.grabPixels();
} catch (InterruptedException e) {
}
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
texture[textures].pixel[i][j] = temp2[i + j * width];
}
}
}
public void addTriangle(int objectNr, int p1, int p2, int p3) {
object[objectNr].triangles += 1;
if (object[objectNr].triangles >= object[objectNr].maxtriangles) {
if (object[objectNr].triangle == null) {
object[objectNr].maxtriangles = 2;
object[objectNr].triangle = new idx3d_triangle[11];
} else {
object[objectNr].maxtriangles *= 2;
idx3d_triangle temp[] = new idx3d_triangle[object[objectNr].maxtriangles + 1];
System.arraycopy(object[objectNr].triangle, 1, temp, 1, object[objectNr].triangles);
object[objectNr].triangle = temp;
}
}
object[objectNr].triangle[object[objectNr].triangles] = new idx3d_triangle(p1, p2, p3);
object[objectNr].triangle[object[objectNr].triangles].n = getNormal(object[objectNr].node[p1].v, object[objectNr].node[p3].v, object[objectNr].node[p2].v);
}
public void addNode(int objectNr, idx3d_node t) {
object[objectNr].nodes += 1;
if (object[objectNr].nodes >= object[objectNr].maxnodes) {
if (object[objectNr].node == null) {
object[objectNr].maxnodes = 2;
object[objectNr].node = new idx3d_node[11];
} else {
object[objectNr].maxnodes *= 2;
idx3d_node temp[] = new idx3d_node[object[objectNr].maxnodes + 1];
System.arraycopy(object[objectNr].node, 1, temp, 1, object[objectNr].nodes);
object[objectNr].node = temp;
}
}
t.n = normalize(t.n);
object[objectNr].node[object[objectNr].nodes] = t;
}
public void addNode(int objectNr, float x, float y, float z) {
addNode(objectNr, new idx3d_node(x, y, z));
}
public idx3d_matrix shiftMatrix(float dx, float dy, float dz) {
idx3d_matrix m = new idx3d_matrix();
m.matrix[0][3] = dx;
m.matrix[1][3] = dy;
m.matrix[2][3] = dz;
return m;
}
public idx3d_matrix scaleMatrix(float dx, float dy, float dz) {
idx3d_matrix m = new idx3d_matrix();
m.matrix[0][0] = dx;
m.matrix[1][1] = dy;
m.matrix[2][2] = dz;
return m;
}
public idx3d_matrix rotateMatrix(float dx, float dy, float dz) {
float SIN;
float COS;
int angle;
idx3d_matrix out = new idx3d_matrix();
if (dx != 0) {
idx3d_matrix m = new idx3d_matrix();
angle = ((int) dx + 1440) % 360;
SIN = sinus[angle];
COS = cosinus[angle];
m.matrix[1][1] = COS;
m.matrix[1][2] = SIN;
m.matrix[2][1] = -SIN;
m.matrix[2][2] = COS;
out = crossproduct(m, out);
}
if (dy != 0) {
idx3d_matrix m = new idx3d_matrix();
angle = ((int) dy + 720) % 360;
SIN = sinus[angle];
COS = cosinus[angle];
m.matrix[0][0] = COS;
m.matrix[0][2] = SIN;
m.matrix[2][0] = -SIN;
m.matrix[2][2] = COS;
out = crossproduct(m, out);
}
if (dz != 0) {
idx3d_matrix m = new idx3d_matrix();
angle = ((int) dz + 720) % 360;
SIN = sinus[angle];
COS = cosinus[angle];
m.matrix[0][0] = COS;
m.matrix[0][1] = SIN;
m.matrix[1][0] = -SIN;
m.matrix[1][1] = COS;
out = crossproduct(m, out);
}
return out;
}
public void shiftObject(int o, float dx, float dy, float dz) {
object[o].matrix = crossproduct(shiftMatrix(dx, dy, dz), object[o].matrix);
}
public void scaleObject(int o, float dx, float dy, float dz) {
object[o].matrix = crossproduct(scaleMatrix(dx, dy, dz), object[o].matrix);
}
public void rotateObject(int o, float dx, float dy, float dz) {
object[o].matrix = crossproduct(object[o].matrix, rotateMatrix(dx, dy, dz));
}
public void rotateObjectWorld(int o, float dx, float dy, float dz) {
object[o].matrix = crossproduct(rotateMatrix(dx, dy, dz), object[o].matrix);
}
public void rotateObject(int obj, float px, float py, float pz, float dx, float dy, float dz) {
shiftObject(obj, -px, -py, -pz);
rotateObject(obj, dx, dy, dz);
shiftObject(obj, px, py, pz);
}
public void shiftWorld(float dx, float dy, float dz) {
worldmatrix = crossproduct(shiftMatrix(dx, dy, dz), worldmatrix);
}
public void scaleWorld(float dx, float dy, float dz) {
worldmatrix = crossproduct(scaleMatrix(dx, dy, dz), worldmatrix);
}
public void rotateWorld(float dx, float dy, float dz) {
worldmatrix = crossproduct(rotateMatrix(dx, dy, dz), worldmatrix);
}
public void scaleObject(int obj, float d) {
scaleObject(obj, d, d, d);
}
public void scaleWorld(float d) {
scaleWorld(d, d, d);
}
public Image renderScene() {
clearDoubleBuffer();
paintObjects();
paintImage();
return DoubleBuffer;
}
private void clearDoubleBuffer() {
for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++) {
zBuffer[i][j] = zInfinite;
}
}
for (int i = 0; i < w * h; i++) {
TargetPixel[i] = Background[i];
}
}
private void clearBackground() {
for (int i = 0; i < w * h; i++) {
Background[i] = bgcolor;
}
}
private void paintObjects() {
for (int i = 1; i <= objects; i++) {
object[i].matrix2 = crossproduct(worldmatrix, object[i].matrix);
for (int j = 1; j <= object[i].nodes; j++) {
object[i].node[j] = projectNode(i, object[i].node[j]);
}
for (int j = 1; j <= object[i].triangles; j++) {
if (object[i].mode == 1) drawWireframe(i, object[i].triangle[j]);
if (object[i].mode == 2) drawFlatshaded(i, object[i].triangle[j]);
if (object[i].mode == 3) drawGouraud(i, object[i].triangle[j]);
if (object[i].mode == 4) drawPhong(i, object[i].triangle[j]);
if (object[i].mode == 5) drawEnvmapped(i, object[i].triangle[j]);
if (object[i].mode == 6) drawGouraudTexture(i, object[i].triangle[j]);
if (object[i].mode == 7) drawPhongTexture(i, object[i].triangle[j]);
if (object[i].mode == 8) drawEnvmappedTexture(i, object[i].triangle[j]);
}
}
}
private void paintImage() {
DoubleBuffer = createImage(new MemoryImageSource(w, h, idx_cm, TargetPixel, 0, w));
}
private idx3d_node projectNode(int obj, idx3d_node q) {
idx3d_node w = q;
idx3d_vector mvect = matrixvectorproduct(object[obj].matrix2, w.v);
w.n2 = normalize(matrixvectorproduct(object[obj].matrix2, w.n));
float zoom = perspective / (perspective + mvect.z) * zoomcorrection;
w.xx = (int) (mvect.x * zoom * centerx + centerx);
w.yy = (int) (mvect.y * zoom * centery + centery);
w.zz = (int) (mvect.z * 65536);
return w;
}
private int getIntensity(int nx, int ny) {
if (staticLight) return StaticLightMap[nx / 2 + 127][ny / 2 + 127];
int nz = LightMap[nx / 2 + 127][ny / 2 + 127];
int intensity = ambient;
for (int i = 1; i <= lights; i++) {
if (light[i].mode == 1) {
intensity += crop((light[i].intensity * (int) Math.abs(nx * light[i].x + ny * light[i].y + nz * light[i].z) >> 8) >> 8, 0, 255);
}
if (light[i].mode == 2) {
}
}
return crop(intensity, 0, 255);
}
private int getIntensity(idx3d_vector v) {
return getIntensity((int) (v.x * 255), (int) (v.y * 255));
}
private int getEnvironment(int nx, int ny) {
if (staticLight) return StaticEnvMap[nx / 2 + 127][ny / 2 + 127];
int env = EnvMap[nx / 2 + 127][ny / 2 + 127];
return crop(ambient + getIntensity(nx, ny) * env * reflectivity / 65536, 0, 255);
}
public int getIntColor(int r, int g, int b) {
return alpha | (r << 16) | (g << 8) | b;
}
private int getColor(int c, int intensity) {
int r = ColorMap[intensity][(rbit & c) >> 16];
int g = ColorMap[intensity][(gbit & c) >> 8];
int b = ColorMap[intensity][(bbit & c)];
return getIntColor(r, g, b);
}
private int getGray(int c) {
return (((rbit & c) >> 16) + ((gbit & c) >> 8) + (bbit & c)) / 3;
}
public void setBackground(Image TempImage) {
PixelGrabber pg = new PixelGrabber(TempImage, 0, 0, w, h, Background, 0, w);
try {
pg.grabPixels();
} catch (InterruptedException e) {
}
}
public void setEnvironment(Image TempImage) {
int temp[] = new int[256 * 256];
PixelGrabber pg = new PixelGrabber(TempImage, 0, 0, 256, 256, temp, 0, 256);
try {
pg.grabPixels();
} catch (InterruptedException e) {
}
for (int i = 0; i < 256; i++) {
for (int j = 0; j < 256; j++) {
EnvMap[i][j] = getGray(temp[i + j * 256]);
}
}
}
private void drawLine(idx3d_node q1, idx3d_node q2, int color) {
idx3d_node temp;
int dx = (int) Math.abs(q1.xx - q2.xx);
int dy = (int) Math.abs(q1.yy - q2.yy);
int dz = 0;
int x,y,z;
int x2,y2;
if (dx > dy) {
if (q1.xx > q2.xx) {
temp = q1;
q1 = q2;
q2 = temp;
}
if (dx > 0) {
dz = (q2.zz - q1.zz) / dx;
dy = ((q2.yy - q1.yy) << 16) / dx;
}
z = q1.zz;
y = q1.yy << 16;
for (x = q1.xx; x <= q2.xx; x++) {
y2 = y >> 16;
if (inrange(x, 0, w) && inrange(y2, 0, h)) {
if (z < zBuffer[x][y2]) {
TargetPixel[x + y2 * w] = color;
zBuffer[x][y2] = z;
}
}
z += dz;
y += dy;
}
} else {
if (q1.yy > q2.yy) {
temp = q1;
q1 = q2;
q2 = temp;
}
if (dy > 0) {
dz = (q2.zz - q1.zz) / dy;
dx = ((q2.xx - q1.xx) << 16) / dy;
}
z = q1.zz;
x = q1.xx << 16;
for (y = q1.yy; y <= q2.yy; y++) {
x2 = x >> 16;
if (inrange(x2, 0, w) && inrange(y, 0, h)) {
if (z < zBuffer[x2][y]) {
TargetPixel[x2 + y * w] = color;
zBuffer[x2][y] = z;
}
}
z += dz;
x += dx;
}
}
}
private void drawWireframe(int obj, idx3d_triangle t) {
int temp;
idx3d_node temp1;
int c = object[obj].color;
idx3d_node p1 = object[obj].node[t.p1];
idx3d_node p2 = object[obj].node[t.p2];
idx3d_node p3 = object[obj].node[t.p3];
drawLine(p1, p2, c);
drawLine(p2, p3, c);
drawLine(p1, p3, c);
}
private void drawFlatshaded(int obj, idx3d_triangle t) {
idx3d_vector n = normalize(matrixvectorproduct(object[obj].matrix, t.n));
int temp;
idx3d_node temp1;
idx3d_node p1 = object[obj].node[t.p1];
idx3d_node p2 = object[obj].node[t.p2];
idx3d_node p3 = object[obj].node[t.p3];
if (p1.yy > p2.yy) {
temp1 = p1;
p1 = p2;
p2 = temp1;
}
if (p2.yy > p3.yy) {
temp1 = p2;
p2 = p3;
p3 = temp1;
}
if (p1.yy > p2.yy) {
temp1 = p1;
p1 = p2;
p2 = temp1;
}
int x1 = p1.xx << 16;
int x2 = p2.xx << 16;
int x3 = p3.xx << 16;
int y1 = p1.yy << 16;
int y2 = p2.yy << 16;
int y3 = p3.yy << 16;
int dx1 = 0;
int dx2 = 0;
int dx3 = 0;
int dz1 = 0;
int dz2 = 0;
int dz3 = 0;
int dy;
if (y2 != y1) {
dy = (y2 - y1) >> 16;
dx1 = (x2 - x1) / dy;
dz1 = (p2.zz - p1.zz) / dy;
}
if (y3 != y2) {
dy = (y3 - y2) >> 16;
dx2 = (x3 - x2) / dy;
dz2 = (p3.zz - p2.zz) / dy;
}
if (y3 != y1) {
dy = (y3 - y1) >> 16;
dx3 = (x3 - x1) / dy;
dz3 = (p3.zz - p1.zz) / dy;
}
int xL = x1;
int xR = x1;
int zL = p1.zz;
int zR = p1.zz;
y1 = y1 >> 16;
y2 = y2 >> 16;
y3 = y3 >> 16;
for (int k = y1; k < y2; k++) {
if ((k >= 0) && (k < h)) {
LEdgeBuffer[k] = xL >> 16;
REdgeBuffer[k] = xR >> 16;
ZEdgeBufferL[k] = zL;
ZEdgeBufferR[k] = zR;
}
xL += dx1;
xR += dx3;
zL += dz1;
zR += dz3;
}
xL = x2;
zL = p2.zz;
for (int k = y2; k <= y3; k++) {
if ((k >= 0) && (k < h)) {
LEdgeBuffer[k] = xL >> 16;
REdgeBuffer[k] = xR >> 16;
ZEdgeBufferL[k] = zL;
ZEdgeBufferR[k] = zR;
}
xL += dx2;
xR += dx3;
zL += dz2;
zR += dz3;
}
y1 = crop(y1, 0, h);
y3 = crop(y3, 0, h);
for (int j = y1; j <= y3; j++) drawFlatshadedLine(j, getColor(object[obj].color, getIntensity(n)));
}
private void drawGouraud(int obj, idx3d_triangle t) {
int temp;
idx3d_node temp1;
idx3d_node p1 = object[obj].node[t.p1];
idx3d_node p2 = object[obj].node[t.p2];
idx3d_node p3 = object[obj].node[t.p3];
if (p1.yy > p2.yy) {
temp1 = p1;
p1 = p2;
p2 = temp1;
}
if (p2.yy > p3.yy) {
temp1 = p2;
p2 = p3;
p3 = temp1;
}
if (p1.yy > p2.yy) {
temp1 = p1;
p1 = p2;
p2 = temp1;
}
int i1 = getIntensity(p1.n2) << 8;
int i2 = getIntensity(p2.n2) << 8;
int i3 = getIntensity(p3.n2) << 8;
int x1 = p1.xx << 16;
int x2 = p2.xx << 16;
int x3 = p3.xx << 16;
int y1 = p1.yy << 16;
int y2 = p2.yy << 16;
int y3 = p3.yy << 16;
int dx1 = 0;
int dx2 = 0;
int dx3 = 0;
int dz1 = 0;
int dz2 = 0;
int dz3 = 0;
int di1 = 0;
int di2 = 0;
int di3 = 0;
int dy;
if (y2 != y1) {
dy = (y2 - y1) >> 16;
dx1 = (x2 - x1) / dy;
dz1 = (p2.zz - p1.zz) / dy;
di1 = (i2 - i1) / dy;
}
if (y3 != y2) {
dy = (y3 - y2) >> 16;
dx2 = (x3 - x2) / dy;
dz2 = (p3.zz - p2.zz) / dy;
di2 = (i3 - i2) / dy;
}
if (y3 != y1) {
dy = (y3 - y1) >> 16;
dx3 = (x3 - x1) / dy;
dz3 = (p3.zz - p1.zz) / dy;
di3 = (i3 - i1) / dy;
}
int xL = x1;
int xR = x1;
int zL = p1.zz;
int zR = p1.zz;
int iL = i1;
int iR = i1;
y1 = y1 >> 16;
y2 = y2 >> 16;
y3 = y3 >> 16;
for (int k = y1; k < y2; k++) {
if ((k >= 0) && (k < h)) {
LEdgeBuffer[k] = xL >> 16;
REdgeBuffer[k] = xR >> 16;
ZEdgeBufferL[k] = zL;
ZEdgeBufferR[k] = zR;
IEdgeBufferL[k] = iL;
IEdgeBufferR[k] = iR;
}
xL += dx1;
xR += dx3;
zL += dz1;
zR += dz3;
iL += di1;
iR += di3;
}
xL = x2;
zL = p2.zz;
iL = i2;
for (int k = y2; k <= y3; k++) {
if ((k >= 0) && (k < h)) {
LEdgeBuffer[k] = xL >> 16;
REdgeBuffer[k] = xR >> 16;
ZEdgeBufferL[k] = zL;
ZEdgeBufferR[k] = zR;
IEdgeBufferL[k] = iL;
IEdgeBufferR[k] = iR;
}
xL += dx2;
xR += dx3;
zL += dz2;
zR += dz3;
iL += di2;
iR += di3;
}
y1 = crop(y1, 0, h);
y3 = crop(y3, 0, h);
for (int j = y1; j <= y3; j++) drawGouraudLine(j, object[obj].color);
}
private void drawPhong(int obj, idx3d_triangle t) {
int temp;
idx3d_node temp1;
idx3d_node p1 = object[obj].node[t.p1];
idx3d_node p2 = object[obj].node[t.p2];
idx3d_node p3 = object[obj].node[t.p3];
if (p1.yy > p2.yy) {
temp1 = p1;
p1 = p2;
p2 = temp1;
}
if (p2.yy > p3.yy) {
temp1 = p2;
p2 = p3;
p3 = temp1;
}
if (p1.yy > p2.yy) {
temp1 = p1;
p1 = p2;
p2 = temp1;
}
int x1 = p1.xx << 16;
int x2 = p2.xx << 16;
int x3 = p3.xx << 16;
int y1 = p1.yy << 16;
int y2 = p2.yy << 16;
int y3 = p3.yy << 16;
int nx1 = (int) (65536 * p1.n2.x);
int nx2 = (int) (65536 * p2.n2.x);
int nx3 = (int) (65536 * p3.n2.x);
int ny1 = (int) (65536 * p1.n2.y);
int ny2 = (int) (65536 * p2.n2.y);
int ny3 = (int) (65536 * p3.n2.y);
int dx1 = 0;
int dx2 = 0;
int dx3 = 0;
int dz1 = 0;
int dz2 = 0;
int dz3 = 0;
int dnx1 = 0;
int dnx2 = 0;
int dnx3 = 0;
int dny1 = 0;
int dny2 = 0;
int dny3 = 0;
int dy;
if (y2 != y1) {
dy = (y2 - y1) >> 16;
dx1 = (x2 - x1) / dy;
dz1 = (p2.zz - p1.zz) / dy;
dnx1 = (nx2 - nx1) / dy;
dny1 = (ny2 - ny1) / dy;
}
if (y3 != y2) {
dy = (y3 - y2) >> 16;
dx2 = (x3 - x2) / dy;
dz2 = (p3.zz - p2.zz) / dy;
dnx2 = (nx3 - nx2) / dy;
dny2 = (ny3 - ny2) / dy;
}
if (y3 != y1) {
dy = (y3 - y1) >> 16;
dx3 = (x3 - x1) / dy;
dz3 = (p3.zz - p1.zz) / dy;
dnx3 = (nx3 - nx1) / dy;
dny3 = (ny3 - ny1) / dy;
}
int xL = x1;
int xR = x1;
int zL = p1.zz;
int zR = p1.zz;
int nxL = nx1;
int nxR = nx1;
int nyL = ny1;
int nyR = ny1;
y1 = y1 >> 16;
y2 = y2 >> 16;
y3 = y3 >> 16;
for (int k = y1; k < y2; k++) {
if ((k >= 0) && (k < h)) {
LEdgeBuffer[k] = xL >> 16;
REdgeBuffer[k] = xR >> 16;
ZEdgeBufferL[k] = zL;
ZEdgeBufferR[k] = zR;
NXEdgeBufferL[k] = nxL;
NXEdgeBufferR[k] = nxR;
NYEdgeBufferL[k] = nyL;
NYEdgeBufferR[k] = nyR;
}
xL += dx1;
xR += dx3;
zL += dz1;
zR += dz3;
nxL += dnx1;
nxR += dnx3;
nyL += dny1;
nyR += dny3;
}
xL = x2;
zL = p2.zz;
nxL = nx2;
nyL = ny2;
for (int k = y2; k <= y3; k++) {
if ((k >= 0) && (k < h)) {
LEdgeBuffer[k] = xL >> 16;
REdgeBuffer[k] = xR >> 16;
ZEdgeBufferL[k] = zL;
ZEdgeBufferR[k] = zR;
NXEdgeBufferL[k] = nxL;
NXEdgeBufferR[k] = nxR;
NYEdgeBufferL[k] = nyL;
NYEdgeBufferR[k] = nyR;
}
xL += dx2;
xR += dx3;
zL += dz2;
zR += dz3;
nxL += dnx2;
nxR += dnx3;
nyL += dny2;
nyR += dny3;
}
y1 = crop(y1, 0, h);
y3 = crop(y3, 0, h);
for (int j = y1; j <= y3; j++) drawPhongLine(j, object[obj].color);
}
private void drawEnvmapped(int obj, idx3d_triangle t) {
int temp;
idx3d_node temp1;
idx3d_node p1 = object[obj].node[t.p1];
idx3d_node p2 = object[obj].node[t.p2];
idx3d_node p3 = object[obj].node[t.p3];
if (p1.yy > p2.yy) {
temp1 = p1;
p1 = p2;
p2 = temp1;
}
if (p2.yy > p3.yy) {
temp1 = p2;
p2 = p3;
p3 = temp1;
}
if (p1.yy > p2.yy) {
temp1 = p1;
p1 = p2;
p2 = temp1;
}
int x1 = p1.xx << 16;
int x2 = p2.xx << 16;
int x3 = p3.xx << 16;
int y1 = p1.yy << 16;
int y2 = p2.yy << 16;
int y3 = p3.yy << 16;
int nx1 = (int) (65536 * p1.n2.x);
int nx2 = (int) (65536 * p2.n2.x);
int nx3 = (int) (65536 * p3.n2.x);
int ny1 = (int) (65536 * p1.n2.y);
int ny2 = (int) (65536 * p2.n2.y);
int ny3 = (int) (65536 * p3.n2.y);
int dx1 = 0;
int dx2 = 0;
int dx3 = 0;
int dz1 = 0;
int dz2 = 0;
int dz3 = 0;
int dnx1 = 0;
int dnx2 = 0;
int dnx3 = 0;
int dny1 = 0;
int dny2 = 0;
int dny3 = 0;
int dy;
if (y2 != y1) {
dy = (y2 - y1) >> 16;
dx1 = (x2 - x1) / dy;
dz1 = (p2.zz - p1.zz) / dy;
dnx1 = (nx2 - nx1) / dy;
dny1 = (ny2 - ny1) / dy;
}
if (y3 != y2) {
dy = (y3 - y2) >> 16;
dx2 = (x3 - x2) / dy;
dz2 = (p3.zz - p2.zz) / dy;
dnx2 = (nx3 - nx2) / dy;
dny2 = (ny3 - ny2) / dy;
}
if (y3 != y1) {
dy = (y3 - y1) >> 16;
dx3 = (x3 - x1) / dy;
dz3 = (p3.zz - p1.zz) / dy;
dnx3 = (nx3 - nx1) / dy;
dny3 = (ny3 - ny1) / dy;
}
int xL = x1;
int xR = x1;
int zL = p1.zz;
int zR = p1.zz;
int nxL = nx1;
int nxR = nx1;
int nyL = ny1;
int nyR = ny1;
y1 = y1 >> 16;
y2 = y2 >> 16;
y3 = y3 >> 16;
for (int k = y1; k < y2; k++) {
if ((k >= 0) && (k < h)) {
LEdgeBuffer[k] = xL >> 16;
REdgeBuffer[k] = xR >> 16;
ZEdgeBufferL[k] = zL;
ZEdgeBufferR[k] = zR;
NXEdgeBufferL[k] = nxL;
NXEdgeBufferR[k] = nxR;
NYEdgeBufferL[k] = nyL;
NYEdgeBufferR[k] = nyR;
}
xL += dx1;
xR += dx3;
zL += dz1;
zR += dz3;
nxL += dnx1;
nxR += dnx3;
nyL += dny1;
nyR += dny3;
}
xL = x2;
zL = p2.zz;
nxL = nx2;
nyL = ny2;
for (int k = y2; k <= y3; k++) {
if ((k >= 0) && (k < h)) {
LEdgeBuffer[k] = xL >> 16;
REdgeBuffer[k] = xR >> 16;
ZEdgeBufferL[k] = zL;
ZEdgeBufferR[k] = zR;
NXEdgeBufferL[k] = nxL;
NXEdgeBufferR[k] = nxR;
NYEdgeBufferL[k] = nyL;
NYEdgeBufferR[k] = nyR;
}
xL += dx2;
xR += dx3;
zL += dz2;
zR += dz3;
nxL += dnx2;
nxR += dnx3;
nyL += dny2;
nyR += dny3;
}
y1 = crop(y1, 0, h);
y3 = crop(y3, 0, h);
for (int j = y1; j <= y3; j++) drawEnvmappedLine(j, object[obj].color);
}
private void drawGouraudTexture(int obj, idx3d_triangle t) {
int temp;
idx3d_node temp1;
idx3d_node p1 = object[obj].node[t.p1];
idx3d_node p2 = object[obj].node[t.p2];
idx3d_node p3 = object[obj].node[t.p3];
if (p1.yy > p2.yy) {
temp1 = p1;
p1 = p2;
p2 = temp1;
}
if (p2.yy > p3.yy) {
temp1 = p2;
p2 = p3;
p3 = temp1;
}
if (p1.yy > p2.yy) {
temp1 = p1;
p1 = p2;
p2 = temp1;
}
int i1 = getIntensity(p1.n2) << 8;
int i2 = getIntensity(p2.n2) << 8;
int i3 = getIntensity(p3.n2) << 8;
int x1 = p1.xx << 16;
int x2 = p2.xx << 16;
int x3 = p3.xx << 16;
int y1 = p1.yy << 16;
int y2 = p2.yy << 16;
int y3 = p3.yy << 16;
float tw = (float) texture[object[obj].texture].w * 65536;
float th = (float) texture[object[obj].texture].h * 65536;
int tx1 = (int) (tw * p1.tx);
int tx2 = (int) (tw * p2.tx);
int tx3 = (int) (tw * p3.tx);
int ty1 = (int) (th * p1.ty);
int ty2 = (int) (th * p2.ty);
int ty3 = (int) (th * p3.ty);
int dx1 = 0;
int dx2 = 0;
int dx3 = 0;
int dz1 = 0;
int dz2 = 0;
int dz3 = 0;
int di1 = 0;
int di2 = 0;
int di3 = 0;
int dtx1 = 0;
int dtx2 = 0;
int dtx3 = 0;
int dty1 = 0;
int dty2 = 0;
int dty3 = 0;
int dy;
if (y2 != y1) {
dy = (y2 - y1) >> 16;
dx1 = (x2 - x1) / dy;
dz1 = (p2.zz - p1.zz) / dy;
di1 = (i2 - i1) / dy;
dtx1 = (tx2 - tx1) / dy;
dty1 = (ty2 - ty1) / dy;
}
if (y3 != y2) {
dy = (y3 - y2) >> 16;
dx2 = (x3 - x2) / dy;
dz2 = (p3.zz - p2.zz) / dy;
di2 = (i3 - i2) / dy;
dtx2 = (tx3 - tx2) / dy;
dty2 = (ty3 - ty2) / dy;
}
if (y3 != y1) {
dy = (y3 - y1) >> 16;
dx3 = (x3 - x1) / dy;
dz3 = (p3.zz - p1.zz) / dy;
di3 = (i3 - i1) / dy;
dtx3 = (tx3 - tx1) / dy;
dty3 = (ty3 - ty1) / dy;
}
int xL = x1;
int xR = x1;
int zL = p1.zz;
int zR = p1.zz;
int iL = i1;
int iR = i1;
int txL = tx1;
int txR = tx1;
int tyL = ty1;
int tyR = ty1;
y1 = y1 >> 16;
y2 = y2 >> 16;
y3 = y3 >> 16;
for (int k = y1; k < y2; k++) {
if ((k >= 0) && (k < h)) {
LEdgeBuffer[k] = xL >> 16;
REdgeBuffer[k] = xR >> 16;
ZEdgeBufferL[k] = zL;
ZEdgeBufferR[k] = zR;
IEdgeBufferL[k] = iL;
IEdgeBufferR[k] = iR;
TXEdgeBufferL[k] = txL;
TXEdgeBufferR[k] = txR;
TYEdgeBufferL[k] = tyL;
TYEdgeBufferR[k] = tyR;
}
xL += dx1;
xR += dx3;
zL += dz1;
zR += dz3;
iL += di1;
iR += di3;
txL += dtx1;
txR += dtx3;
tyL += dty1;
tyR += dty3;
}
xL = x2;
zL = p2.zz;
iL = i2;
txL = tx2;
tyL = ty2;
for (int k = y2; k <= y3; k++) {
if ((k >= 0) && (k < h)) {
LEdgeBuffer[k] = xL >> 16;
REdgeBuffer[k] = xR >> 16;
ZEdgeBufferL[k] = zL;
ZEdgeBufferR[k] = zR;
IEdgeBufferL[k] = iL;
IEdgeBufferR[k] = iR;
TXEdgeBufferL[k] = txL;
TXEdgeBufferR[k] = txR;
TYEdgeBufferL[k] = tyL;
TYEdgeBufferR[k] = tyR;
}
xL += dx2;
xR += dx3;
zL += dz2;
zR += dz3;
iL += di2;
iR += di3;
txL += dtx2;
txR += dtx3;
tyL += dty2;
tyR += dty3;
}
y1 = crop(y1, 0, h);
y3 = crop(y3, 0, h);
for (int j = y1; j <= y3; j++) drawGouraudTextureLine(j, object[obj].texture);
}
private void drawPhongTexture(int obj, idx3d_triangle t) {
int temp;
idx3d_node temp1;
idx3d_node p1 = object[obj].node[t.p1];
idx3d_node p2 = object[obj].node[t.p2];
idx3d_node p3 = object[obj].node[t.p3];
if (p1.yy > p2.yy) {
temp1 = p1;
p1 = p2;
p2 = temp1;
}
if (p2.yy > p3.yy) {
temp1 = p2;
p2 = p3;
p3 = temp1;
}
if (p1.yy > p2.yy) {
temp1 = p1;
p1 = p2;
p2 = temp1;
}
int x1 = p1.xx << 16;
int x2 = p2.xx << 16;
int x3 = p3.xx << 16;
int y1 = p1.yy << 16;
int y2 = p2.yy << 16;
int y3 = p3.yy << 16;
int nx1 = (int) (65536 * p1.n2.x);
int nx2 = (int) (65536 * p2.n2.x);
int nx3 = (int) (65536 * p3.n2.x);
int ny1 = (int) (65536 * p1.n2.y);
int ny2 = (int) (65536 * p2.n2.y);
int ny3 = (int) (65536 * p3.n2.y);
float tw = (float) texture[object[obj].texture].w * 65536;
float th = (float) texture[object[obj].texture].h * 65536;
int tx1 = (int) (tw * p1.tx);
int tx2 = (int) (tw * p2.tx);
int tx3 = (int) (tw * p3.tx);
int ty1 = (int) (th * p1.ty);
int ty2 = (int) (th * p2.ty);
int ty3 = (int) (th * p3.ty);
int dx1 = 0;
int dx2 = 0;
int dx3 = 0;
int dz1 = 0;
int dz2 = 0;
int dz3 = 0;
int dnx1 = 0;
int dnx2 = 0;
int dnx3 = 0;
int dny1 = 0;
int dny2 = 0;
int dny3 = 0;
int dtx1 = 0;
int dtx2 = 0;
int dtx3 = 0;
int dty1 = 0;
int dty2 = 0;
int dty3 = 0;
int dy;
if (y2 != y1) {
dy = (y2 - y1) >> 16;
dx1 = (x2 - x1) / dy;
dz1 = (p2.zz - p1.zz) / dy;
dnx1 = (nx2 - nx1) / dy;
dny1 = (ny2 - ny1) / dy;
dtx1 = (tx2 - tx1) / dy;
dty1 = (ty2 - ty1) / dy;
}
if (y3 != y2) {
dy = (y3 - y2) >> 16;
dx2 = (x3 - x2) / dy;
dz2 = (p3.zz - p2.zz) / dy;
dnx2 = (nx3 - nx2) / dy;
dny2 = (ny3 - ny2) / dy;
dtx2 = (tx3 - tx2) / dy;
dty2 = (ty3 - ty2) / dy;
}
if (y3 != y1) {
dy = (y3 - y1) >> 16;
dx3 = (x3 - x1) / dy;
dz3 = (p3.zz - p1.zz) / dy;
dnx3 = (nx3 - nx1) / dy;
dny3 = (ny3 - ny1) / dy;
dtx3 = (tx3 - tx1) / dy;
dty3 = (ty3 - ty1) / dy;
}
int xL = x1;
int xR = x1;
int zL = p1.zz;
int zR = p1.zz;
int nxL = nx1;
int nxR = nx1;
int nyL = ny1;
int nyR = ny1;
int txL = tx1;
int txR = tx1;
int tyL = ty1;
int tyR = ty1;
y1 = y1 >> 16;
y2 = y2 >> 16;
y3 = y3 >> 16;
for (int k = y1; k < y2; k++) {
if ((k >= 0) && (k < h)) {
LEdgeBuffer[k] = xL >> 16;
REdgeBuffer[k] = xR >> 16;
ZEdgeBufferL[k] = zL;
ZEdgeBufferR[k] = zR;
NXEdgeBufferL[k] = nxL;
NXEdgeBufferR[k] = nxR;
NYEdgeBufferL[k] = nyL;
NYEdgeBufferR[k] = nyR;
TXEdgeBufferL[k] = txL;
TXEdgeBufferR[k] = txR;
TYEdgeBufferL[k] = tyL;
TYEdgeBufferR[k] = tyR;
}
xL += dx1;
xR += dx3;
zL += dz1;
zR += dz3;
nxL += dnx1;
nxR += dnx3;
nyL += dny1;
nyR += dny3;
txL += dtx1;
txR += dtx3;
tyL += dty1;
tyR += dty3;
}
xL = x2;
zL = p2.zz;
nxL = nx2;
nyL = ny2;
txL = tx2;
tyL = ty2;
for (int k = y2; k <= y3; k++) {
if ((k >= 0) && (k < h)) {
LEdgeBuffer[k] = xL >> 16;
REdgeBuffer[k] = xR >> 16;
ZEdgeBufferL[k] = zL;
ZEdgeBufferR[k] = zR;
NXEdgeBufferL[k] = nxL;
NXEdgeBufferR[k] = nxR;
NYEdgeBufferL[k] = nyL;
NYEdgeBufferR[k] = nyR;
TXEdgeBufferL[k] = txL;
TXEdgeBufferR[k] = txR;
TYEdgeBufferL[k] = tyL;
TYEdgeBufferR[k] = tyR;
}
xL += dx2;
xR += dx3;
zL += dz2;
zR += dz3;
nxL += dnx2;
nxR += dnx3;
nyL += dny2;
nyR += dny3;
txL += dtx2;
txR += dtx3;
tyL += dty2;
tyR += dty3;
}
y1 = crop(y1, 0, h);
y3 = crop(y3, 0, h);
for (int j = y1; j <= y3; j++) drawPhongTextureLine(j, object[obj].texture);
}
private void drawEnvmappedTexture(int obj, idx3d_triangle t) {
int temp;
idx3d_node temp1;
idx3d_node p1 = object[obj].node[t.p1];
idx3d_node p2 = object[obj].node[t.p2];
idx3d_node p3 = object[obj].node[t.p3];
if (p1.yy > p2.yy) {
temp1 = p1;
p1 = p2;
p2 = temp1;
}
if (p2.yy > p3.yy) {
temp1 = p2;
p2 = p3;
p3 = temp1;
}
if (p1.yy > p2.yy) {
temp1 = p1;
p1 = p2;
p2 = temp1;
}
int x1 = p1.xx << 16;
int x2 = p2.xx << 16;
int x3 = p3.xx << 16;
int y1 = p1.yy << 16;
int y2 = p2.yy << 16;
int y3 = p3.yy << 16;
int nx1 = (int) (65536 * p1.n2.x);
int nx2 = (int) (65536 * p2.n2.x);
int nx3 = (int) (65536 * p3.n2.x);
int ny1 = (int) (65536 * p1.n2.y);
int ny2 = (int) (65536 * p2.n2.y);
int ny3 = (int) (65536 * p3.n2.y);
float tw = (float) texture[object[obj].texture].w * 65536;
float th = (float) texture[object[obj].texture].h * 65536;
int tx1 = (int) (tw * p1.tx);
int tx2 = (int) (tw * p2.tx);
int tx3 = (int) (tw * p3.tx);
int ty1 = (int) (th * p1.ty);
int ty2 = (int) (th * p2.ty);
int ty3 = (int) (th * p3.ty);
int dx1 = 0;
int dx2 = 0;
int dx3 = 0;
int dz1 = 0;
int dz2 = 0;
int dz3 = 0;
int dnx1 = 0;
int dnx2 = 0;
int dnx3 = 0;
int dny1 = 0;
int dny2 = 0;
int dny3 = 0;
int dtx1 = 0;
int dtx2 = 0;
int dtx3 = 0;
int dty1 = 0;
int dty2 = 0;
int dty3 = 0;
int dy;
if (y2 != y1) {
dy = (y2 - y1) >> 16;
dx1 = (x2 - x1) / dy;
dz1 = (p2.zz - p1.zz) / dy;
dnx1 = (nx2 - nx1) / dy;
dny1 = (ny2 - ny1) / dy;
dtx1 = (tx2 - tx1) / dy;
dty1 = (ty2 - ty1) / dy;
}
if (y3 != y2) {
dy = (y3 - y2) >> 16;
dx2 = (x3 - x2) / dy;
dz2 = (p3.zz - p2.zz) / dy;
dnx2 = (nx3 - nx2) / dy;
dny2 = (ny3 - ny2) / dy;
dtx2 = (tx3 - tx2) / dy;
dty2 = (ty3 - ty2) / dy;
}
if (y3 != y1) {
dy = (y3 - y1) >> 16;
dx3 = (x3 - x1) / dy;
dz3 = (p3.zz - p1.zz) / dy;
dnx3 = (nx3 - nx1) / dy;
dny3 = (ny3 - ny1) / dy;
dtx3 = (tx3 - tx1) / dy;
dty3 = (ty3 - ty1) / dy;
}
int xL = x1;
int xR = x1;
int zL = p1.zz;
int zR = p1.zz;
int nxL = nx1;
int nxR = nx1;
int nyL = ny1;
int nyR = ny1;
int txL = tx1;
int txR = tx1;
int tyL = ty1;
int tyR = ty1;
y1 = y1 >> 16;
y2 = y2 >> 16;
y3 = y3 >> 16;
for (int k = y1; k < y2; k++) {
if ((k >= 0) && (k < h)) {
LEdgeBuffer[k] = xL >> 16;
REdgeBuffer[k] = xR >> 16;
ZEdgeBufferL[k] = zL;
ZEdgeBufferR[k] = zR;
NXEdgeBufferL[k] = nxL;
NXEdgeBufferR[k] = nxR;
NYEdgeBufferL[k] = nyL;
NYEdgeBufferR[k] = nyR;
TXEdgeBufferL[k] = txL;
TXEdgeBufferR[k] = txR;
TYEdgeBufferL[k] = tyL;
TYEdgeBufferR[k] = tyR;
}
xL += dx1;
xR += dx3;
zL += dz1;
zR += dz3;
nxL += dnx1;
nxR += dnx3;
nyL += dny1;
nyR += dny3;
txL += dtx1;
txR += dtx3;
tyL += dty1;
tyR += dty3;
}
xL = x2;
zL = p2.zz;
nxL = nx2;
nyL = ny2;
txL = tx2;
tyL = ty2;
for (int k = y2; k <= y3; k++) {
if ((k >= 0) && (k < h)) {
LEdgeBuffer[k] = xL >> 16;
REdgeBuffer[k] = xR >> 16;
ZEdgeBufferL[k] = zL;
ZEdgeBufferR[k] = zR;
NXEdgeBufferL[k] = nxL;
NXEdgeBufferR[k] = nxR;
NYEdgeBufferL[k] = nyL;
NYEdgeBufferR[k] = nyR;
TXEdgeBufferL[k] = txL;
TXEdgeBufferR[k] = txR;
TYEdgeBufferL[k] = tyL;
TYEdgeBufferR[k] = tyR;
}
xL += dx2;
xR += dx3;
zL += dz2;
zR += dz3;
nxL += dnx2;
nxR += dnx3;
nyL += dny2;
nyR += dny3;
txL += dtx2;
txR += dtx3;
tyL += dty2;
tyR += dty3;
}
y1 = crop(y1, 0, h);
y3 = crop(y3, 0, h);
for (int j = y1; j <= y3; j++) drawEnvmappedTextureLine(j, object[obj].texture);
}
private void drawFlatshadedLine(int y, int color) {
if ((y >= 0) && (y < h)) {
int xL = LEdgeBuffer[y];
int xR = REdgeBuffer[y];
int zL = ZEdgeBufferL[y];
int zR = ZEdgeBufferR[y];
if ((xL != xR)) {
if (xL > xR) {
int temp;
temp = xL;
xL = xR;
xR = temp;
temp = zL;
zL = zR;
zR = temp;
}
int dz = (zR - zL) / (xR - xL);
int z = zL;
xL = crop(xL, 0, w);
xR = crop(xR, 0, w);
int offset = y * w;
for (int x = xL; x < xR; x++) {
if (z < zBuffer[x][y]) {
TargetPixel[x + offset] = color;
zBuffer[x][y] = z;
}
z += dz;
}
}
}
}
private void drawGouraudLine(int y, int color) {
if ((y >= 0) && (y < h)) {
int xL = LEdgeBuffer[y];
int xR = REdgeBuffer[y];
int zL = ZEdgeBufferL[y];
int zR = ZEdgeBufferR[y];
int iL = IEdgeBufferL[y];
int iR = IEdgeBufferR[y];
if ((xL != xR)) {
if (xL > xR) {
int temp;
temp = xL;
xL = xR;
xR = temp;
temp = zL;
zL = zR;
zR = temp;
temp = iL;
iL = iR;
iR = temp;
}
int dx = (xR - xL);
int dz = (zR - zL) / dx;
int di = (iR - iL) / dx;
int z = zL;
int i = iL;
xL = crop(xL, 0, w);
xR = crop(xR, 0, w);
int offset = y * w;
for (int x = xL; x < xR; x++) {
if (z < zBuffer[x][y]) {
TargetPixel[x + offset] = getColor(color, i >> 8);
zBuffer[x][y] = z;
}
z += dz;
i += di;
}
}
}
}
private void drawPhongLine(int y, int color) {
if ((y >= 0) && (y < h)) {
int xL = LEdgeBuffer[y];
int xR = REdgeBuffer[y];
int zL = ZEdgeBufferL[y];
int zR = ZEdgeBufferR[y];
int nxL = NXEdgeBufferL[y];
int nxR = NXEdgeBufferR[y];
int nyL = NYEdgeBufferL[y];
int nyR = NYEdgeBufferR[y];
if ((xL != xR)) {
if (xL > xR) {
int temp;
temp = xL;
xL = xR;
xR = temp;
temp = zL;
zL = zR;
zR = temp;
temp = nxL;
nxL = nxR;
nxR = temp;
temp = nyL;
nyL = nyR;
nyR = temp;
}
int dx = (xR - xL);
int dz = (zR - zL) / dx;
int dnx = (nxR - nxL) / dx;
int dny = (nyR - nyL) / dx;
int z = zL;
int nx = nxL;
int ny = nyL;
xL = crop(xL, 0, w);
xR = crop(xR, 0, w);
int offset = y * w;
for (int x = xL; x < xR; x++) {
if (z < zBuffer[x][y]) {
TargetPixel[x + offset] = getColor(color, getIntensity(nx / 256, ny / 256));
zBuffer[x][y] = z;
}
z += dz;
nx += dnx;
ny += dny;
}
}
}
}
private void drawEnvmappedLine(int y, int color) {
if ((y >= 0) && (y < h)) {
int xL = LEdgeBuffer[y];
int xR = REdgeBuffer[y];
int zL = ZEdgeBufferL[y];
int zR = ZEdgeBufferR[y];
int nxL = NXEdgeBufferL[y];
int nxR = NXEdgeBufferR[y];
int nyL = NYEdgeBufferL[y];
int nyR = NYEdgeBufferR[y];
if ((xL != xR)) {
if (xL > xR) {
int temp;
temp = xL;
xL = xR;
xR = temp;
temp = zL;
zL = zR;
zR = temp;
temp = nxL;
nxL = nxR;
nxR = temp;
temp = nyL;
nyL = nyR;
nyR = temp;
}
int dx = (xR - xL);
int dz = (zR - zL) / dx;
int dnx = (nxR - nxL) / dx;
int dny = (nyR - nyL) / dx;
int z = zL;
int nx = nxL;
int ny = nyL;
xL = crop(xL, 0, w);
xR = crop(xR, 0, w);
int offset = y * w;
for (int x = xL; x < xR; x++) {
if (z < zBuffer[x][y]) {
TargetPixel[x + offset] = getColor(color, getEnvironment(nx / 256, ny / 256));
zBuffer[x][y] = z;
}
z += dz;
nx += dnx;
ny += dny;
}
}
}
}
private void drawGouraudTextureLine(int y, int t) {
if ((y >= 0) && (y < h)) {
int xL = LEdgeBuffer[y];
int xR = REdgeBuffer[y];
int zL = ZEdgeBufferL[y];
int zR = ZEdgeBufferR[y];
int iL = IEdgeBufferL[y];
int iR = IEdgeBufferR[y];
int txL = TXEdgeBufferL[y];
int txR = TXEdgeBufferR[y];
int tyL = TYEdgeBufferL[y];
int tyR = TYEdgeBufferR[y];
if ((xL != xR)) {
if (xL > xR) {
int temp;
temp = xL;
xL = xR;
xR = temp;
temp = zL;
zL = zR;
zR = temp;
temp = iL;
iL = iR;
iR = temp;
temp = txL;
txL = txR;
txR = temp;
temp = tyL;
tyL = tyR;
tyR = temp;
}
int dx = (xR - xL);
int dz = (zR - zL) / dx;
int di = (iR - iL) / dx;
int dtx = (txR - txL) / dx;
int dty = (tyR - tyL) / dx;
int z = zL;
int i = iL;
int tx = txL;
int ty = tyL;
xL = crop(xL, 0, w);
xR = crop(xR, 0, w);
int offset = y * w;
for (int x = xL; x < xR; x++) {
if (z < zBuffer[x][y]) {
tx = (int) Math.abs(tx);
ty = (int) Math.abs(ty);
TargetPixel[x + offset] = getColor(texture[t].pixel[(tx >> 16) % texture[t].w][(ty >> 16) % texture[t].h], i >> 8);
zBuffer[x][y] = z;
}
z += dz;
i += di;
tx += dtx;
ty += dty;
}
}
}
}
private void drawPhongTextureLine(int y, int t) {
if ((y >= 0) && (y < h)) {
int xL = LEdgeBuffer[y];
int xR = REdgeBuffer[y];
int zL = ZEdgeBufferL[y];
int zR = ZEdgeBufferR[y];
int nxL = NXEdgeBufferL[y];
int nxR = NXEdgeBufferR[y];
int nyL = NYEdgeBufferL[y];
int nyR = NYEdgeBufferR[y];
int txL = TXEdgeBufferL[y];
int txR = TXEdgeBufferR[y];
int tyL = TYEdgeBufferL[y];
int tyR = TYEdgeBufferR[y];
if ((xL != xR)) {
if (xL > xR) {
int temp;
temp = xL;
xL = xR;
xR = temp;
temp = zL;
zL = zR;
zR = temp;
temp = nxL;
nxL = nxR;
nxR = temp;
temp = nyL;
nyL = nyR;
nyR = temp;
temp = txL;
txL = txR;
txR = temp;
temp = tyL;
tyL = tyR;
tyR = temp;
}
int dx = (xR - xL);
int dz = (zR - zL) / dx;
int dtx = (txR - txL) / dx;
int dty = (tyR - tyL) / dx;
int dnx = (nxR - nxL) / dx;
int dny = (nyR - nyL) / dx;
int z = zL;
int nx = nxL;
int ny = nyL;
int tx = txL;
int ty = tyL;
xL = crop(xL, 0, w);
xR = crop(xR, 0, w);
int offset = y * w;
for (int x = xL; x < xR; x++) {
if (z < zBuffer[x][y]) {
tx = (int) Math.abs(tx);
ty = (int) Math.abs(ty);
TargetPixel[x + offset] = getColor(texture[t].pixel[(tx >> 16) % texture[t].w][(ty >> 16) % texture[t].h], getIntensity(nx / 256, ny / 256));
zBuffer[x][y] = z;
}
z += dz;
nx += dnx;
ny += dny;
tx += dtx;
ty += dty;
}
}
}
}
private void drawEnvmappedTextureLine(int y, int t) {
if ((y >= 0) && (y < h)) {
int xL = LEdgeBuffer[y];
int xR = REdgeBuffer[y];
int zL = ZEdgeBufferL[y];
int zR = ZEdgeBufferR[y];
int nxL = NXEdgeBufferL[y];
int nxR = NXEdgeBufferR[y];
int nyL = NYEdgeBufferL[y];
int nyR = NYEdgeBufferR[y];
int txL = TXEdgeBufferL[y];
int txR = TXEdgeBufferR[y];
int tyL = TYEdgeBufferL[y];
int tyR = TYEdgeBufferR[y];
if ((xL != xR)) {
if (xL > xR) {
int temp;
temp = xL;
xL = xR;
xR = temp;
temp = zL;
zL = zR;
zR = temp;
temp = nxL;
nxL = nxR;
nxR = temp;
temp = nyL;
nyL = nyR;
nyR = temp;
temp = txL;
txL = txR;
txR = temp;
temp = tyL;
tyL = tyR;
tyR = temp;
}
int dx = (xR - xL);
int dz = (zR - zL) / dx;
int dtx = (txR - txL) / dx;
int dty = (tyR - tyL) / dx;
int dnx = (nxR - nxL) / dx;
int dny = (nyR - nyL) / dx;
int z = zL;
int nx = nxL;
int ny = nyL;
int tx = txL;
int ty = tyL;
xL = crop(xL, 0, w);
xR = crop(xR, 0, w);
int offset = y * w;
for (int x = xL; x < xR; x++) {
if (z < zBuffer[x][y]) {
tx = (int) Math.abs(tx);
ty = (int) Math.abs(ty);
TargetPixel[x + offset] = getColor(texture[t].pixel[(tx >> 16) % texture[t].w][(ty >> 16) % texture[t].h], getEnvironment(nx / 256, ny / 256));
zBuffer[x][y] = z;
}
z += dz;
nx += dnx;
ny += dny;
tx += dtx;
ty += dty;
}
}
}
}
public void generateField(float data[][], int xmax, int ymax, int rm, int c) {
float xtemp;
float ytemp;
float ztemp;
int q1;
int q2;
int q3;
int q4;
idx3d_node v;
addObject(rm, c);
rotateObject(objects, (float) 90, 0, 0);
float xscale = 2 / (float) (xmax - 1);
float yscale = 2 / (float) (ymax - 1);
for (int i = 0; i < xmax; i++) {
for (int j = 0; j < ymax; j++) {
xtemp = -1 + xscale * (float) i;
ytemp = -1 + yscale * (float) j;
ztemp = data[i][j];
v = new idx3d_node(xtemp, ytemp, ztemp);
if ((j > 0) && (i > 0)) {
v.n.x = (data[i - 1][j] - data[i][j]) / xscale;
v.n.y = (data[i][j - 1] - data[i][j]) / yscale;
v.n.z = (float) 1;
}
v.n.z = (float) 1;
v.tx = (float) i / (float) (xmax - 1);
v.ty = (float) j / (float) (ymax - 1);
addNode(objects, v);
}
}
for (int i = 0; i < (xmax - 1); i++) {
for (int j = 0; j < (ymax - 1); j++) {
q1 = j + xmax * i + 1;
q2 = j + 1 + xmax * i + 1;
q3 = j + xmax * (i + 1) + 1;
q4 = j + 1 + xmax * (i + 1) + 1;
addTriangle(objects, q1, q2, q3);
addTriangle(objects, q3, q2, q4);
}
}
}
public void generateScanObject(int obj, int rows, int cols) {
int start = 1;
int k;
int sw = 0;
int end = object[obj].nodes + 1;
int t_nodes = object[obj].nodes;
float tmpx, tmpy, tmpz, dx, dy;
for (int j = 0; j < cols; j++)
for (int i = 1; i < rows; i++) {
k = j * rows + i;
tmpx = object[obj].node[k].v.x;
tmpz = object[obj].node[k].v.z;
if (i == 1)
object[obj].node[k].n = normalize(new idx3d_vector(tmpx, 1, tmpz));
else if (i == rows - 1)
object[obj].node[k].n = normalize(new idx3d_vector(tmpx, -1, tmpz));
else {
dx = object[obj].node[k - 1].v.x - object[obj].node[k + 1].v.x;
dy = object[obj].node[k - 1].v.y - object[obj].node[k + 1].v.y;
object[obj].node[k].n = normalize(new idx3d_vector(tmpx, dx / dy, tmpz));
}
object[obj].node[k].tx = (float) (j) / (float) (cols - 1);
object[obj].node[k].ty = (float) (i - 1) / (float) (rows - 1);
}
for (int col = 0; col < cols; col++) {
for (int row = 1; row < rows; row++) {
sw = 0;
k = col * rows + row;
tmpx = object[obj].node[k].v.x;
tmpz = object[obj].node[k].v.z;
if ((tmpx == 0) || (tmpz == 0)) sw = 1;
k = (col + 1) * rows + row;
tmpx = object[obj].node[k].v.x;
tmpz = object[obj].node[k].v.z;
if ((tmpx == 0) || (tmpz == 0)) sw = 1;
k = col * rows + row + 1;
tmpx = object[obj].node[k].v.x;
tmpz = object[obj].node[k].v.z;
if ((tmpx == 0) || (tmpz == 0)) sw = 1;
if (sw == 0) {
addTriangle(obj, (rows * col + row), (rows * (col + 1) + row), (rows * col + row + 1));
addTriangle(obj, (rows * col + row + 1), (rows * (col + 1) + row), (rows * (col + 1) + row + 1));
}
}
}
}
public void generateRotationObject(int obj, int steps) {
double alpha = 2 * pi / ((double) steps);
int start = 1;
int end = object[obj].nodes + 1;
int t_nodes = object[obj].nodes;
object[obj].node[1].n = normalize(new idx3d_vector(object[obj].node[1].v.x, (float) 1, object[obj].node[1].v.z));
object[obj].node[t_nodes].n = normalize(new idx3d_vector(object[obj].node[t_nodes].v.x, (float) -1, object[obj].node[t_nodes].v.z));
for (int i = 2; i < t_nodes; i++) {
object[obj].node[i].n = normalize(new idx3d_vector(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));
object[obj].node[i].tx = 0;
object[obj].node[i].ty = (float) (i - 1) / (float) (t_nodes - 1);
}
for (int j = 1; j < (steps + 1); j++) {
for (int i = start; i < end; i++) {
float qx = (float) (object[obj].node[i].v.x * Math.cos(j * alpha) + object[obj].node[i].v.z * Math.sin(j * alpha));
float qz = (float) (object[obj].node[i].v.z * Math.cos(j * alpha) - object[obj].node[i].v.x * Math.sin(j * alpha));
idx3d_node w = new idx3d_node(qx, object[obj].node[i].v.y, qz);
if (i == start)
w.n = normalize(new idx3d_vector(qx, 1, qz));
else if (i == end - 1)
w.n = normalize(new idx3d_vector(qx, -1, qz));
else
w.n = normalize(new idx3d_vector(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));
w.ty = (float) (i - 1) / (float) (t_nodes - 1);
w.tx = (float) (j - 1) / (float) (steps - 1);
addNode(obj, w);
}
}
for (int col = 0; col < steps; col++) {
for (int row = 1; row < t_nodes; row++) {
addTriangle(obj, (t_nodes * col + row), (t_nodes * (col + 1) + row), (t_nodes * col + row + 1));
addTriangle(obj, (t_nodes * col + row + 1), (t_nodes * (col + 1) + row), (t_nodes * (col + 1) + row + 1));
}
}
}
public String getFPS(int frames) {
long idx_time1;
long idx_time2;
double fps;
Image temp;
idx_time1 = new Date().getTime();
for (int i = 0; i < frames; i++) {
rotateWorld((float) Math.random(), (float) Math.random(), (float) Math.random());
temp = renderScene();
}
idx_time2 = new Date().getTime();
fps = (double) frames / ((double) (idx_time2 - idx_time1) / 1000);
fps = (double) ((int) (fps * 100)) / 100;
return new String("Benchmark: " + fps + " FPS");
}
}
class idx3d_matrix {
float matrix[][] = new float[4][4];
public idx3d_matrix() {
matrix[0][0] = (float) 1;
matrix[1][1] = (float) 1;
matrix[2][2] = (float) 1;
matrix[3][3] = (float) 1;
}
}
class idx3d_object {
int mode = 1;
int color;
idx3d_triangle triangle[];
idx3d_node node[];
int triangles = 0;
int maxtriangles = 0;
int nodes = 0;
int maxnodes = 0;
int texture;
idx3d_matrix matrix = new idx3d_matrix();
idx3d_matrix matrix2 = new idx3d_matrix();
public idx3d_object(int rm, int col) {
mode = rm;
color = col;
}
}
class idx3d_node {
idx3d_vector v = new idx3d_vector();
idx3d_vector n = new idx3d_vector();
idx3d_vector n2 = new idx3d_vector();
int xx; int yy; int zz; float tx; float ty;
public idx3d_node(float x, float y, float z) {
v.x = x;
v.y = y;
v.z = z;
n.x = (float) 0;
n.y = (float) 0;
n.z = (float) 1;
}
}
class idx3d_triangle {
int p1;
int p2;
int p3;
idx3d_vector n = new idx3d_vector();
public idx3d_triangle(int q1, int q2, int q3) {
p1 = q1;
p2 = q2;
p3 = q3;
}
}
class idx3d_light {
int x;
int y;
int z;
int mode = 0; int intensity = 255;
public idx3d_light(idx3d_vector lvect, int lmode, int lintensity) {
x = (int) (lvect.x * 255);
y = (int) (lvect.y * 255);
z = (int) (lvect.z * 255);
mode = lmode;
intensity = lintensity;
}
}
class idx3d_texture {
int w;
int h;
int pixel[][];
}