RenderBuffer.java

java · 443 lines · part of 0001 · raw


public class RenderBuffer
{


  //---- DATA

  //---- Buffer data

  int w, h, size;
  int[] buf;
  int[] zbuf;

  int clip_x1, clip_y1;
  int clip_x2, clip_y2;

  int cx, cy;

  //---- Triangle data

  float tri_x1, tri_y1, tri_z1;
  float tri_x2, tri_y2, tri_z2;
  float tri_x3, tri_y3, tri_z3;



  //---- CODE



  //---- RenderBuffer

  public RenderBuffer(int width, int height)
  {
    w = width;
    h = height;
    
    cx = w >> 1;
    cy = h >> 1;
    
    clip_x1 = 0; clip_y1 = 0;
    clip_x2 = w; clip_y2 = h;
    
    size = w*h;

    buf = new int[size];
    zbuf = new int[size];
    
    clear(0);
    clearZBuf();
  }



  //---- clear
  
  public void clear(int col)
  {
    for(int i=0; i<size; i++) buf[i] = col;
  }



  //---- clearZBuf
  
  public void clearZBuf()
  {
    for(int i=0; i<size; i++) zbuf[i] = 0;
  }



  //---- copy
  
  public void copy(RenderBuffer src)
  {
    int[] srcbuf = src.buf;
    
    for(int i=0; i<size; i++) buf[i] = srcbuf[i];
  }



  //---- layer
  
  public void layer(RenderBuffer src)
  {
    int[] srcbuf = src.buf;

    for(int i=0; i<size; i++) if((srcbuf[i] & 0xFF000000) != 0) buf[i] = srcbuf[i];
  }



  //---- box
  
  public void box(double x1, double y1, double x2, double y2, int col)
  {
    int xx1 = (int)x1, yy1 = (int)y1, xx2 = (int)x2, yy2 = (int)y2;
    
    if(xx1 < clip_x1) xx1 = clip_x1;
    if(xx2 > clip_x2) xx2 = clip_x2;

    if(yy1 < clip_y1) yy1 = clip_y1;
    if(yy2 > clip_y2) yy2 = clip_y2;

    int i, i1, i2;

    for(int j=yy1; j<yy2; j++)
    {
      i1 = j*w + xx1;
      i2 = j*w + xx2;

      for(i=i1; i<i2; i++) buf[i] = col;
    }
  }



  //---- circle
  
  public void circle(double cx, double cy, double r, int col)
  {
    int y1 = (int)(cy-r-1);
    int y2 = (int)(cy+r+1);

    int i, i1, i2;

    double r2 = r*r;
    double a;

    if(y1 < clip_y1) y1 = clip_y1;
    if(y2 > clip_y2) y2 = clip_y2;
    
    for(int y = y1; y < y2; y ++)
    {
      a = r2 - (cy-y)*(cy-y);
      
      if(a > 0)
      {
        a = Math.sqrt(a);

        i1 = (int)(cx-a);
        i2 = (int)(cx+a);
        
        if(i1 < clip_x1) i1 = clip_x1;
        if(i2 > clip_x2) i2 = clip_x2;
        
        i1 += y*w;
        i2 += y*w;

        for(i=i1; i<i2; i++) buf[i] = col;
      }
    }
  
  }



  //---- xSkewCircle
  
  public void xSkewCircle(double cx, double cy, double r, double xscale, double xskew, int col)
  {
    int y1 = (int)(cy-r-1);
    int y2 = (int)(cy+r+1);

    int i, i1, i2;

    double r2 = r*r;
    double a;

    if(y1 < clip_y1) y1 = clip_y1;
    if(y2 > clip_y2) y2 = clip_y2;
    
    for(int y = y1; y < y2; y ++)
    {
      a = r2 - (cy-y)*(cy-y);
      
      if(a > 0)
      {
        a = xscale * Math.sqrt(a);

        i1 = (int)(cx - a + (cy-y)*xskew);
        i2 = (int)(cx + a + (cy-y)*xskew);
        
        if(i1 < clip_x1) i1 = clip_x1;
        if(i2 > clip_x2) i2 = clip_x2;
        
        i1 += y*w;
        i2 += y*w;

        for(i=i1; i<i2; i++) buf[i] = col;
      }
    }
  }



  //---- alphaPixel
  
