package com.brackeen.javagamebook.graphics3D;

/**
    Klasa ZBuffer implementuje z-bufor, czyli bufor głębi, w którym są
    przechowywane głębokości wszystkich pikseli obiektów trójwymiarowych
    wyświetlanych na ekranie. Wartość zapisana dla każdego piksela jest
    odwrotnością jego głębokości (1/z), zatem dla obiektów znajdujących
    się bliżej pierwszego planu precyzja jest większa niż w przypadku 
    obiektów znajdujących się dalej od kamery (gdzie duża precyzja 
    głębokości jest mniej nieistotna z punktu widzenia jakości obrazu).
*/
public class ZBuffer {

    private short[] depthBuffer;
    private int width;
    private int height;

    /**
        Tworzy nowy z-bufor o określonej szerokości i wysokości.
    */
    public ZBuffer(int width, int height) {
        depthBuffer = new short[width*height];
        this.width = width;
        this.height = height;
        clear();
    }


    /**
        Zwraca szerokość tego z-bufora.
    */
    public int getWidth() {
        return width;
    }


    /**
        Zwraca wysokość tego z-bufora.
    */
    public int getHeight() {
        return height;
    }


    /**
        Zwraca tablicę używaną do przechowywania tego bufora głębi.
    */
    public short[] getArray() {
        return depthBuffer;
    }


    /**
        Czyści z-bufor. Wszystkie głębokości będą miały wartość 0.
    */
    public void clear() {
        for (int i=0; i<depthBuffer.length; i++) {
            depthBuffer[i] = 0;
        }
    }


    /**
        Ustawia głębokość dla piksela w danej pozycji,
        zastępuje dotychczasową wartość w buforze.
    */
    public void setDepth(int offset, short depth) {
        depthBuffer[offset] = depth;
    }


    /**
        Sprawdza głębokość piksela w danej pozycji, jeśli przekazana
        głębokość jest mniejsza (przekazana wartość jest większa lub
        równa wartości przechowywanej w z-buforze na danej pozycji),
        wówczas w buforze jest zapisywana nowa głębokość, a metoda
        zwraca wartość true. W przeciwnym przypadku w buforze nie są
        wprowadzane żadne zmiany a metoda zwraca wartość false.
    */
    public boolean checkDepth(int offset, short depth) {
        if (depth >= depthBuffer[offset]) {
            depthBuffer[offset] = depth;
            return true;
        }
        else {
            return false;
        }
    }

}
