Package com.bulletphysics.demos.applet

Source Code of com.bulletphysics.demos.applet.Rasterizer

/*
* Software OpenGL-like 3D renderer (c) 2008 Martin Dvorak <jezek2@advel.cz>
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
*    claim that you wrote the original software. If you use this software
*    in a product, an acknowledgment in the product documentation would be
*    appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
*    misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/

package com.bulletphysics.demos.applet;

import javax.vecmath.Tuple3f;
import javax.vecmath.Tuple4f;

/**
*
* @author jezek2
*/
public class Rasterizer {
 
  public static final int COLOR_BUFFER = 1 << 0;
  public static final int DEPTH_BUFFER = 1 << 1;
 
  private int[] pixels;
  private float[] zbuffer;
  private int width;
  private int height;
 
  private int minY, maxY;
  private Span[] spans;
 
  public void init(int[] pixels, int width, int height) {
    this.pixels = pixels;
    this.width = width;
    this.height = height;
   
    spans = new Span[height];
    for (int i=0; i<height; i++) {
      spans[i] = new Span();
    }
   
    zbuffer = new float[width*height];
  }

  public int getWidth() {
    return width;
  }

  public int getHeight() {
    return height;
  }
 
  public void clear(int bufferMask, Tuple3f color) {
    if ((bufferMask & COLOR_BUFFER) != 0) {
      int r = (int)(color.x*255f);
      int g = (int)(color.y*255f);
      int b = (int)(color.z*255f);
      int c = (r << 16) | (g << 8) | b;
      for (int i=0; i<zbuffer.length; i++) {
        pixels[i] = c;
      }
    }

    if ((bufferMask & DEPTH_BUFFER) != 0) {
      for (int i=0; i<zbuffer.length; i++) {
        zbuffer[i] = Float.MAX_VALUE;
      }
    }
  }

  public void drawPolygon(int num, Tuple4f[] vertices, Tuple3f[] colors) {
    minY = Short.MAX_VALUE;
    maxY = Short.MIN_VALUE;

    for (int i=0; i<height; i++) {
      spans[i].x1 = Short.MAX_VALUE;
      spans[i].x2 = Short.MIN_VALUE;
    }
   
    for (int i=0; i<num; i++) {
      int j = (i+1)%num;
      scanEdge(vertices[i], vertices[j], colors[i], colors[j]);
    }
   
    for (int i=minY; i<maxY; i++) {
      int x1 = spans[i].x1;
      int x2 = spans[i].x2;
     
      if (x1 >= width) continue;
      if (x2 < 0) continue;
     
      if (x1 < 0) {
        float m = (float)(-x1) / (float)(x2 - x1);
        spans[i].c1r = (short)(spans[i].c1r + (spans[i].c2r - spans[i].c1r) * m);
        spans[i].c1g = (short)(spans[i].c1g + (spans[i].c2g - spans[i].c1g) * m);
        spans[i].c1b = (short)(spans[i].c1b + (spans[i].c2b - spans[i].c1b) * m);
        x1 = 0;
      }
      if (x2 >= width) {
        float m = (float)((width - 1) - x1) / (float)(x2 - x1);
        spans[i].c2r = (short)((float)spans[i].c1r + (spans[i].c2r - spans[i].c1r) * m);
        spans[i].c2g = (short)((float)spans[i].c1g + (spans[i].c2g - spans[i].c1g) * m);
        spans[i].c2b = (short)((float)spans[i].c1b + (spans[i].c2b - spans[i].c1b) * m);
        x2 = width - 1;
      }
     
      int pos = i*width;
     
      Span span = spans[i];
     
      float z1 = (float)span.z1;
      float z2 = (float)span.z2;

      float r1 = (float)span.c1r;
      float g1 = (float)span.c1g;
      float b1 = (float)span.c1b;
      float r2 = (float)span.c2r;
      float g2 = (float)span.c2g;
      float b2 = (float)span.c2b;

      for (int j=x1; j<=x2; j++) {
        float a = (float)(j - x1) / (float)(x2 - x1 + 1);
        float z = z1*(1f-a) + z2*a;

        if (z > zbuffer[pos+j]) {
          continue;
        }
        else {
          zbuffer[pos+j] = z;
        }

        float r = r1*(1f-a) + r2*a;
        float g = g1*(1f-a) + g2*a;
        float b = b1*(1f-a) + b2*a;
        int ir = ((int)r) & 0xFF;
        int ig = ((int)g) & 0xFF;
        int ib = ((int)b) & 0xFF;
        pixels[pos+j] = (ir << 16) | (ig << 8) | ib;
      }
    }
  }
 
  private void scanEdge(Tuple4f v1, Tuple4f v2, Tuple3f c1, Tuple3f c2) {
    Tuple4f first, last;
    Tuple3f cfirst, clast;
   
    if (v1.y < v2.y) {
      first = v1;
      last = v2;
      cfirst = c1;
      clast = c2;
    }
    else {
      first = v2;
      last = v1;
      cfirst = c2;
      clast = c1;
    }
   
    float y1 = (int)first.y;
    float y2 = (int)last.y;
   
    if (y1 >= height) return;
    if (y2 < 0) return;
    if (y2 >= height) y2 = height - 1;
   
    float slopeX, x;
    float slopeZ, z;
    float slopeCR, slopeCG, slopeCB, cr, cg, cb;
   
    float invSub = 1f / (last.y - first.y);
   
    x = first.x;
    slopeX = (last.x - first.x) * invSub;
   
    z = first.z;
    slopeZ = (last.z - first.z) * invSub;
   
    cr = cfirst.x;
    cg = cfirst.y;
    cb = cfirst.z;
    slopeCR = (clast.x - cfirst.x) * invSub;
    slopeCG = (clast.y - cfirst.y) * invSub;
    slopeCB = (clast.z - cfirst.z) * invSub;
   
    if (y1 < 0) {
      x += slopeX * (-y1);
      z += slopeZ * (-y1);
      cr += slopeCR * (-y1);
      cg += slopeCG * (-y1);
      cb += slopeCB * (-y1);
      y1 = 0;
    }
   
    if (y1 < minY) minY = (int)y1;
    if (y2 > maxY) maxY = (int)y2;
   
    for (int i=(int)y1; i<(int)y2; i++) {
      int sx = (int)x;
      int scr = (int)(cr*255f);
      int scg = (int)(cg*255f);
      int scb = (int)(cb*255f);
     
      if (sx < spans[i].x1) {
        spans[i].x1 = sx;
        spans[i].z1 = z;
        spans[i].c1r = (short)scr;
        spans[i].c1g = (short)scg;
        spans[i].c1b = (short)scb;
      }
      if (sx > spans[i].x2) {
        spans[i].x2 = sx;
        spans[i].z2 = z;
        spans[i].c2r = (short)scr;
        spans[i].c2g = (short)scg;
        spans[i].c2b = (short)scb;
      }
      x += slopeX;
      z += slopeZ;
      cr += slopeCR;
      cg += slopeCG;
      cb += slopeCB;
    }
  }
 
  private static final int EDGE_LEFT   = 1 << 0;
  private static final int EDGE_RIGHT  = 1 << 1;
  private static final int EDGE_TOP    = 1 << 2;
  private static final int EDGE_BOTTOM = 1 << 3;
 
