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

📄 sortedscanconverter.java

📁 JAVA游戏编程光盘,内有18个实例,非常详细地阐述了JAVA游戏编程的知识.
💻 JAVA
字号:
package com.brackeen.javagamebook.graphics3D;

import com.brackeen.javagamebook.math3D.*;

/**
    A ScanConverter used to draw sorted polygons from
    front-to-back with no overdraw. Polygons are added and clipped
    to a list of what's in the view window. Call clear() before
    drawing every frame.
*/
public class SortedScanConverter extends ScanConverter {

    protected static final int DEFAULT_SCANLIST_CAPACITY = 8;

    private SortedScanList[] viewScans;
    private SortedScanList[] polygonScans;
    private boolean sortedMode;

    /**
        Creates a new SortedScanConverter for the specified
        ViewWindow. The ViewWindow's properties can change in
        between scan conversions. By default, sorted mode is
        off, but can be turned on by calling setSortedMode().
    */
    public SortedScanConverter(ViewWindow view) {
        super(view);
        sortedMode = false;
    }


    /**
        Clears the current view scan. Call this method every frame.
    */
    public void clear() {
        if (viewScans != null) {
            for (int y=0; y<viewScans.length; y++) {
                viewScans[y].clear();
            }
        }
    }


    /**
        Sets sorted mode, so this scan converter can assume
        the polygons are drawn front-to-back, and should be
        clipped against polygons already scanned for this view.
    */
    public void setSortedMode(boolean b) {
        sortedMode = b;
    }


    /**
        Gets the nth scan for the specified row.
    */
    public Scan getScan(int y, int index) {
        return polygonScans[y].getScan(index);
    }


    /**
        Gets the number of scans for the specified row.
    */
    public int getNumScans(int y) {
        return polygonScans[y].getNumScans();
    }


    /**
        Checks if the view is filled.
    */
    public boolean isFilled() {
        if (viewScans == null) {
            return false;
        }

        int left = view.getLeftOffset();
        int right = left + view.getWidth() - 1;
        for (int y=view.getTopOffset(); y<viewScans.length; y++) {
            if (!viewScans[y].equals(left, right)) {
                return false;
            }
        }
        return true;
    }


    protected void ensureCapacity() {
        super.ensureCapacity();
        int height = view.getTopOffset() + view.getHeight();
        int oldHeight = (viewScans == null)?0:viewScans.length;
        if (height != oldHeight) {
            SortedScanList[] newViewScans =
                new SortedScanList[height];
            SortedScanList[] newPolygonScans =
                new SortedScanList[height];
            if (oldHeight != 0) {
                System.arraycopy(viewScans, 0, newViewScans, 0,
                    Math.min(height, oldHeight));
                System.arraycopy(polygonScans, 0, newPolygonScans,
                    0, Math.min(height, oldHeight));
            }
            viewScans = newViewScans;
            polygonScans = newPolygonScans;
            for (int i=oldHeight; i<height; i++) {
                viewScans[i] = new SortedScanList();
                polygonScans[i] = new SortedScanList();
            }
        }
    }


    /**
        Scan-converts a polygon, and if sortedMode is on, adds
        and clips it to a list of what's in the view window.
    */
    public boolean convert(Polygon3D polygon) {
        boolean visible = super.convert(polygon);
        if (!sortedMode || !visible) {
            return visible;
        }

        // clip the scan to what's already in the view
        visible = false;
        for (int y=getTopBoundary(); y<=getBottomBoundary(); y++) {
            Scan scan = getScan(y);
            SortedScanList diff = polygonScans[y];
            diff.clear();
            if (scan.isValid()) {
                viewScans[y].add(scan.left, scan.right, diff);
                visible |= (polygonScans[y].getNumScans() > 0);
            }
        }

        return visible;

    }


    /**
        The SortedScanList class represents a series of scans
        for a row. New scans can be added and clipped to what's
        visible in the row.
    */
    private static class SortedScanList {

        private int length;
        private Scan[] scans;

        /**
            Creates a new SortedScanList with the default
            capacity (number of scans per row).
        */
        public SortedScanList() {
            this(DEFAULT_SCANLIST_CAPACITY);
        }


        /**
            Creates a new SortedScanList with the specified
            capacity (number of scans per row).
        */
        public SortedScanList(int capacity) {
            scans = new Scan[capacity];
            for (int i=0; i<capacity; i++) {
                scans[i] = new Scan();
            }
            length = 0;
        }


        /**
            Clears this list of scans.
        */
        public void clear() {
            length = 0;
        }


        /**
            Clears the number of scans in this list.
        */
        public int getNumScans() {
            return length;
        }


        /**
            Gets the nth scan in this list.
        */
        public Scan getScan(int index) {
            return scans[index];
        }


        /**
            Checks if this scan list has only one scan and that
            scan is equal to the specified left and right values.
        */
        public boolean equals(int left, int right) {
            return (length == 1 && scans[0].equals(left,right));
        }


        /**
            Add and clip the scan to this row, putting what is
            visible (the difference) in the specified
            SortedScanList.
        */
        public void add(int left, int right, SortedScanList diff) {
            for (int i=0; i<length && left <= right; i++) {
                Scan scan = scans[i];
                int maxRight = scan.left - 1;
                if (left <= maxRight) {
                    if (right < maxRight) {
                        diff.add(left, right);
                        insert(left, right, i);
                        return;
                    }
                    else {
                        diff.add(left, maxRight);
                        scan.left = left;
                        left = scan.right + 1;
                        if (merge(i)) {
                            i--;
                        }
                    }
                }
                else if (left <= scan.right) {
                    left = scan.right + 1;
                }
            }
            if (left <= right) {
                insert(left, right, length);
                diff.add(left, right);
            }

        }

        // add() helper methods

        private void growCapacity() {
            int capacity = scans.length;
            int newCapacity = capacity*2;
            Scan[] newScans = new Scan[newCapacity];
            System.arraycopy(scans, 0, newScans, 0, capacity);
            for (int i=length; i<newCapacity; i++) {
                newScans[i] = new Scan();
            }
            scans = newScans;
        }

        private void add(int left, int right) {
            if (length == scans.length) {
                growCapacity();
            }
            scans[length].setTo(left, right);
            length++;
        }

        private void insert(int left, int right, int index) {
            if (index > 0) {
                Scan prevScan = scans[index-1];
                if (prevScan.right == left - 1) {
                    prevScan.right = right;
                    return;
                }
            }

            if (length == scans.length) {
                growCapacity();
            }
            Scan last = scans[length];
            last.setTo(left, right);
            for (int i=length; i>index; i--) {
                scans[i] = scans[i-1];
            }
            scans[index] = last;
            length++;
        }

        private void remove(int index) {
            Scan removed = scans[index];
            for (int i=index; i<length-1; i++) {
                scans[i] = scans[i+1];
            }
            scans[length-1] = removed;
            length--;
        }

        private boolean merge(int index) {
            if (index > 0) {
                Scan prevScan = scans[index-1];
                Scan thisScan = scans[index];
                if (prevScan.right == thisScan.left-1) {
                    prevScan.right = thisScan.right;
                    remove(index);
                    return true;
                }
            }
            return false;
        }

    }

}

⌨️ 快捷键说明

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