House.java

java · 940 lines · part of Unfolded Panorama · raw

//

import java.awt.*;
import java.applet.*;
import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Event;
import java.awt.Image;
import java.awt.Font;



//---- Z3D_Scene -------------------------------------------------------------//

class Z3D_Scene
{
  //- Screen data

  int buf[];
  int w, h;
  
  int clip_x1, clip_y1, clip_x2, clip_y2;
  int cx, cy;
  
  float scale;

  //- Render options

  boolean wireframe = false;
  
  boolean wireframe_changed = false;
  boolean wireframe_new = false;

  //- Traingle data
  
  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;

  //- ZN Logo (210x18)
  
  int[] zn_add;
  int[] zn_mul;
  
  //- Orientation

  float rx=0, ry=0, drx=0, dry=0;
  boolean rchanged = true;

  //- 3D Object
  
  int[][] face;
  float[][] point;

  int[] factex;
  int[][] tex;

  float[][] tpoint;
  float[][] spoint;
  
  int numPoints, numFaces;
  


  //---- Scene

  public Z3D_Scene(Applet applet, int[] buf, int w, int h)
  {
    this.w = w;
    this.h = h;
    this.buf = buf;

    clip_x1 = 0;
    clip_y1 = 0;
    clip_x2 = w;
    clip_y2 = h;
    
    cx = w >> 1;
    cy = h >> 1;
    
    scale = w*0.6f;

    //- Create object

    //  Basic object

    point = new float[8][5];
    face = new int[12][4];
    
    numPoints = 8;
    numFaces = 6;
    
    point[0][0] =  1; point[0][1] =  1; point[0][2] =  1;   point[0][3] = 0; point[0][4] = 1; // u & v not done yet!
    point[1][0] =  1; point[1][1] =  1; point[1][2] = -1;   point[1][3] = 0; point[1][4] = 0;
    point[2][0] = -1; point[2][1] =  1; point[2][2] = -1;   point[2][3] = 0; point[2][4] = 0;
    point[3][0] = -1; point[3][1] =  1; point[3][2] =  1;   point[3][3] = 0; point[3][4] = 0;
    point[4][0] =  1; point[4][1] = -1; point[4][2] =  1;   point[4][3] = 0; point[4][4] = 0;
    point[5][0] =  1; point[5][1] = -1; point[5][2] = -1;   point[5][3] = 0; point[5][4] = 0;
    point[6][0] = -1; point[6][1] = -1; point[6][2] = -1;   point[6][3] = 0; point[6][4] = 0;
    point[7][0] = -1; point[7][1] = -1; point[7][2] =  1;   point[7][3] = 0; point[7][4] = 0;
    
    face[0][0] = 3; face[0][1] = 0; face[0][2] = 1; face[0][3] = 2; // 0
    face[1][0] = 2; face[1][1] = 1; face[1][2] = 5; face[1][3] = 6; // 1
    face[2][0] = 3; face[2][1] = 2; face[2][2] = 6; face[2][3] = 7; // 2
    face[3][0] = 6; face[3][1] = 5; face[3][2] = 4; face[3][3] = 7; // 3
    face[4][0] = 0; face[4][1] = 3; face[4][2] = 7; face[4][3] = 4; // 4
    face[5][0] = 1; face[5][1] = 0; face[5][2] = 4; face[5][3] = 5; // 5

    //  Load textures
    
    tex = new int[6][256*256];
    
    int i, j, k;

    for(k=0; k<6; k++)
      for(j=0; j<256; j++)
        for(i=0; i<256; i++)
          tex[k][(j<<8)+i] = (i^j) << (k*2);

    tex[0] = getPixels(applet, "top.jpg", 256, 256);
    tex[1] = getPixels(applet, "front.jpg", 256, 256);
    tex[2] = getPixels(applet, "right.jpg", 256, 256);
    tex[3] = getPixels(applet, "bottom.jpg", 256, 256);
    tex[4] = getPixels(applet, "back.jpg", 256, 256);
    tex[5] = getPixels(applet, "left.jpg", 256, 256);

    //  Working data

    tpoint = new float[8][5];
    spoint = new float[8][5];

    //  ZN Logo

    zn_add = getPixels(applet, "zn_add.jpg", 210, 18);
    zn_mul = getPixels(applet, "zn_mul.jpg", 210, 18);
  }

  //---- getPixels

	private int[] getPixels(Applet applet, String ImageFile, int width, int height)
	{
	  Image TempImage = applet.getImage(applet.getDocumentBase(),ImageFile);
	  
		applet.showStatus("Grabbing Pixels...");
		int TempPixel[]=new int [width*height];

		PixelGrabber pg= new PixelGrabber(TempImage,0,0,width,height,TempPixel,0,width);
		try
		{
			pg.grabPixels();
		}
		catch (InterruptedException e)
		{
		}

		return TempPixel;
	}

