import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Event;
import java.awt.Image;
import java.awt.Font;
import java.util.Vector; // http://java.sun.com/products/jdk/1.1/docs/api/java.util.Vector.html
/*
TODOs:
* Poly.line - clip z to horizontal edges of buffer
* Frame rate dependent time increments
*/
//---- Triangle rasteriser ---------------------------------------------------//
class Tri
{
//- Output buffers
private int w, h;
private int[] buf; // Pixel buffer (0x00rrggbb)
private int[] zbuf; // 1/Z Buffer
private int[] ibuf; // Index buffer (for shape picking)
//- Rendering workspace
private int ymin, ymax;
private int xmin[], xmax[];
private int zmin[], zmax[];
//- Triangle parameters
public double x1, y1, z1, r1, g1, b1, a1, u1, v1;
public double x2, y2, z2, r2, g2, b2, a2, u2, v2;
public double x3, y3, z3, r3, g3, b3, a3, u3, v3;
//---- Tri
public Tri(int[] buf, int[] zbuf, int w, int h)
{
this.w = w;
this.h = h;
this.buf = buf;
this.zbuf = zbuf;
xmin = new int[h];
xmax = new int[h];
zmin = new int[h];
zmax = new int[h];
}
//---- col
public void col(int c)
{
clear();
line(x1, y1, z1, x2, y2, z2);
line(x2, y2, z2, x3, y3, z3);
line(x3, y3, z3, x1, y1, z1);
fill_col(c);
}
//---- clearZBuf
public void clearZBuf()
{
for(int i=0; i<w*h; i++) zbuf[i] = 0;
}
//---- clear
public void clear()
{
int i;
ymin = h;
ymax = 0;
for(i=0; i<h; i++)
{
xmin[i] = w;
xmax[i] = 0;
}
}
public void line(double x1, double y1, double z1, double x2, double y2, double z2)
{
double t;
int x, y, z, i;
int iy1, iy2;
if(y2>y1) {
// line going down - right hand side
iy1 = (int)(y1)+1;
iy2 = (int)(y2)+1;
if(iy1 >= h) { return; }
if(iy2 <= 0) { return; }
if(iy1 < 0) { iy1 = 0; }
if(iy2 > h) { iy2 = h; }
if(iy1 < ymin) { ymin = iy1; }
if(iy2 > ymax) { ymax = iy2; }
for(y=iy1; y<iy2; y++)
{
x = (int) (x1 + (x2-x1)*(y-y1)/(y2-y1));
z = (int)(32*65536/(z1 + (z2-z1)*(y-y1)/(y2-y1)));
if(x > w) { x = w; } // TODO: Clip z to edge of screen too
if(x < 0) { x = 0; } // TODO: Clip z to edge of screen too
xmax[y] = x;
zmax[y] = z;
}
} else {
// line going up - left hand side
t = x1; x1 = x2; x2 = t;
t = y1; y1 = y2; y2 = t;
t = z1; z1 = z2; z2 = t;
iy1 = (int)(y1)+1;
iy2 = (int)(y2)+1;
if(iy1 >= h) { return; }
if(iy2 <= 0) { return; }
if(iy1 < 0) { iy1 = 0; }
if(iy2 > h) { iy2 = h; }
if(iy1 < ymin) { ymin = iy1; }
if(iy2 > ymax) { ymax = iy2; }
for(y=iy1; y<iy2; y++)
{
x = (int) (x1 + (x2-x1)*(y-y1)/(y2-y1));
z = (int)(32*65536/(z1 + (z2-z1)*(y-y1)/(y2-y1)));
if(x > w) { x = w; } // TODO: Clip z to edge of screen too
if(x < 0) { x = 0; } // TODO: Clip z to edge of screen too
xmin[y] = x;
zmin[y] = z;
}
}
}
public void fill_col(int c)
{
int x, y, z, zd=0;
int o, oo;
oo = w*ymin;
for(y=ymin; y<ymax; y++)
{
o = oo + xmin[y];
z = zmin[y];
if(xmax[y] > xmin[y]) zd = (zmax[y]-z)/(xmax[y]-xmin[y]);
for(x=xmin[y]; x<xmax[y]; x++)
{
if(z > zbuf[o])
{
buf[o] = c;
zbuf[o] = z;
}
z += zd;
o++;
}
oo += w;
}
}
}
//---- Polygon rasteriser ----------------------------------------------------//
class Poly
{
int w, h;
int[] buf;
int[] zbuf;
int poly_ymin, poly_ymax;
int poly_xmin[], poly_xmax[];
int poly_zmin[], poly_zmax[];
// int poly2_ymin, poly2_ymax;
// int poly2_xmin[], poly2_xmax[];
public Poly(int[] buf, int[] zbuf, int w, int h)
{
this.w = w;
this.h = h;
this.buf = buf;
this.zbuf = zbuf;
poly_xmin = new int[h];
poly_xmax = new int[h];
poly_zmin = new int[h];
poly_zmax = new int[h];
}
public void clearZBuf()
{
for(int i=0; i<w*h; i++) zbuf[i] = 0;
}
public void clear()
{
int i;
poly_ymin = h;
poly_ymax = 0;
for(i=0; i<h; i++)
{
poly_xmin[i] = w;
poly_xmax[i] = 0;
}
}
public void line(double x1, double y1, double z1, double x2, double y2, double z2)
{
double t;
int x, y, z, i;
int iy1, iy2;
if(y2>y1) {
// line going down - right hand side
iy1 = (int)(y1)+1;
iy2 = (int)(y2)+1;
if(iy1 >= h) { return; }
if(iy2 <= 0) { return; }
if(iy1 < 0) { iy1 = 0; }
if(iy2 > h) { iy2 = h; }
if(iy1 < poly_ymin) { poly_ymin = iy1; }
if(iy2 > poly_ymax) { poly_ymax = iy2; }
for(y=iy1; y<iy2; y++)
{
x = (int) (x1 + (x2-x1)*(y-y1)/(y2-y1));
z = (int)(4*4096*65536/ ( ( z1 + (z2-z1) * (y-y1) / (y2-y1) )) );
if(x > w) { x = w; } // TODO: Clip z to edge of screen too
if(x < 0) { x = 0; } // TODO: Clip z to edge of screen too
poly_xmax[y] = x;
poly_zmax[y] = z;
}
} else {
// line going up - left hand side
t = x1; x1 = x2; x2 = t;
t = y1; y1 = y2; y2 = t;
t = z1; z1 = z2; z2 = t;
iy1 = (int)(y1)+1;
iy2 = (int)(y2)+1;
if(iy1 >= h) { return; }
if(iy2 <= 0) { return; }
if(iy1 < 0) { iy1 = 0; }
if(iy2 > h) { iy2 = h; }
if(iy1 < poly_ymin) { poly_ymin = iy1; }
if(iy2 > poly_ymax) { poly_ymax = iy2; }
for(y=iy1; y<iy2; y++)
{
x = (int) (x1 + (x2-x1)*(y-y1)/(y2-y1));
z = (int)(4*4096*65536/(z1 + (z2-z1)*(y-y1)/(y2-y1)));
if(x > w) { x = w; } // TODO: Clip z to edge of screen too
if(x < 0) { x = 0; } // TODO: Clip z to edge of screen too
poly_xmin[y] = x;
poly_zmin[y] = z;
}
}
}
public void fill_col(int c)
{
int x, y, z, zd=0;
int o, oo;
////////
c = 0x00FFFFFF;
////////
oo = w*poly_ymin;
//- Solid fill
if((c & 0xFF000000) == 0)
{
for(y=poly_ymin; y<poly_ymax; y++, oo += w)
{
z = poly_zmin[y]; if(poly_xmax[y] > poly_xmin[y]) zd = (poly_zmax[y]-z)/(poly_xmax[y]-poly_xmin[y]);
for(x=poly_xmin[y], o = oo + poly_xmin[y]; x<poly_xmax[y]; x++, o++, z += zd) if(z > zbuf[o]) { buf[o] = c; zbuf[o] = z; }
}
}
//- Alpha fill
else
{
for(y=poly_ymin; y<poly_ymax; y++, oo += w)
{
z = poly_zmin[y]; if(poly_xmax[y] > poly_xmin[y]) zd = (poly_zmax[y]-z)/(poly_xmax[y]-poly_xmin[y]);
for(x=poly_xmin[y], o = oo + poly_xmin[y]; x<poly_xmax[y]; x++, o++, z += zd) if(z > zbuf[o])
{
if(zbuf[o] > 0) buf[o] = ((buf[o]>>1)&0x7F7F7F)+((c>>1)&0x7F7F7F);
else buf[o] = c;
zbuf[o] = z;
}
}
}
}
}
//---- 3D Renderer -----------------------------------------------------------//
//---- Surface
class Surface
{
public Surface()
{
}
}
//---- Scene
class Scene
{
//---- Data
//- Camera
private double camera_x=0, camera_y=0, camera_z=-11; // -17 to fit whole scene in, -11 for close-up
private double camera_rx=0, camera_ry=0;
//- Output buffer
private int[] buf = null;
private int[] zbuf = null;
private int w = 0, h = 0;
private Poly poly;
int bg_col = 0x00FFFFFF, bg_r=0, bg_g=0, bg_b=0;
//- Shapes in this scene
private Vector shapes;
//- Transformation stack
private Transform[] trans;
private int numTransforms;
protected double time = 0;
//---- Main code
public Scene()
{
shapes = new Vector();
trans = new Transform[32];
numTransforms = 0;
setBackground(bg_col);
}
//---- addShape
public void addShape(Shape s)
{
shapes.addElement(s);
}
//---- setBuffer
public void setBuffer(int[] buf, int w, int h)
{
this.buf = buf; this.w = w; this.h = h;
this.zbuf = new int[w*h];
poly = new Poly(buf, zbuf, w, h);
}
//---- setBackground
public void setBackground(int col)
{
bg_col = col;
bg_r = (col>>16) & 0xFF;
bg_g = (col>> 8) & 0xFF;
bg_b = (col ) & 0xFF;
}
//---- setCamera
public void setCamera(double x, double y, double z, double rx, double ry)
{
camera_x = x; camera_y = y; camera_z = z;
camera_rx = rx; camera_ry = ry;
}
//---- transformPoint
public void transformPoint(double p[], double t[], double s[])
{
// Transform point
trans[numTransforms-1].multiply(p, t);
// Screen space point
if(s != null)
{
s[0] = w*0.5 + 250.0*t[0]/(t[2]);
s[1] = h*0.5 - 250.0*t[1]/(t[2]);
s[2] = t[2];
}
}
//---- plotPoint
public void plotPoint(double sx, double sy)
{
// if(sx >= 0 && sx < w && sy >= 0 && sy < h) buf[(int)sx + w*(int)sy] = 0xFFFFFF;
if(sx >= 0 && sx < w-1 && sy >= 0 && sy < h-1)
{
double dx = sx-(int)sx;
double dy = sy-(int)sy;
int o = (int)sx + w*(int)sy;
int c00 = (int)(255*Math.sqrt((1-dx)*(1-dy)));
int c01 = (int)(255*Math.sqrt(( dx)*(1-dy)));
int c10 = (int)(255*Math.sqrt((1-dx)*( dy)));
int c11 = (int)(255*Math.sqrt(( dx)*( dy)));
buf[o ] = c00 + (c00<<8) + (c00 << 16);
buf[o+1 ] = c01 + (c01<<8) + (c01 << 16);
buf[o+w ] = c10 + (c10<<8) + (c10 << 16);
buf[o+w+1] = c11 + (c11<<8) + (c11 << 16);
}
}
//---- drawLine
public void drawLine(double x1, double y1, double x2, double y2)
{
double dx = x2-x1;
double dy = y2-y1;
if(dx < 0) dx =- dx;
if(dy < 0) dy =- dy;
if(dx > dy)
{
dx = 1/dx;
if(x2 < x1)
{
double y = y1; y1 = y2; y2 = y;
double x = x1; x1 = x2; x2 = x;
}
for(int i=(int)(x1+1); i<=(int)x2; i++) plotPoint(i, y1 + (y2-y1)*(i-x1)*dx);
}
else
{
dy = 1/dy;
if(y2 < y1)
{
double y = y1; y1 = y2; y2 = y;
double x = x1; x1 = x2; x2 = x;
}
for(int i=(int)(y1+1); i<=(int)y2; i++) plotPoint(x1 + (x2-x1)*(i-y1)*dy, i);
}
}
//---- drawFace
public void drawFace(double[] s1, double[] s2, double[] s3, int c)
{
poly.clear();
poly.line(s1[0], s1[1], s1[2], s2[0], s2[1], s2[2]);
poly.line(s2[0], s2[1], s2[2], s3[0], s3[1], s3[2]);
poly.line(s3[0], s3[1], s3[2], s1[0], s1[1], s1[2]);
poly.fill_col(c);
}
//---- transform
public void transform(Transform t)
{
trans[numTransforms] = new Transform(trans[numTransforms-1]);
trans[numTransforms].transform(t);
numTransforms ++;
}
//---- untransform
public void untransform()
{
numTransforms --;
}
//---- render
public void render()
{
//- Sort out time
time += 0.05; // Assume 20 fps
//- Set up transformation stack
trans[0] = new Transform();
trans[0].translate(-camera_x, -camera_y, -camera_z);
trans[0].rotateY(-camera_ry);
trans[0].rotateX(-camera_rx);
numTransforms = 1;
//- Clear buffer
int size = w*h;
int i, j;
/* */
for(i=0; i<size; i++) buf[i] = bg_col;
/* */
/* * /
for(i = 1+w; i < size-w-1; i++)
{
buf[i] = 0;
buf[i] += (buf[i-1]>>2)&0x003F3F3F;
buf[i] += (buf[i+1]>>2)&0x003F3F3F;
buf[i] += (buf[i-w]>>2)&0x003F3F3F;
buf[i] += (buf[i+w]>>2)&0x003F3F3F;
}
/* */
poly.clearZBuf();
//- Render shapes
for(i=0; i<shapes.size(); i++) ((Shape)shapes.elementAt(i)).render();
//- Post-processing effects
int o;
int d, dd, ddd;
int r, g, b;
int[][] gauss =
{
{ 1, 5, 9, 5, 1 },
{ 5, 16, 27, 16, 5 },
{ 9, 27, 44, 27, 9 },
{ 5, 16, 27, 16, 5 },
{ 1, 5, 9, 5, 1 }
};
int m, n;
int rad = 4;
for(j=rad; j<h-rad; j++) for(i=rad, o=j*w+i; i<w-rad; i++, o++)
{
// Calculate difference
d = (zbuf[o-1]>>2) + (zbuf[o+1]>>2) + (zbuf[o-w]>>2) + (zbuf[o+w]>>2);
d -= zbuf[o];
if(d < 0) d = 0;
d = (d)>>15;
if(d > 256) d = 256;
d = 256-d;
// Calculate rate of change
/*
dd = (zbuf[o-1]>>3) + (zbuf[o+1]>>3) + (zbuf[o-w]>>3) + (zbuf[o+w]>>3);
dd += (zbuf[o-2]>>3) + (zbuf[o+2]>>3) + (zbuf[o-w-w]>>3) + (zbuf[o+w+w]>>3);
dd -= zbuf[o];
if(dd < 0) dd = 0;
dd = (dd)>>17;
if(dd > 256) dd = 256;
dd = 256-dd;
*/
// Calculate 3rd order
/*
ddd = (zbuf[o-1]>>4) + (zbuf[o+1]>>4) + (zbuf[o-w]>>4) + (zbuf[o+w]>>4);
ddd += (zbuf[o-2]>>4) + (zbuf[o+2]>>4) + (zbuf[o-w-w]>>4) + (zbuf[o+w+w]>>4);
ddd += (zbuf[o-3]>>4) + (zbuf[o+3]>>4) + (zbuf[o-w-w-w]>>4) + (zbuf[o+w+w+w]>>4);
ddd += (zbuf[o-4]>>4) + (zbuf[o+4]>>4) + (zbuf[o-w-w-w-w]>>4) + (zbuf[o+w+w+w+w]>>4);
ddd -= zbuf[o];
if(ddd < 0) ddd = 0;
ddd = (ddd)>>16;
if(dd > 256) ddd = 256;
ddd = 256-ddd;
*/
// Apply filter
// if(dd < d) d = dd;
// d = (d>>1)+(dd>>1);
if(d < 256)
{
r = (buf[o]>>16)&255;
g = (buf[o]>> 8)&255;
b = (buf[o] )&255;
r = (r*d)>>8;
g = (g*d)>>8;
b = (b*d)>>8;
buf[o] = (r<<16)+(g<<8)+b;
}
}
// System.out.println(zbuf[w*h/2]);
//- Done
}
}
//---- Shape
class Shape
{
//---- Data
Scene scene = null;
public Transform trans = null;
int numPoints = 0;
int numLines = 0;
int numFaces = 0;
double[][] p; // Points
int[] lp1, lp2; // Lines
int[] fp1, fp2, fp3; // Faces
int[] col; // Face colours
double[][] t; // Translated points
double[][] s; // Screen points
Vector shapes;
//- Center point
double[] op;
double[] ot;
double[] os;
double fog;
double fog_start = 100, fog_dist = 100;
//---- Main code
public Shape(Scene sc)
{
scene = sc;
shapes = new Vector();
trans = new Transform();
p = new double[64][4];
lp1 = new int[64];
lp2 = new int[64];
fp1 = new int[64];
fp2 = new int[64];
fp3 = new int[64];
col = new int[64];
t = new double[64][4];
s = new double[64][4];
op = new double[4];
ot = new double[4];
os = new double[4];
op[0] = 0;
op[1] = 0;
op[2] = 0;
op[3] = 1;
}
//---- addPoint
public void addPoint(double x, double y, double z)
{
p[numPoints][0] = x;
p[numPoints][1] = y;
p[numPoints][2] = z;
p[numPoints][3] = 1;
numPoints ++;
}
public void addLine(int p1, int p2)
{
if(p1 == p2) return;
if(p1 > p2) { int p = p1; p1 = p2; p2 = p; }
lp1[numLines] = p1;
lp2[numLines] = p2;
numLines ++;
}
public void addFace(int p1, int p2, int p3)
{
fp1[numFaces] = p1;
fp2[numFaces] = p2;
fp3[numFaces] = p3;
col[numFaces] = (p1*0x76D761A9 + p2*0x78421687 + p3*0xF76DE1A7) & 0x00FFFFFF; // Random colour if none specified
numFaces ++;
}
public void addFace(int p1, int p2, int p3, int c)
{
fp1[numFaces] = p1;
fp2[numFaces] = p2;
fp3[numFaces] = p3;
col[numFaces] = c;
numFaces ++;
}
//---- addShape
public void addShape(Shape s)
{
shapes.addElement(s);
}
//---- setTransform
public void setTransform(Transform newtrans)
{
this.trans = null;
this.trans = new Transform(newtrans);
}
//---- drawFace
public void drawFace(double[] p1, double[] p2, double[] p3, int col)
{
if(p1[2] < 0.1 || p2[2] < 0.1 || p3[2] < 0.1) return;
int a = (col>>24) & 0xFF;
int r = (col>>16) & 0xFF;
int g = (col>> 8) & 0xFF;
int b = (col ) & 0xFF;
r = (int)(r*fog + scene.bg_r*(1-fog));
g = (int)(g*fog + scene.bg_g*(1-fog));
b = (int)(b*fog + scene.bg_b*(1-fog));
col = (a<<24)+(r<<16)+(g<<8)+b;
scene.drawFace(p1, p2, p3, col);
}
//---- render
public void render()
{
int i;
// Set up transformation
scene.transform(trans);
// Calculate position of shape origin
scene.transformPoint(op, ot, os);
// Calculate fogging for this object
fog = 1 - (os[2]-fog_start)/fog_dist;
if(fog < 0) fog = 0;
if(fog > 1) fog = 1;
// Render sub-shapes
for(i=0; i<shapes.size(); i++) ((Shape)shapes.elementAt(i)).render();
// Transform points
for(i=0; i<numPoints; i++) scene.transformPoint(p[i], t[i], s[i]);
// Render this shape
if(numLines+numFaces == 0) for(i=0; i<numPoints; i++) scene.plotPoint(s[i][0], s[i][1]);
if(numFaces == 0) for(i=0; i<numLines ; i++) scene.drawLine (s[lp1[i]][0], s[lp1[i]][1], s[lp2[i]][0], s[lp2[i]][1]);
for(i=0; i<numFaces ; i++) drawFace (s[fp1[i]], s[fp2[i]], s[fp3[i]], col[i]);
// Revert transformation
scene.untransform();
}
}
//---- This scene ------------------------------------------------------------//
//---- Square
class Square extends Shape
{
public Square(Scene sc)
{
super(sc);
addPoint(-1, 0, -1);
addPoint(-1, 0, 1);
addPoint( 1, 0, 1);
addPoint( 1, 0, -1);
addLine(0, 1);
addLine(1, 2);
addLine(2, 3);
addLine(3, 4);
addFace(0, 1, 2);
addFace(2, 3, 0);
}
}
//---- Cube
class Cube extends Shape
{
public Cube(Scene sc)
{
super(sc);
makeCube(sc, 0x999999);
}
public Cube(Scene sc, int col)
{
super(sc);
makeCube(sc, col);
}
private void makeCube(Scene sc, int col)
{
// System.out.println("Creating Cube");
addPoint(-1, -1, -1); // 0
addPoint(-1, -1, 1); // 1
addPoint(-1, 1, -1); // 2
addPoint(-1, 1, 1); // 3
addPoint( 1, -1, -1); // 4
addPoint( 1, -1, 1); // 5
addPoint( 1, 1, -1); // 6
addPoint( 1, 1, 1); // 7
addLine(0, 1);
addLine(0, 2);
addLine(0, 4);
addLine(1, 3);
addLine(1, 5);
addLine(2, 3);
addLine(2, 6);
addLine(3, 7);
addLine(4, 5);
addLine(4, 6);
addLine(5, 7);
addLine(6, 7);
addFace(0, 1, 3, col); // 0 1 3
addFace(0, 5, 1, col); // 0 1 5 !
addFace(0, 3, 2, col); // 0 2 3 !
addFace(0, 2, 6, col); // 0 2 6
addFace(0, 4, 5, col); // 0 4 5
addFace(0, 6, 4, col); // 0 4 6 !
addFace(1, 7, 3, col); // 1 3 7 !
addFace(1, 5, 7, col); // 1 5 7
addFace(2, 3, 7, col); // 2 3 7
addFace(2, 7, 6, col); // 2 6 7 !
addFace(4, 7, 5, col); // 4 5 7 !
addFace(4, 6, 7, col); // 4 6 7
}
}
//---- Checks
class Checks extends Shape
{
int size = 4;
public Checks(Scene sc, int col1, int col2)
{
super(sc);
int i, j;
for(j=0; j<size+1; j++) for(i=0; i<size+1; i++)
{
addPoint(i-0.5*size, 0, j-0.5*size);
// System.out.println(numPoints+" "+i+" "+j);
}
for(j=0; j<size; j++) for(i=0; i<size; i++)
{
int p = i+j*(size+1);
int col = ((i^j)&1)==1 ? col1 : col2;
addFace(p+size+2, p+1, p, col);
addFace(p, p+size+1, p+size+2, col);
}
}
}
//---- Pillar
class Pillar extends Shape
{
public Pillar(Scene sc)
{
super(sc);
// System.out.println("Creating Pillar");
Shape s;
s = new Cube(sc, 0x336699);
s.trans.scale(1.0, 0.2, 1.0);
s.trans.translate(0.0, -2.0, 0.0);
addShape(s);
s = new Cube(sc, 0x003366);
s.trans.scale(0.6, 1.8, 0.6);
addShape(s);
s = new Cube(sc, 0x336699);
s.trans.scale(1.0, 0.2, 1.0);
s.trans.translate(0.0, 2.0, 0.0);
addShape(s);
}
}
//---- LinkShape1
class LinkShape1 extends Shape
{
public LinkShape1(Scene sc)
{
super(sc);
Shape s;
s = new Cube(sc, 0xFFCC00);
s.trans.scale(0.3, 0.3, 0.3);
s.trans.translate(-0.7, 0, 0);
addShape(s);
s = new Cube(sc, 0xFFCC00);
s.trans.scale(0.3, 0.3, 0.3);
s.trans.translate( 0.7, 0, 0);
addShape(s);
s = new Cube(sc, 0xFFFF00);
s.trans.scale(0.3, 0.3, 0.3);
s.trans.translate(0, -0.7, 0);
addShape(s);
s = new Cube(sc, 0xFFFF00);
s.trans.scale(0.3, 0.3, 0.3);
s.trans.translate(0, 0.7, 0);
addShape(s);
s = new Cube(sc, 0xFF9900);
s.trans.scale(0.3, 0.3, 0.3);
s.trans.translate(0, 0, -0.7);
addShape(s);
s = new Cube(sc, 0xFF9900);
s.trans.scale(0.3, 0.3, 0.3);
s.trans.translate(0, 0, 0.7);
addShape(s);
s = new Cube(sc, 0xCC6600);
s.trans.scale(0.3, 0.3, 0.3);
s.trans.translate(0, 0, 0);
addShape(s);
}
}
//---- LinkShape2
class LinkShape2Corner extends Shape
{
public LinkShape2Corner(Scene sc, int col)
{
super(sc);
addPoint(1, 1, 1);
addPoint(1, 0, 0);
addPoint(0, 1, 0);
addPoint(0, 0, 1);
addFace(0, 1, 2, col);
addFace(0, 2, 3, col);
addFace(0, 3, 1, col);
}
}
class LinkShape2 extends Shape
{
public LinkShape2(Scene sc)
{
super(sc);
int col1 = 0xFFFF00;
int col2 = 0x0000FF;
Shape s;
s = new LinkShape2Corner(sc, col1);
addShape(s);
s = new LinkShape2Corner(sc, col2);
s.trans.rotateY(3.1415926*0.5);
addShape(s);
s = new LinkShape2Corner(sc, col1);
s.trans.rotateY(3.1415926*1.0);
addShape(s);
s = new LinkShape2Corner(sc, col2);
s.trans.rotateY(3.1415926*1.5);
addShape(s);
s = new LinkShape2Corner(sc, col2);
s.trans.rotateX(3.1415926*0.5);
addShape(s);
s = new LinkShape2Corner(sc, col1);
s.trans.rotateX(3.1415926*0.5);
s.trans.rotateY(3.1415926*0.5);
addShape(s);
s = new LinkShape2Corner(sc, col2);
s.trans.rotateX(3.1415926*0.5);
s.trans.rotateY(3.1415926*1.0);
addShape(s);
s = new LinkShape2Corner(sc, col1);
s.trans.rotateX(3.1415926*0.5);
s.trans.rotateY(3.1415926*1.5);
addShape(s);
}
}
//---- LinkShape3
class LinkShape3 extends Shape
{
public LinkShape3(Scene sc)
{
super(sc);
Shape s;
for(int i=0; i<8; i++)
{
s = new Cube(sc, 0xFF0000 + i*0x001F1F);
s.trans.scale(0.2, 0.4, 0.2);
s.trans.translate(-0.8, 0, 0);
s.trans.rotateY(i*2*3.1415926/8);
addShape(s);
}
}
}
//---- LinkShape4
class LinkShape4 extends Shape
{
public LinkShape4(Scene sc)
{
super(sc);
Shape s;
for(int i=0; i<8; i++)
{
int b0 = (i )&1;
int b1 = (i>>1)&1;
int b2 = (i>>2)&1;
s = new Cube(sc, b0*0xFF0000 + b1*0x00FF00 + b2*0x0000FF);
s.trans.scale(0.4, 0.4, 0.4);
s.trans.translate(b0*1.2-0.6, b1*1.2-0.6, b2*1.2-0.6);
addShape(s);
}
}
}
//---- LinkShape5
class LinkShape5 extends Shape
{
public LinkShape5(Scene sc)
{
super(sc);
Shape s;
for(int i=0; i<12; i++)
{
s = new Cube(sc, 0x660099 + i*0x001100);
s.trans.scale(0.2, 0.2, 0.2);
s.trans.translate(-0.8, (i-6)*0.14, 0);
s.trans.rotateY(i*2*3.1415926/7);
addShape(s);
}
}
}
//---- LinkShape6
class LinkShape6 extends Shape
{
public LinkShape6(Scene sc)
{
super(sc);
Shape s;
for(int i=0; i<64; i+=5)
{
s = new LinkShape1(sc);//Cube(sc, 0x660099 + i*0x001100);
s.trans.rotateZ( i*3.14159/52);
s.trans.rotateX( i*3.14159/41);
double scale = 0.9+0.6*Math.sin(i*3.14159/7);
s.trans.scale(scale, scale, scale);
s.trans.translate(3+2*Math.sin(i*3.14159/12), 0*(i-32.0)/32.0, 0);
s.trans.rotateY( i*3.14159/37);
addShape(s);
}
}
}
//---- MainShape
class MainShape extends Shape
{
Shape[] st;
boolean reflections = false;
boolean rocky_floor = false;
public MainShape(Scene sc)
{
super(sc);
Shape s;
int i, j;
//- Reflected pillars
if(reflections)
{
for(i=0; i<5; i++)
{
s = new Pillar(sc);
s.trans.translate(-4.5, -4.4, 0.0);
s.trans.rotateY(3.14159*2.0*i/5.0);
addShape(s);
}
}
//- Floor
int col1 = 0xFFFFFF;
int col2 = 0x000000;
if(reflections) { col1 += 0x80000000; }
if(reflections) { col2 += 0x80000000; }
for(j=0; j<2; j++) for(i=0; i<2; i++)
{
if(rocky_floor)
{
s = new LinkShape6(sc);//Checks(sc, col1, col2);
s.trans.scale(1, 0.3, 1);
s.trans.translate(8*i-4, -2.0, 8*j-4);
addShape(s);
}
s = new Checks(sc, col1, col2);
s.trans.scale(2, 1, 2);
s.trans.translate(8*i-4, -2.2, 8*j-4);
addShape(s);
}
//- Pillars with things on them
st = new Shape[5];
st[0] = new LinkShape1(sc);
st[1] = new LinkShape2(sc);
st[2] = new LinkShape3(sc);
st[3] = new LinkShape4(sc);
st[4] = new LinkShape5(sc);
for(i=0; i<5; i++)
{
s = new Pillar(sc);
s.trans.translate(-4.5, 0.0, 0.0);
s.trans.rotateY(3.14159*2.0*i/5.0);
addShape(s);
st[i].trans.scale(0.5, 0.5, 0.5);
st[i].trans.translate(-4.5, 0.0, 0.0);
st[i].trans.rotateY(3.14159*2.0*i/5.0);
st[i].trans.translate(0.0, 2.95, 0.0);
addShape(st[i]);
}
}
int frameno = 0;
public void render()
{
int i;
double[] scale = {1, 1, 1, 1, 1};
i = (frameno / 25)%5;
scale[i] = 1 + Math.exp(-(frameno%25)*0.1)*Math.sin(frameno*3.14159/5);
frameno ++;
for(i=0; i<5; i++)
{
st[i].trans.identity();
if(i != 0) st[i].trans.rotateX(scene.time * 0.18428);
if(i != 1) st[i].trans.rotateY(scene.time * 0.38291);
if(i != 2) st[i].trans.rotateZ(scene.time * 0.29219);
if(i != 3) st[i].trans.rotateY(scene.time * 0.50291);
if(i != 4) st[i].trans.rotateX(scene.time * 0.18428);
st[i].trans.scale(1, scale[i], 1);
st[i].trans.scale(0.5, 0.5, 0.5);
st[i].trans.translate(-4.5, 0.0, 0.0);
st[i].trans.rotateY(3.14159*2.0*i/5.0);
st[i].trans.translate(0.0, 2.85, 0.0);
}
super.render();
}
}
//---- MyScene
class MyScene extends Scene
{
Shape s;
Transform t;
double rx=-0.6, ry=0, rz=0;
public MyScene()
{
// System.out.println("Creating MyScene");
s = new MainShape(this);
addShape(s);
}
public void render()
{
t = new Transform();
rx = -0.45 + 0.15 * Math.sin(time*3.14159/7.391);
ry = 0.257 * time;
rz = 0.157 * time;
/*
t.rotateX(rx);
t.rotateY(ry);
t.rotateZ(rz);
t.rotateX(rx-ry);
t.rotateZ(rz-rx);
t.rotateX(3.1415926*0.5);
*/
t.rotateY(ry);
t.rotateX(rx);
s.setTransform(t);
super.render();
}
}
//---- Applet ----------------------------------------------------------------//
public class Site3D extends tinyptc
{
MyScene scene;
public void main(int width,int height)
{
int size = width * height;
int buf[] = new int[size];
scene = new MyScene();
scene.setBuffer(buf, width, height);
while (true)
{
scene.render();
update(buf);
}
}
int mouse_x = 0, mouse_y = 0;
int mouse_oldx = 0, mouse_oldy = 0;
boolean mouse_drag = true;
public boolean mouseDown(Event evt, int x, int y)
{
mouse_oldx = x;
mouse_oldy = y;
mouse_x = x;
mouse_y = y;
mouse_drag = true;
return true;
}
public boolean mouseDrag(Event e, int x, int y)
{
scene.ry += (x-mouse_x)*0.01;
scene.rx -= (y-mouse_y)*0.01;
if(scene.rx > -0.1) scene.rx = -0.1;
if(scene.rx < -1.2) scene.rx = -1.2;
mouse_x = x;
mouse_y = y;
return true;
}
public boolean mouseUp(Event evt, int x, int y)
{
mouse_drag = false;
return true;
}
}
class Site3D123 extends java.applet.Applet implements Runnable
{
//- Data
Thread runThread = null;
static int imw = 320, imh = 240;
Image im = null;
Graphics img = null;
int[][] buffer;
MyScene myScene;
//- Main code
public void init()
{
System.out.println("LKS 3D Site v0.01");
myScene = new MyScene();
}
public void start()
{
if(runThread == null)
{
runThread = new Thread(this);
runThread.start();
}
}
public void stop()
{
if(runThread != null)
{
runThread.stop();
runThread = null;
}
}
public void run()
{
imw = size().width;
imh = size().height;
im = createImage(imw, imh);
img = im.getGraphics();
img.setColor(Color.black);
img.fillRect(0, 0, imw, imh);
// myScene.setBuffer(img, imw, imh);
while(true)
{
repaint();
try { runThread.sleep(10); } catch (InterruptedException e) { return; }
}
}
public void update(Graphics g)
{
paint(g);
}
int k = 0;
public void paint(Graphics g)
{
if(im != null)
{
img.setColor(Color.black);
img.fillRect(0, 0, imw, imh);
myScene.render();
g.drawImage(im, 0, 0, this);
g.setColor((k++&1) == 0 ? Color.blue : Color.yellow);
g.fillRect(0, 0, 10, 10);
}
}
int mouse_x = 0, mouse_y = 0;
int mouse_oldx = 0, mouse_oldy = 0;
boolean mouse_drag = true;
public boolean mouseDown(Event evt, int x, int y)
{
mouse_oldx = x;
mouse_oldy = y;
mouse_x = x;
mouse_y = y;
mouse_drag = true;
return true;
}
public boolean mouseDrag(Event e, int x, int y)
{
mouse_x = x;
mouse_y = y;
repaint();
return true;
}
public boolean mouseUp(Event evt, int x, int y)
{
mouse_drag = false;
return true;
}
}