  public void drawLine(Tuple4f[] vertices, Tuple3f[] colors) {
    float x1 = vertices[0].x + 0.5f;
    float y1 = vertices[0].y + 0.5f;
    float z1 = vertices[0].z;

    float x2 = vertices[1].x + 0.5f;
    float y2 = vertices[1].y + 0.5f;
    float z2 = vertices[1].z;
   
    while (true) {
      int outcode1 = 0;
      if (x1 < 0) outcode1 |= EDGE_LEFT;
      else if (x1 >= width) outcode1 |= EDGE_RIGHT;
      if (y1 < 0) outcode1 |= EDGE_TOP;
      else if (y1 >= height) outcode1 |= EDGE_BOTTOM;

      int outcode2 = 0;
      if (x2 < 0) outcode2 |= EDGE_LEFT;
      else if (x2 >= width) outcode2 |= EDGE_RIGHT;
      if (y2 < 0) outcode2 |= EDGE_TOP;
      else if (y2 >= height) outcode2 |= EDGE_BOTTOM;
     
      if (outcode1 == 0 && outcode2 == 0) {
        break;
      }
      else if ((outcode1 & outcode2) != 0) {
        return;
      }
     
      int outcode = (outcode1 != 0)? outcode1 : outcode2;
      float x, y, z;
     
      if ((outcode & EDGE_LEFT) != 0) {
        float m = (0 - x1) / (x2 - x1);
        x = 0f;
        y = y1 + (y2 - y1) * m;
        z = z1 + (z2 - z1) * m;
      }
      else if ((outcode & EDGE_RIGHT) != 0) {
        float m = ((width-1) - x1) / (x2 - x1);
        x = width - 1;
        y = y1 + (y2 - y1) * m;
        z = z1 + (z2 - z1) * m;
      }
      else if ((outcode & EDGE_TOP) != 0) {
        float m = (0 - y1) / (y2 - y1);
        x = x1 + (x2 - x1) * m;
        y = 0f;
        z = z1 + (z2 - z1) * m;
      }
      else/* if ((outcode & EDGE_BOTTOM) != 0)*/ {
        float m = ((height-1) - y1) / (y2 - y1);
        x = x1 + (x2 - x1) * m;
        y = height - 1;
        z = z1 + (z2 - z1) * m;
      }
     
      if (outcode == outcode1) {
        x1 = x;
        y1 = y;
        z1 = z;
      }
      else {
        x2 = x;
        y2 = y;
        z2 = z;
      }
    }

    int color = ((int)(colors[0].x * 255f) << 16) | ((int)(colors[0].y * 255f) << 8) | (int)(colors[0].z * 255f);
    lineBresenham((int)x1, (int)y1, (int)x2, (int)y2, z1, z2, color);
  }
 
  // http://cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
  private void lineBresenham(int x0, int y0, int x1, int y1, float z1, float z2, int color) {
    int dy = y1 - y0;
    int dx = x1 - x0;
    int stepx, stepy;
    int pos;

    if (dy < 0) { dy = -dy;  stepy = -1; } else { stepy = 1; }
    if (dx < 0) { dx = -dx;  stepx = -1; } else { stepx = 1; }
    dy <<= 1;                                                  // dy is now 2*dy
    dx <<= 1;                                                  // dx is now 2*dx

    pos = y0*width+x0;
    if (z1 <= zbuffer[pos]) {
      zbuffer[pos] = z1;
      pixels[pos] = color;
    }
   
    if (dx > dy) {
      int fraction = dy - (dx >> 1);                         // same as 2*dy - dx
      float dz = (z2 - z1) / dx, z = z1 + dz;
      while (x0 != x1) {
        if (fraction >= 0) {
          y0 += stepy;
          fraction -= dx;                                // same as fraction -= 2*dx
        }
        x0 += stepx;
        fraction += dy;                                    // same as fraction -= 2*dy
       
        pos = y0*width+x0;
        if (z <= zbuffer[pos]) {
          zbuffer[pos] = z;
          pixels[pos] = color;
        }
        z += dz;
      }
    } else {
      int fraction = dx - (dy >> 1);
      float dz = (z2 - z1) / dy, z = z1 + dz;
      while (y0 != y1) {
        if (fraction >= 0) {
          x0 += stepx;
          fraction -= dy;
        }
        y0 += stepy;
        fraction += dx;
       
        pos = y0*width+x0;
        if (z <= zbuffer[pos]) {
          zbuffer[pos] = z;
          pixels[pos] = color;
        }
        z += dz;
      }
    }
  }
 
}
TOP

Related Classes of com.bulletphysics.demos.applet.Rasterizer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.