  //---- setRotation

  public void addRotation(float rx, float ry)
  {
    drx -= rx*0.01;
    dry += ry*0.01;
    rchanged = true;
  }

  //---- setWireframe

  public void setWireframe(boolean wf)
  {
    wireframe_new = wf;
    wireframe_changed = true;
  }

  //---- render

  public void render()
  {
    if(rchanged)
    {
      rx += drx;
      ry += dry;
      drx = dry = 0;
      rchanged = false;
    }
    else
    {
      return;
    }

    if(wireframe_changed)
    {
      wireframe_changed = false;
      wireframe = wireframe_new;
    }

    //- Clear buffer

    idx3d_Math.clearBuffer(buf, 0x336699);
    
    //- Render object
    
    int i, j;

//    rx = 0.0f;
//    ry += 0.01f;
    
    //  Transform

    float x, y, z;
    idx3d_Matrix m;
    
    m = new idx3d_Matrix();
    m.rotateSelf(rx, 0, 0);
    m.rotateSelf(0, ry, 0);
//    m.shift(0, 0, 2);

    //  Render triangles
    
    scale = w*1/8;
    float hp = 3.14159f * 0.5f;

    //  front    

    transformPoints(m);

    clip_x1 = w*1/4; clip_y1 = h*1/3;
    clip_x2 = w*2/4; clip_y2 = h*2/3;
    cx = (clip_x1+clip_x2)>>1;
    cy = (clip_y1+clip_y2)>>1;

    for(i=0; i<numFaces; i++) drawSquare(i);

    //  top

    m.rotate(-hp, 0, 0);
    transformPoints(m);

    clip_x1 = w*1/4; clip_y1 = h*0/3;
    clip_x2 = w*2/4; clip_y2 = h*1/3;
    cx = (clip_x1+clip_x2)>>1;
    cy = (clip_y1+clip_y2)>>1;

    for(i=0; i<numFaces; i++) drawSquare(i);

    //  bottom

    m.rotate(hp, 0, 0);
    m.rotate(hp, 0, 0);
    transformPoints(m);

    clip_x1 = w*1/4; clip_y1 = h*2/3;
    clip_x2 = w*2/4; clip_y2 = h*3/3;
    cx = (clip_x1+clip_x2)>>1;
    cy = (clip_y1+clip_y2)>>1;

    for(i=0; i<numFaces; i++) drawSquare(i);

    //  left

    m.rotate(-hp, 0, 0);
    m.rotate(0, hp, 0);
    transformPoints(m);

    clip_x1 = w*0/4; clip_y1 = h*1/3;
    clip_x2 = w*1/4; clip_y2 = h*2/3;
    cx = (clip_x1+clip_x2)>>1;
    cy = (clip_y1+clip_y2)>>1;

    for(i=0; i<numFaces; i++) drawSquare(i);

    //  back

    m.rotate(0, hp, 0);
    transformPoints(m);

    clip_x1 = w*3/4; clip_y1 = h*1/3;
    clip_x2 = w*4/4; clip_y2 = h*2/3;
    cx = (clip_x1+clip_x2)>>1;
    cy = (clip_y1+clip_y2)>>1;

    for(i=0; i<numFaces; i++) drawSquare(i);

    //  right

    m.rotate(0, hp, 0);
    transformPoints(m);

    clip_x1 = w*2/4; clip_y1 = h*1/3;
    clip_x2 = w*3/4; clip_y2 = h*2/3;
    cx = (clip_x1+clip_x2)>>1;
    cy = (clip_y1+clip_y2)>>1;

    for(i=0; i<numFaces; i++) drawSquare(i);

    //- Put ZN logo
    
    int o1 = 0;
    int o2 = w*(h-18);
    int r, g, b, zm, za;

    for(j=0; j<18; j++)
    {
      for(i=0; i<210; i++)
      {
        r = (buf[o2] >> 16)&255;
        g = (buf[o2] >> 8 )&255;
        b = (buf[o2]      )&255;
        
        zm = zn_mul[o1] & 255;
        za = zn_add[o1] & 255;
        
        r = ((r * zm)>>8);
        g = ((g * zm)>>8);
        b = ((b * zm)>>8);
        
        r = ((za>>8) + (r)*(255-za))>>8;
        g = ((za>>8) + (g)*(255-za))>>8;
        b = ((za>>8) + (b)*(255-za))>>8;
        
        if(r > 255) r = 255;
        if(g > 255) g = 255;
        if(b > 255) b = 255;

        if(r < 0) r = 0;
        if(g < 0) g = 0;
        if(b < 0) b = 0;

        buf[o2] = (r<<16)+(g<<8)+(b) + zn_add[o1];

        o1 ++;
        o2 ++;
      }
      
      o2 += w-210;
    }
    
  }  

