Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

By: a guest on Jul 9th, 2012  |  syntax: Java  |  size: 5.46 KB  |  views: 21  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. package com.brackeen.javagamebook.graphics3D;
  2.  
  3. import java.awt.*;
  4. import java.awt.image.*;
  5. import com.brackeen.javagamebook.math3D.*;
  6.  
  7. public class SolidZBufferedRenderer extends PolygonRenderer {
  8.  
  9.     /**
  10.         The minimum distance for z-buffering. Larger values give
  11.         more accurate calculations for further distances.
  12.     */
  13.     protected static final int MIN_DISTANCE = 12;
  14.  
  15.     protected ZBuffer zBuffer;
  16.     // used for calculating depth
  17.     protected float w;
  18.  
  19.     public static final int SCALE_BITS = 12;
  20.     public static final int SCALE = 1 << SCALE_BITS;
  21.  
  22.     public static final int INTERP_SIZE_BITS = 4;
  23.     public static final int INTERP_SIZE = 1 << INTERP_SIZE_BITS;
  24.  
  25.     protected Vector3D c = new Vector3D();
  26.     protected Vector3D viewPos = new Vector3D();
  27.  
  28.     protected BufferedImage doubleBuffer;
  29.     protected short[] doubleBufferData;
  30.     ScanRenderer scanRenderer;
  31.  
  32.     public SolidZBufferedRenderer(Transform3D camera, ViewWindow viewWindow) {
  33.         super(camera, viewWindow, true);
  34.     }
  35.  
  36.     protected void init() {
  37.         destPolygon = new SolidPolygon3D();
  38.         scanConverter = new ScanConverter(viewWindow);
  39.  
  40.         scanRenderer = new Method1();
  41.     }
  42.  
  43.     public void startFrame(Graphics2D g) {
  44.         super.startFrame(g);
  45.         // initialize depth buffer
  46.         if (zBuffer == null ||
  47.             zBuffer.getWidth() != viewWindow.getWidth() ||
  48.             zBuffer.getHeight() != viewWindow.getHeight())
  49.         {
  50.             zBuffer = new ZBuffer(
  51.                 viewWindow.getWidth(), viewWindow.getHeight());
  52.         }
  53.         else if (clearViewEveryFrame) {
  54.             zBuffer.clear();
  55.         }
  56.  
  57.         // initialize buffer
  58.         if (doubleBuffer == null ||
  59.             doubleBuffer.getWidth() != viewWindow.getWidth() ||
  60.             doubleBuffer.getHeight() != viewWindow.getHeight())
  61.         {
  62.             doubleBuffer = new BufferedImage(
  63.                 viewWindow.getWidth(), viewWindow.getHeight(),
  64.                 BufferedImage.TYPE_USHORT_565_RGB);
  65.             //doubleBuffer = g.getDeviceConfiguration().createCompatibleImage(
  66.             //viewWindow.getWidth(), viewWindow.getHeight());
  67.  
  68.             DataBuffer dest =
  69.                 doubleBuffer.getRaster().getDataBuffer();
  70.             doubleBufferData = ((DataBufferUShort)dest).getData();
  71.         }
  72.         // clear view
  73.         if (clearViewEveryFrame) {
  74.             for (int i=0; i<doubleBufferData.length; i++) {
  75.                 doubleBufferData[i] = 0;
  76.             }
  77.         }
  78.     }
  79.  
  80.     public void endFrame(Graphics2D g) {
  81.         // draw the double buffer onto the screen
  82.         g.drawImage(doubleBuffer, viewWindow.getLeftOffset(),
  83.             viewWindow.getTopOffset(), null);
  84.     }
  85.  
  86.  
  87.     protected void drawCurrentPolygon(Graphics2D g) {
  88.  
  89.         //a.setToCrossProduct(textureBounds.getDirectionV(),
  90.             //textureBounds.getOrigin());
  91.         //b.setToCrossProduct(textureBounds.getOrigin(),
  92.             //textureBounds.getDirectionU());
  93.  
  94.         c.setTo(destPolygon.getNormal());
  95.  
  96.         // w is used to compute depth at each pixel
  97.         w = SCALE * MIN_DISTANCE * Short.MAX_VALUE /
  98.             (viewWindow.getDistance() *
  99.             c.getDotProduct(destPolygon.getNormal()));
  100.  
  101.         int y = scanConverter.getTopBoundary();
  102.         viewPos.y = viewWindow.convertFromScreenYToViewY(y);
  103.         viewPos.z = -viewWindow.getDistance();
  104.  
  105.         while (y<=scanConverter.getBottomBoundary()) {
  106.             ScanConverter.Scan scan = scanConverter.getScan(y);
  107.  
  108.             if (scan.isValid()) {
  109.                 viewPos.x = viewWindow.
  110.                     convertFromScreenXToViewX(scan.left);
  111.                 int offset = (y - viewWindow.getTopOffset()) *
  112.                     viewWindow.getWidth() +
  113.                     (scan.left - viewWindow.getLeftOffset());
  114.  
  115.                 scanRenderer.render(offset, scan.left, scan.right);
  116.             }
  117.             y++;
  118.             viewPos.y--;
  119.         }
  120.     }
  121.  
  122.  
  123.     /**
  124.         The ScanRenderer class is an abstract inner class of
  125.         FastTexturedPolygonRenderer that provides an interface for
  126.         rendering a horizontal scan line.
  127.     */
  128.     public abstract class ScanRenderer {
  129.  
  130.         public abstract void render(int offset,
  131.             int left, int right);
  132.  
  133.     }
  134.  
  135.     //================================================
  136.     // FASTEST METHOD: no texture (for comparison)
  137.     //================================================
  138.     public class Method0 extends ScanRenderer {
  139.  
  140.         public void render(int offset, int left, int right) {
  141.             for (int x=left; x<=right; x++) {
  142.                 doubleBufferData[offset++] = (short)((SolidPolygon3D)destPolygon).getColor().getRGB();
  143.             }
  144.         }
  145.     }
  146.  
  147.     public class Method1 extends ScanRenderer {
  148.  
  149.         public void render(int offset, int left, int right) {
  150.  
  151.                 float z = c.getDotProduct(viewPos);
  152.                 float dz = INTERP_SIZE * c.x;
  153.                 int depth = (int)(w*z);
  154.                 int dDepth = (int)(w*c.x);
  155.  
  156.             for (int x=left; x<=right; x++) {
  157.  
  158.                 if (zBuffer.checkDepth(offset,
  159.                         (short)(depth >> SCALE_BITS)))
  160.                         {
  161.                             doubleBufferData[offset] =
  162.                                 (short) ((SolidPolygon3D)destPolygon).getColor().getRGB();
  163.                 }
  164.                         offset++;
  165.                         depth+=dDepth;
  166.             }
  167.  
  168.         }
  169.     }
  170.  
  171.  
  172.  
  173. }