  void alphaPixel(int i, int r, int g, int b, int a)
  {
    int c = buf[i];
    
    int rr = (c>>16) & 0xFF;
    int gg = (c>> 8) & 0xFF;
    int bb = (c    ) & 0xFF;
    
    rr = ( rr*(255-a) + r*(a) ) >> 8;
    gg = ( gg*(255-a) + g*(a) ) >> 8;
    bb = ( bb*(255-a) + b*(a) ) >> 8;
    
    buf[i] = 0xFF000000 + (rr << 16) + (gg << 8) + (bb);
  }


  
  //---- hilightEdges

  void hilightEdges(int col)
  {
    int x, y, a;

    for(int i = w*3 + 3; i < size-w*3-3; i++)
    {
/*
      if(zbuf[i] == 0)
      {
        for(y = -w*3; y <= w*3; y+= w) for(x = -3; x <= 3; x++)
        {
          if(zbuf[i+x+y] > 0)
          {
            buf[i] = 0xFFFFFFFF;
            break;
          }
        }
      }
*/

      int dx = zbuf[i-1] - 2*zbuf[i] + zbuf[i+1];
      int dy = zbuf[i-w] - 2*zbuf[i] + zbuf[i+w];

      if(dx < 0) dx =- dx;
      if(dy < 0) dy =- dy;

//      if(dx > 40) buf[i] = col;
//      if(dy > 40) buf[i] = col;

      if(dx > 40 || dy > 40)
      {
        a = dx;
        if(a < dy) a = dy;
        if(a > 255+40) a = 255+40;

        alphaPixel(i, 0, 0, 0, a-40);
      }
    }
  }



  //---- zbufTri
  
  void zbufTri(int col)
  {
    int i, j;
  
    //- 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;
    }
  
    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;
    }
  
    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;
    }
  
    //- 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);
  
    //- 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;
  
    //- See if we need to flip triangle horizontally
  
    boolean side13onleft = dx13 < dx12;
  
    //- Draw top of triangle
  
    float xa, xb, dxa, dxb;
    float za, zb, dza, dzb;
  
    //  Swap over if necessary
  
    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;
    }
  
    int fxa  = (int)(xa * 0x10000), fxb  = (int)(xb * 0x10000);
    int fdxa = (int)(dxa * 0x10000), fdxb = (int)(dxb * 0x10000);
  
    float zl = tri_z1 - tri_x1*dzx + (y1-tri_y1)*dzy;
    
    for(j=y1; j<y2; j++)
    {
    	int xai = (fxa+0xFFFF) >> 16;  //  int xai = (int)xa; if(xai < xa) xai++;
      int xbi = (fxb+0xFFFF) >> 16;  //  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;
  
      int o = j*w + xai;
      int oz = j*w + xai;
  
      for(i=xai; i<xbi; i++)
      {
        int tempz = (int)(z*0x10000);

        if(tempz > zbuf[oz])
        {
          buf[o] = col;
          zbuf[oz] = tempz;
        }

        o ++;
        oz ++;
        z += dzx;
      }
  
      fxa += fdxa; fxb += fdxb;
  
      zl += dzy;
    }
  
    //- Draw bottom of triangle
  
    if(side13onleft)
    {
      xb = tri_x2 + dx23 * (y2-tri_y2);
      dxb = dx23;
      fxb  = (int)(xb *0x10000);
      fdxb = (int)(dxb*0x10000);
    }
    else
    {
      xa = tri_x2 + dx23 * (y2-tri_y2);
      dxa = dx23;
      fxa  = (int)(xa *0x10000);
      fdxa = (int)(dxa*0x10000);
    }

    for(j=y2; j<y3; j++)
    {
      int xai = (fxa+0xFFFF) >> 16;  //  int xai = (int)xa; if(xai < xa) xai++;
      int xbi = (fxb+0xFFFF) >> 16;  //  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;
  
      int o = j*w + xai;
      int oz = j*w + xai;
  
      for(i=xai; i<xbi; i++)
      {
        int tempz = (int)(z*0x10000);

        if(tempz > zbuf[oz])
        {
          buf[o] = col;
          zbuf[oz] = tempz;
        }

        o ++;
        oz ++;
        z += dzx;
      }
  
      fxa += fdxa; fxb += fdxb;
  
      zl += dzy;
    }
  
  }
  


}