  void transformPoints(idx3d_Matrix m)
  {
    int i;
    float x, y, z;

    for(i=0; i<numPoints; i++)
    {
      x = point[i][0];
      y = point[i][1];
      z = point[i][2];

  		tpoint[i][0] = x*m.m00 + y*m.m01 + z*m.m02+ m.m03;
  		tpoint[i][1] = x*m.m10 + y*m.m11 + z*m.m12+ m.m13;
    	tpoint[i][2] = x*m.m20 + y*m.m21 + z*m.m22+ m.m23;
	  }
  }

  void renderQuad(int texnum, float[] p1, float[] p2, float[] p3, float[] p4)
  {
    tri_x1 = p1[0];
    tri_y1 = p1[1];
    tri_z1 = p1[2];
    tri_u1 = p1[3];
    tri_v1 = p1[4];
      
    tri_x2 = p2[0];
    tri_y2 = p2[1];
    tri_z2 = p2[2];
    tri_u2 = p2[3];
    tri_v2 = p2[4];
      
    tri_x3 = p3[0];
    tri_y3 = p3[1];
    tri_z3 = p3[2];
    tri_u3 = p3[3];
    tri_v3 = p3[4];
      
    tri_persp(texnum);

    tri_x1 = p3[0];
    tri_y1 = p3[1];
    tri_z1 = p3[2];
    tri_u1 = p3[3];
    tri_v1 = p3[4];
    
    tri_x2 = p4[0];
    tri_y2 = p4[1];
    tri_z2 = p4[2];
    tri_u2 = p4[3];
    tri_v2 = p4[4];
    
    tri_x3 = p1[0];
    tri_y3 = p1[1];
    tri_z3 = p1[2];
    tri_u3 = p1[3];
    tri_v3 = p1[4];
    
    tri_persp(texnum);
  }

  void interpolate(float[] p1, float[] p2, float a, float[] result)
  {
    for(int i=0; i<5; i++)
    {
      result[i] = p1[i] * (1.0f-a) + p2[i] * a;
    }
  }

  void drawSquare(int index)
  {
    float[] p1 = tpoint[face[index][0]];
    float[] p2 = tpoint[face[index][1]];
    float[] p3 = tpoint[face[index][2]];
    float[] p4 = tpoint[face[index][3]];
    
    float[] ip1 = new float[5];
    float[] ip2 = new float[5];
    float[] ip3 = new float[5];
    float[] ip4 = new float[5];
    
    float[] tp1 = new float[5];
    float[] tp2 = new float[5];

    //- Texture co-ords
    
    p1[3] =   0; p1[4] =   0;
    p2[3] = 256; p2[4] =   0;
    p3[3] = 256; p3[4] = 256;
    p4[3] =   0; p4[4] = 256;

    //- Subdivide into 4x4
    
    int i, j;
    
    for(j=0; j<4; j++)
    {
      for(i=0; i<4; i++)
      {
        //  Calculate square
        
        interpolate(p1, p2, (i)*0.25f, tp1);
        interpolate(p4, p3, (i)*0.25f, tp2);
        interpolate(tp1, tp2, (j)*0.25f, ip1);
        
        interpolate(p1, p2, (i+1)*0.25f, tp1);
        interpolate(p4, p3, (i+1)*0.25f, tp2);
        interpolate(tp1, tp2, j*0.25f, ip2);

        interpolate(p1, p2, (i+1)*0.25f, tp1);
        interpolate(p4, p3, (i+1)*0.25f, tp2);
        interpolate(tp1, tp2, (j+1)*0.25f, ip3);

        interpolate(p1, p2, (i)*0.25f, tp1);
        interpolate(p4, p3, (i)*0.25f, tp2);
        interpolate(tp1, tp2, (j+1)*0.25f, ip4);
        
        //  Screen co-ords
        
        ip1[0] = cx + scale * ip1[0] / ip1[2];
        ip1[1] = cy - scale * ip1[1] / ip1[2];

        ip2[0] = cx + scale * ip2[0] / ip2[2];
        ip2[1] = cy - scale * ip2[1] / ip2[2];

        ip3[0] = cx + scale * ip3[0] / ip3[2];
        ip3[1] = cy - scale * ip3[1] / ip3[2];

        ip4[0] = cx + scale * ip4[0] / ip4[2];
        ip4[1] = cy - scale * ip4[1] / ip4[2];
        
        //  render square

        renderQuad(index, ip1, ip2, ip3, ip4);
      }
    }
  }



