Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.brackeen.javagamebook.graphics3D;
- import java.awt.*;
- import java.awt.image.*;
- import com.brackeen.javagamebook.math3D.*;
- public class SolidZBufferedRenderer extends PolygonRenderer {
- /**
- The minimum distance for z-buffering. Larger values give
- more accurate calculations for further distances.
- */
- protected static final int MIN_DISTANCE = 12;
- protected ZBuffer zBuffer;
- // used for calculating depth
- protected float w;
- public static final int SCALE_BITS = 12;
- public static final int SCALE = 1 << SCALE_BITS;
- public static final int INTERP_SIZE_BITS = 4;
- public static final int INTERP_SIZE = 1 << INTERP_SIZE_BITS;
- protected Vector3D c = new Vector3D();
- protected Vector3D viewPos = new Vector3D();
- protected BufferedImage doubleBuffer;
- protected short[] doubleBufferData;
- ScanRenderer scanRenderer;
- public SolidZBufferedRenderer(Transform3D camera, ViewWindow viewWindow) {
- super(camera, viewWindow, true);
- }
- protected void init() {
- destPolygon = new SolidPolygon3D();
- scanConverter = new ScanConverter(viewWindow);
- scanRenderer = new Method1();
- }
- public void startFrame(Graphics2D g) {
- super.startFrame(g);
- // initialize depth buffer
- if (zBuffer == null ||
- zBuffer.getWidth() != viewWindow.getWidth() ||
- zBuffer.getHeight() != viewWindow.getHeight())
- {
- zBuffer = new ZBuffer(
- viewWindow.getWidth(), viewWindow.getHeight());
- }
- else if (clearViewEveryFrame) {
- zBuffer.clear();
- }
- // initialize buffer
- if (doubleBuffer == null ||
- doubleBuffer.getWidth() != viewWindow.getWidth() ||
- doubleBuffer.getHeight() != viewWindow.getHeight())
- {
- doubleBuffer = new BufferedImage(
- viewWindow.getWidth(), viewWindow.getHeight(),
- BufferedImage.TYPE_USHORT_565_RGB);
- //doubleBuffer = g.getDeviceConfiguration().createCompatibleImage(
- //viewWindow.getWidth(), viewWindow.getHeight());
- DataBuffer dest =
- doubleBuffer.getRaster().getDataBuffer();
- doubleBufferData = ((DataBufferUShort)dest).getData();
- }
- // clear view
- if (clearViewEveryFrame) {
- for (int i=0; i<doubleBufferData.length; i++) {
- doubleBufferData[i] = 0;
- }
- }
- }
- public void endFrame(Graphics2D g) {
- // draw the double buffer onto the screen
- g.drawImage(doubleBuffer, viewWindow.getLeftOffset(),
- viewWindow.getTopOffset(), null);
- }
- protected void drawCurrentPolygon(Graphics2D g) {
- //a.setToCrossProduct(textureBounds.getDirectionV(),
- //textureBounds.getOrigin());
- //b.setToCrossProduct(textureBounds.getOrigin(),
- //textureBounds.getDirectionU());
- c.setTo(destPolygon.getNormal());
- // w is used to compute depth at each pixel
- w = SCALE * MIN_DISTANCE * Short.MAX_VALUE /
- (viewWindow.getDistance() *
- c.getDotProduct(destPolygon.getNormal()));
- int y = scanConverter.getTopBoundary();
- viewPos.y = viewWindow.convertFromScreenYToViewY(y);
- viewPos.z = -viewWindow.getDistance();
- while (y<=scanConverter.getBottomBoundary()) {
- ScanConverter.Scan scan = scanConverter.getScan(y);
- if (scan.isValid()) {
- viewPos.x = viewWindow.
- convertFromScreenXToViewX(scan.left);
- int offset = (y - viewWindow.getTopOffset()) *
- viewWindow.getWidth() +
- (scan.left - viewWindow.getLeftOffset());
- scanRenderer.render(offset, scan.left, scan.right);
- }
- y++;
- viewPos.y--;
- }
- }
- /**
- The ScanRenderer class is an abstract inner class of
- FastTexturedPolygonRenderer that provides an interface for
- rendering a horizontal scan line.
- */
- public abstract class ScanRenderer {
- public abstract void render(int offset,
- int left, int right);
- }
- //================================================
- // FASTEST METHOD: no texture (for comparison)
- //================================================
- public class Method0 extends ScanRenderer {
- public void render(int offset, int left, int right) {
- for (int x=left; x<=right; x++) {
- doubleBufferData[offset++] = (short)((SolidPolygon3D)destPolygon).getColor().getRGB();
- }
- }
- }
- public class Method1 extends ScanRenderer {
- public void render(int offset, int left, int right) {
- float z = c.getDotProduct(viewPos);
- float dz = INTERP_SIZE * c.x;
- int depth = (int)(w*z);
- int dDepth = (int)(w*c.x);
- for (int x=left; x<=right; x++) {
- if (zBuffer.checkDepth(offset,
- (short)(depth >> SCALE_BITS)))
- {
- doubleBufferData[offset] =
- (short) ((SolidPolygon3D)destPolygon).getColor().getRGB();
- }
- offset++;
- depth+=dDepth;
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement