⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fasttexturedpolygonrenderer.java

📁 Java games programing--很好的java游戏编程源码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package com.brackeen.javagamebook.graphics3D;

import java.awt.*;
import java.awt.image.*;
import java.util.HashMap;
import com.brackeen.javagamebook.math3D.*;
import com.brackeen.javagamebook.graphics3D.texture.*;

/**
    The FastTexturedPolygonRenderer is a PolygonRenderer that
    efficiently renders Textures.
*/
public class FastTexturedPolygonRenderer extends PolygonRenderer {

    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 a = new Vector3D();
    protected Vector3D b = new Vector3D();
    protected Vector3D c = new Vector3D();
    protected Vector3D viewPos = new Vector3D();
    protected BufferedImage doubleBuffer;
    protected short[] doubleBufferData;
    protected HashMap scanRenderers;

    public FastTexturedPolygonRenderer(Transform3D camera,
        ViewWindow viewWindow)
    {
        this(camera, viewWindow, true);
    }

    public FastTexturedPolygonRenderer(Transform3D camera,
        ViewWindow viewWindow, boolean clearViewEveryFrame)
    {
        super(camera, viewWindow, clearViewEveryFrame);
    }

    protected void init() {
        destPolygon = new TexturedPolygon3D();
        scanConverter = new ScanConverter(viewWindow);

        // create renders for each texture (HotSpot optimization)
        scanRenderers = new HashMap();
        scanRenderers.put(PowerOf2Texture.class,
            new PowerOf2TextureRenderer());
        scanRenderers.put(ShadedTexture.class,
            new ShadedTextureRenderer());
        scanRenderers.put(ShadedSurface.class,
            new ShadedSurfaceRenderer());
    }


    public void startFrame(Graphics2D g) {
        // 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) {
        if (!(sourcePolygon instanceof TexturedPolygon3D)) {
            // not a textured polygon - return
            return;
        }
        TexturedPolygon3D poly = (TexturedPolygon3D)destPolygon;
        Texture texture = poly.getTexture();
        ScanRenderer scanRenderer = (ScanRenderer)
            scanRenderers.get(texture.getClass());
        scanRenderer.setTexture(texture);
        Rectangle3D textureBounds = poly.getTextureBounds();

        a.setToCrossProduct(textureBounds.getDirectionV(),
            textureBounds.getOrigin());
        b.setToCrossProduct(textureBounds.getOrigin(),
            textureBounds.getDirectionU());
        c.setToCrossProduct(textureBounds.getDirectionU(),
            textureBounds.getDirectionV());

        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 {

        protected Texture currentTexture;

        public void setTexture(Texture texture) {
            this.currentTexture = texture;
        }

        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)0x0007;
            }
        }
    }


    //================================================
    // METHOD 1: access pixel buffers directly
    // and use textures sizes that are a power of 2
    //================================================
    public class Method1 extends ScanRenderer {

        public void render(int offset, int left, int right) {
            for (int x=left; x<=right; x++) {
                int tx = (int)(a.getDotProduct(viewPos) /
                    c.getDotProduct(viewPos));
                int ty = (int)(b.getDotProduct(viewPos) /
                    c.getDotProduct(viewPos));
                doubleBufferData[offset++] =
                    currentTexture.getColor(tx, ty);
                viewPos.x++;
            }
        }
    }


    //================================================
    // METHOD 2: avoid redundant calculations
    //================================================
    public class Method2 extends ScanRenderer {

        public void render(int offset, int left, int right) {
            float u = a.getDotProduct(viewPos);
            float v = b.getDotProduct(viewPos);
            float z = c.getDotProduct(viewPos);
            float du = a.x;
            float dv = b.x;
            float dz = c.x;
            for (int x=left; x<=right; x++) {
                doubleBufferData[offset++] =
                    currentTexture.getColor(
                    (int)(u/z), (int)(v/z));
                u+=du;
                v+=dv;
                z+=dz;
            }
        }
    }


    //================================================
    // METHOD 3: use ints instead of floats
    //================================================
    public class Method3 extends ScanRenderer {

        public void render(int offset, int left, int right) {
            int u = (int)(SCALE * a.getDotProduct(viewPos));
            int v = (int)(SCALE * b.getDotProduct(viewPos));
            int z = (int)(SCALE * c.getDotProduct(viewPos));
            int du = (int)(SCALE * a.x);
            int dv = (int)(SCALE * b.x);
            int dz = (int)(SCALE * c.x);
            for (int x=left; x<=right; x++) {
                doubleBufferData[offset++] =
                    currentTexture.getColor(u/z, v/z);
                u+=du;
                v+=dv;
                z+=dz;
            }
        }
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -