package com.brackeen.javagamebook.math3D;

/**
    Klasa PointLight3D to punktowe źródło światła o ustalonej
    intensywności(między 0 a 1) i opcjonalnie odległości wygasania,
    która pozwala na osłabianie światła wraz z odległością.
*/
public class PointLight3D extends Vector3D {

    public static final float NO_DISTANCE_FALLOFF = -1;

    private float intensity;
    private float distanceFalloff;

    /**
        Tworzy nowe światło PointLight3D w punkcie (0,0,0) o intensywności
        1 i niewygasające wraz z odległością.
    */
    public PointLight3D() {
        this(0,0,0, 1, NO_DISTANCE_FALLOFF);
    }


    /**
        Tworzy kopię podanego źródła światła PointLight3D.
    */
    public PointLight3D(PointLight3D p) {
        setTo(p);
    }


    /**
        Tworzy nowe światło PointLight3D o podanej lokacji
        i intensywności. Światło nie wygasa wraz z odległością.
    */
    public PointLight3D(float x, float y, float z,
        float intensity)
    {
        this(x, y, z, intensity, NO_DISTANCE_FALLOFF);
    }


    /**
        Tworzy nowe światło PointLight3D o podanej lokacji
        i intensywności. Światło nie wygasa wraz z odległością.
    */
    public PointLight3D(float x, float y, float z,
        float intensity, float distanceFalloff)
    {
        setTo(x, y, z);
        setIntensity(intensity);
        setDistanceFalloff(distanceFalloff);
    }


    /**
        Przypisuje temu światłu PointLight3D tę samą lokalizację, intensywność
        i odległość wygasania, które ma podane światło PointLight3D.
    */
    public void setTo(PointLight3D p) {
        setTo(p.x, p.y, p.z);
        setIntensity(p.getIntensity());
        setDistanceFalloff(p.getDistanceFalloff());
    }


    /**
        Pobiera intensywność światła z tego źródła w 
        określonej odległości od niego.
    */
    public float getIntensity(float distance) {
        if (distanceFalloff == NO_DISTANCE_FALLOFF) {
            return intensity;
        }
        else if (distance >= distanceFalloff) {
            return 0;
        }
        else {
            return intensity * (distanceFalloff - distance)
                / (distanceFalloff + distance);
        }
    }

    /**
        Pobiera intensywność tego światła.
    */
    public float getIntensity() {
        return intensity;
    }


    /**
        Ustawia intensywność tego światła.
    */
    public void setIntensity(float intensity) {
        this.intensity = intensity;
    }


    /**
        Pobiera odległość wygasania. Po jej przekroczeniu
        intensywność światła spada do zera.
    */
    public float getDistanceFalloff() {
        return distanceFalloff;
    }


    /**
        Ustawia odległość wygasania. Po jej przekroczeniu
        intensywność światła spada do zera. NO_DISTANCE_FALLOFF
        jesli światło nie powinno wygasać wraz z odległością.
    */
    public void setDistanceFalloff(float distanceFalloff) {
        this.distanceFalloff = distanceFalloff;
    }

}
