home games dev
Lewpen.com»Research & Development»3D Graphics»Java 3D Engine»Nice 3D Engine

Nice 3D Engine

3D Engine with scene graph and cartoon rendering style

/ Source / RenderBuffer.java

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


}

Comments

Article
Related Articles

Using a BSP tree for reflections and object intersection

Sponsored Links

Toys & Games:

Doggie Doo
Nerf Vortex
Monster High
Lagoona Hydration Station
Milky Bunny
Moshling Tree House
Lego Ninja Go Fire Temple
Fireman Sam Pontypandy Rescue
Rock Elmo
Star Wars Ultimate Force Lightsaber

Games

The Dodge Game
Flatspace

2-Player Games:

Quake 2D
Meteora

Puzzle Games:

Mini Tetris
Sudoku Solver

Development

3D Graphics:

3D Graphics Articles
WebGL Examples
Flash 3D Engine
Java 3D Engine

Development:

Programming Articles
Animation Demos
Game Development Examples

Links

iBuddy Social Network
Local Legends Football
PHP Charts & Graphs
CubeLogix Studios