Panorama Viewer
Placing the viewpoint inside the cube and making the faces of the cube textured
Java Dec 2001
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