  //---- tri_col

  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;
        }
          
      }
    }
    
  }


  //---- tri_tex

  public void tri_tex(int texnum)
  {
    int[] tex = this.tex[texnum];

    float t;
    int x, y;
    
    int x1, x2, y1, y2;

    int o, ti;
    float u1, v1, u2, v2;
    float du, dv;
    
    //  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_x2; tri_x2=tri_x1; tri_x1=t;
      t=tri_y2; tri_y2=tri_y1; tri_y1=t;
      t=tri_u2; tri_u2=tri_u1; tri_u1=t;
      t=tri_v2; tri_v2=tri_v1; tri_v1=t;
    }
    if(tri_y2 > tri_y3)
    {
      t=tri_x3; tri_x3=tri_x2; tri_x2=t;
      t=tri_y3; tri_y3=tri_y2; tri_y2=t;
      t=tri_u3; tri_u3=tri_u2; tri_u2=t;
      t=tri_v3; tri_v3=tri_v2; tri_v2=t;
    }
    if(tri_y1 > tri_y2)
    {
      t=tri_x2; tri_x2=tri_x1; tri_x1=t;
      t=tri_y2; tri_y2=tri_y1; tri_y1=t;
      t=tri_u2; tri_u2=tri_u1; tri_u1=t;
      t=tri_v2; tri_v2=tri_v1; tri_v1=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;
    
    u1 = 0; v1 = 0; u2 = 0; v2 = 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));

          u1 = (tri_u1 + (tri_u3-tri_u1) * (y-tri_y1) / (tri_y3-tri_y1));
          u2 = (tri_u1 + (tri_u2-tri_u1) * (y-tri_y1) / (tri_y2-tri_y1));

          v1 = (tri_v1 + (tri_v3-tri_v1) * (y-tri_y1) / (tri_y3-tri_y1));
          v2 = (tri_v1 + (tri_v2-tri_v1) * (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));

          u1 = (tri_u1 + (tri_u3-tri_u1) * (y-tri_y1) / (tri_y3-tri_y1));
          u2 = (tri_u2 + (tri_u3-tri_u2) * (y-tri_y2) / (tri_y3-tri_y2));

          v1 = (tri_v1 + (tri_v3-tri_v1) * (y-tri_y1) / (tri_y3-tri_y1));
          v2 = (tri_v2 + (tri_v3-tri_v2) * (y-tri_y2) / (tri_y3-tri_y2));
        }
        if(x1 > x2)
        {
          ti = x2; x2 = x1; x1 = ti;
          t  = u2; u2 = u1; u1 = t;
          t  = v2; v2 = v1; v1 = t;
        }
        if(x1 < 0) x1 = 0;
        if(x2 > w) x2 = w;
    
        if(x2 > x1) {
          du = (u2-u1)/(x2-x1);
          dv = (v2-v1)/(x2-x1);
    
          o = y*w + x1;
    
          for(x = x1; x < x2; x ++)
          {
            ti = (((int)v1)<<8) + ((int)u1);
            
            ti = (int)u1;
            ti = (ti<<16)+(ti<<8)+ti;
            buf[o++] = ti;//tex[ti];
            u1 += du;
            v1 += dv;
          }
        }
          
      }
    }
    
  }



  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++)
      {
        buf[o++] = tex[ ( (((int)(v/z))<<8) + ((int)(u/z)) ) & 0xFFFF ];//(((int)u)<<16)+(((int)v)<<8);
        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++)
      {
        buf[o++] = tex[ ( (((int)(v/z))<<8) + ((int)(u/z)) ) & 0xFFFF ];//(((int)u)<<16)+(((int)v)<<8);
        z += dzx;
  			u += dux;
  			v += dvx;
      }
  
      xa += dxa; xb += dxb;
  
      zl += dzy;
      ul += duy;
      vl += dvy;
    }
  
  }


}



//---- House -----------------------------------------------------------------//

public class House extends tinyptc
{
  //- Data

  int rx, ry;

  Z3D_Scene scene;

  //- Mouse data

  int mouse_x = 0, mouse_y = 0;
  int mouse_oldx = 0, mouse_oldy = 0;
  boolean mouse_drag = true;
  int mouse_changex = 0, mouse_changey = 0;



  //- Main code

  public void main(int width, int height)
  {
    int size = width * height;
    int buf[] = new int[size];
    int seed = 0x12345;

    scene = new Z3D_Scene(this, buf, width, height);
    
    while (true)
    {
      scene.addRotation(mouse_changey, mouse_changex);
      mouse_changex = 0;
      mouse_changey = 0;
      scene.render();
      update(buf);

//      while(mouse_changex == 0 && mouse_changey == 0);
    }
  }






  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;

    mouse_changex += mouse_x-mouse_oldx;    
    mouse_changey += mouse_y-mouse_oldy;    

    mouse_oldx = x;
    mouse_oldy = y;

    return true;
  }



  public boolean mouseUp(Event evt, int x, int y)
  {
    mouse_drag = false;

    return true;
  }
  

}