Test Java cube rendering 2 December 2001
This is a barebones renderer for one object, with a software solid triangle rasteriser
HouseScreen Buffer
The screen buffer is provided by tinyptc. It is an int[] linear RGB pixel array.
Matrices & Vectors
These come from IDX Graphics 3D engine.
Triangle Rendering
I render the triangles like this:
//---- tri_col
// Arguments are stored in 'this' // this.tri_x1 // this.tri_y1 // this.tri_x2 // this.tri_y2 // this.tri_x3 // this.tri_y3
public void tri_col(int col) {
float t;
int x, y, y1, y2, x1, x2, o, ti;
float c1, c2;
float dc;
// Don't draw if backfacing
if((tri_x2-tri_x1)*(tri_y3-tri_y1) > (tri_x3-tri_x1)*(tri_y2-tri_y1)) return;
// Sort points
if(tri_y1 > tri_y2) { t=tri_y2; tri_y2=tri_y1; tri_y1=t; t=tri_x2; tri_x2=tri_x1; tri_x1=t; }
if(tri_y2 > tri_y3) { t=tri_y3; tri_y3=tri_y2; tri_y2=t; t=tri_x3; tri_x3=tri_x2; tri_x2=t; }
if(tri_y1 > tri_y2) { t=tri_y2; tri_y2=tri_y1; tri_y1=t; t=tri_x2; tri_x2=tri_x1; tri_x1=t; }
// Clip top point to screen and pixel
y1 = (int)tri_y1; if(y1>=h) return; if(y1<0) y1 = 0;
y2 = (int)tri_y3; if(y2<0) return; if(y2>h) y2 = h;
c1=0; c2=0;
for(y=y1-1; y<y2+1; y++)
{
if(y >= tri_y1 && y < tri_y3)
{
if(y >= tri_y1 && y < tri_y2)
{
x1 = (int)(tri_x1 + (tri_x3-tri_x1) * (y-tri_y1) / (tri_y3-tri_y1));
x2 = (int)(tri_x1 + (tri_x2-tri_x1) * (y-tri_y1) / (tri_y2-tri_y1));
}
else
{
x1 = (int)(tri_x1 + (tri_x3-tri_x1) * (y-tri_y1) / (tri_y3-tri_y1));
x2 = (int)(tri_x2 + (tri_x3-tri_x2) * (y-tri_y2) / (tri_y3-tri_y2));
}
if(x1 > x2)
{
ti = x2; x2 = x1; x1 = ti;
t = c2; c2 = c1; c1 = t;
}
if(x1 < 0) x1 = 0;
if(x2 > w) x2 = w;
if(x2 > x1) {
dc = (c2-c1)/(x2-x1);
o = y*w + x1;
for(x = x1; x < x2; x ++) buf[o++] = col;
}
}
}
}
Source 12 files
- Example1.html HTML · 19 lines
- House.java Java · 326 lines
- idx3d_Math.java Java · 193 lines
- idx3d_Matrix.java Java · 324 lines
- idx3d_Vector.java Java · 186 lines
- tinyptc.java Java · 137 lines
- applet/Example1.html HTML · 19 lines
- source/House.java Java · 326 lines
- source/idx3d_Math.java Java · 193 lines
- source/idx3d_Matrix.java Java · 324 lines
- source/idx3d_Vector.java Java · 186 lines
- source/tinyptc.java Java · 137 lines
Panorama viewer 3 December 2001
Placing the viewpoint inside the cube and making the faces of the cube textured
HousePerspective correct textured triangles
This is my routine for perspective texturemapping the triangles:
//---- tri_persp
// Array of flattened 256x256 32-bit RGB texture bitmaps // In the case of Lewpen.com panorama viewer, the dimensions are tex[6][65536]
int[][] tex;
// Arguments for tri_persp - co-ordinates and texture co-ords of each corner
float tri_x1, tri_y1, tri_z1, tri_u1, tri_v1; float tri_x2, tri_y2, tri_z2, tri_u2, tri_v2; float tri_x3, tri_y3, tri_z3, tri_u3, tri_v3;
public void tri_persp(int texnum) { if(tri_z1 < 0) return; if(tri_z2 < 0) return; if(tri_z3 < 0) return;
int[] tex = this.tex[texnum];
tri_u1 = 256-tri_u1;
tri_u2 = 256-tri_u2;
tri_u3 = 256-tri_u3;
int i, j;
// Don't draw if backfacing
if((tri_x2-tri_x1)*(tri_y3-tri_y1) < (tri_x3-tri_x1)*(tri_y2-tri_y1)) return;
//- Sort points
float t;
if(tri_y2 < tri_y1)
{
t = tri_x1; tri_x1 = tri_x2; tri_x2 = t;
t = tri_y1; tri_y1 = tri_y2; tri_y2 = t;
t = tri_z1; tri_z1 = tri_z2; tri_z2 = t;
t = tri_u1; tri_u1 = tri_u2; tri_u2 = t;
t = tri_v1; tri_v1 = tri_v2; tri_v2 = t;
}
if(tri_y3 < tri_y2)
{
t = tri_x2; tri_x2 = tri_x3; tri_x3 = t;
t = tri_y2; tri_y2 = tri_y3; tri_y3 = t;
t = tri_z2; tri_z2 = tri_z3; tri_z3 = t;
t = tri_u2; tri_u2 = tri_u3; tri_u3 = t;
t = tri_v2; tri_v2 = tri_v3; tri_v3 = t;
}
if(tri_y2 < tri_y1)
{
t = tri_x1; tri_x1 = tri_x2; tri_x2 = t;
t = tri_y1; tri_y1 = tri_y2; tri_y2 = t;
t = tri_z1; tri_z1 = tri_z2; tri_z2 = t;
t = tri_u1; tri_u1 = tri_u2; tri_u2 = t;
t = tri_v1; tri_v1 = tri_v2; tri_v2 = t;
}
//- Divide by z to do perspective correction
tri_u1 /= tri_z1; tri_u2 /= tri_z2; tri_u3 /= tri_z3;
tri_v1 /= tri_z1; tri_v2 /= tri_z2; tri_v3 /= tri_z3;
tri_z1 = 1.0f/tri_z1; tri_z2 = 1.0f/tri_z2; tri_z3 = 1.0f/tri_z3;
//- Work out deltas along edges
float dx12 = (tri_x2-tri_x1)/(tri_y2-tri_y1), dx23 = (tri_x3-tri_x2)/(tri_y3-tri_y2), dx13 = (tri_x3-tri_x1)/(tri_y3-tri_y1);
float dz12 = (tri_z2-tri_z1)/(tri_y2-tri_y1), dz23 = (tri_z3-tri_z2)/(tri_y3-tri_y2), dz13 = (tri_z3-tri_z1)/(tri_y3-tri_y1);
float du12 = (tri_u2-tri_u1)/(tri_y2-tri_y1), du23 = (tri_u3-tri_u2)/(tri_y3-tri_y2), du13 = (tri_u3-tri_u1)/(tri_y3-tri_y1);
float dv12 = (tri_v2-tri_v1)/(tri_y2-tri_y1), dv23 = (tri_v3-tri_v2)/(tri_y3-tri_y2), dv13 = (tri_v3-tri_v1)/(tri_y3-tri_y1);
//- Round to pixel and clip to top & bottom of screen
int y1 = (int)tri_y1; if(y1 < tri_y1) y1++;
int y2 = (int)tri_y2; if(y2 < tri_y2) y2++;
int y3 = (int)tri_y3; if(y3 < tri_y3) y3++;
if(y1 < clip_y1) y1 = clip_y1;
if(y2 < clip_y1) y2 = clip_y1;
if(y3 < clip_y1) y3 = clip_y1;
if(y1 > clip_y2) y1 = clip_y2;
if(y2 > clip_y2) y2 = clip_y2;
if(y3 > clip_y2) y3 = clip_y2;
if(y3 <= y1) return;
//- Calculate horizontal and vertical deltas for parameters
float d = (tri_x3-tri_x1)*(tri_y2-tri_y1) - (tri_y3-tri_y1)*(tri_x2-tri_x1);
float dzx = ( (tri_y2-tri_y1)*(tri_z3-tri_z1) + (tri_y1-tri_y3)*(tri_z2-tri_z1) ) / d;
float dzy = ( (tri_x1-tri_x2)*(tri_z3-tri_z1) + (tri_x3-tri_x1)*(tri_z2-tri_z1) ) / d;
float dux = ( (tri_y2-tri_y1)*(tri_u3-tri_u1) + (tri_y1-tri_y3)*(tri_u2-tri_u1) ) / d;
float duy = ( (tri_x1-tri_x2)*(tri_u3-tri_u1) + (tri_x3-tri_x1)*(tri_u2-tri_u1) ) / d;
float dvx = ( (tri_y2-tri_y1)*(tri_v3-tri_v1) + (tri_y1-tri_y3)*(tri_v2-tri_v1) ) / d;
float dvy = ( (tri_x1-tri_x2)*(tri_v3-tri_v1) + (tri_x3-tri_x1)*(tri_v2-tri_v1) ) / d;
//- See if we need to flip triangle horizontally
boolean side13onleft = dx13 < dx12;
//- Draw top of triangle
float xa, xb, dxa, dxb;
if(side13onleft)
{
xa = tri_x1 + dx13 * (y1-tri_y1);
xb = tri_x1 + dx12 * (y1-tri_y1);
dxa = dx13;
dxb = dx12;
}
else
{
xa = tri_x1 + dx12 * (y1-tri_y1);
xb = tri_x1 + dx13 * (y1-tri_y1);
dxa = dx12;
dxb = dx13;
}
float zl = tri_z1 - tri_x1*dzx + (y1-tri_y1)*dzy;
float ul = tri_u1 - tri_x1*dux + (y1-tri_y1)*duy;
float vl = tri_v1 - tri_x1*dvx + (y1-tri_y1)*dvy;
for(j=y1; j<y2; j++)
{
int xai = (int)xa; if(xai < xa) xai++;
int xbi = (int)xb; if(xbi < xb) xbi++;
if(xai < clip_x1) xai = clip_x1;
if(xbi < clip_x1) xbi = clip_x1;
if(xai > clip_x2) xai = clip_x2;
if(xbi > clip_x2) xbi = clip_x2;
float z = zl + xai*dzx;
float u = ul + xai*dux;
float v = vl + xai*dvx;
int o = j*w+xai;
for(i=xai; i<xbi; i++)
{
// Perspective per-pixel divide by Z happens here
buf[o++] = tex[ ( (((int)(v/z))<<8) + ((int)(u/z)) ) & 0xFFFF ];
// use (((int)u)<<16)+(((int)v)<<8) for linear.
z += dzx;
u += dux;
v += dvx;
}
xa += dxa; xb += dxb;
zl += dzy;
ul += duy;
vl += dvy;
}
//- Draw bottom of triangle
if(side13onleft)
{
xb = tri_x2 + dx23 * (y2-tri_y2);
dxb = dx23;
}
else
{
xa = tri_x2 + dx23 * (y2-tri_y2);
dxa = dx23;
}
for(j=y2; j<y3; j++)
{
int xai = (int)xa; if(xai < xa) xai++;
int xbi = (int)xb; if(xbi < xb) xbi++;
if(xai < clip_x1) xai = clip_x1;
if(xbi < clip_x1) xbi = clip_x1;
if(xai > clip_x2) xai = clip_x2;
if(xbi > clip_x2) xbi = clip_x2;
float z = zl + xai*dzx;
float u = ul + xai*dux;
float v = vl + xai*dvx;
int o = j*w+xai;
for(i=xai; i<xbi; i++)
{
// Perspective per-pixel divide by Z happens here
buf[o++] = tex[ ( (((int)(v/z))<<8) + ((int)(u/z)) ) & 0xFFFF ];
// use (((int)u)<<16)+(((int)v)<<8) for linear.
z += dzx;
u += dux;
v += dvx;
}
xa += dxa; xb += dxb;
zl += dzy;
ul += duy;
vl += dvy;
}
}
Source 7 files
- index.html HTML · 76 lines
- panorama.html HTML · 76 lines
- source/House.java Java · 882 lines
- source/idx3d_Math.java Java · 193 lines
- source/idx3d_Matrix.java Java · 324 lines
- source/idx3d_Vector.java Java · 186 lines
- source/tinyptc.java Java · 137 lines
Unfolded panorama 3 December 2001
Instead of rotating the cube the texture can be warped and the cube and view point can remain static
HousePanorama viewer - click and drag to rotate the texture
Source 12 files
- Example1.html HTML · 19 lines
- House.html HTML · 19 lines
- House.java Java · 940 lines
- idx3d_Math.java Java · 193 lines
- idx3d_Matrix.java Java · 324 lines
- idx3d_Vector.java Java · 186 lines
- tinyptc.java Java · 137 lines
- source/House.java Java · 940 lines
- source/idx3d_Math.java Java · 193 lines
- source/idx3d_Matrix.java Java · 324 lines
- source/idx3d_Vector.java Java · 186 lines
- source/tinyptc.java Java · 137 lines