001/**
002 * Copyright (c) 2008-2014 Ardor Labs, Inc.
003 *
004 * This file is part of Ardor3D.
005 *
006 * Ardor3D is free software: you can redistribute it and/or modify it 
007 * under the terms of its license which may be found in the accompanying
008 * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
009 */
010
011package com.ardor3d.light;
012
013import java.io.IOException;
014import java.io.Serializable;
015
016import com.ardor3d.math.ColorRGBA;
017import com.ardor3d.math.type.ReadOnlyColorRGBA;
018import com.ardor3d.util.export.InputCapsule;
019import com.ardor3d.util.export.OutputCapsule;
020import com.ardor3d.util.export.Savable;
021
022/**
023 * <code>Light</code> defines the attributes of a light element. This class is abstract and intended to be sub-classed
024 * by specific lighting types. A light will illuminate portions of the scene by assigning its properties to the objects
025 * in the scene. This will affect the objects color values, depending on the color of the ambient, diffuse and specular
026 * light components.
027 * 
028 * Ambient light defines the general light of the scene, that is the intensity and color of lighting if no particular
029 * lights are affecting it.
030 * 
031 * Diffuse lighting defines the reflection of light on matte surfaces.
032 * 
033 * Specular lighting defines the reflection of light on shiny surfaces.
034 */
035public abstract class Light implements Serializable, Savable {
036
037    private static final long serialVersionUID = 1L;
038
039    /**
040     * dark grey (.4, .4, .4, 1)
041     */
042    public static final ReadOnlyColorRGBA DEFAULT_AMBIENT = new ColorRGBA(0.4f, 0.4f, 0.4f, 1.0f);
043
044    /**
045     * white (1, 1, 1, 1)
046     */
047    public static final ReadOnlyColorRGBA DEFAULT_DIFFUSE = new ColorRGBA(1, 1, 1, 1);
048
049    /**
050     * white (1, 1, 1, 1)
051     */
052    public static final ReadOnlyColorRGBA DEFAULT_SPECULAR = new ColorRGBA(1, 1, 1, 1);
053
054    public enum Type {
055        Directional, Point, Spot
056    }
057
058    // light attributes.
059    private final ColorRGBA _ambient = new ColorRGBA(DEFAULT_AMBIENT);
060    private final ColorRGBA _diffuse = new ColorRGBA(DEFAULT_DIFFUSE);
061    private final ColorRGBA _specular = new ColorRGBA(DEFAULT_SPECULAR);
062
063    private boolean _attenuate;
064    private float _constant = 1;
065    private float _linear;
066    private float _quadratic;
067
068    private int _lightMask = 0;
069    private int _backLightMask = 0;
070
071    private boolean _enabled;
072
073    private String _name;
074
075    /** when true, indicates the lights in this lightState will cast shadows. */
076    protected boolean _shadowCaster;
077
078    /**
079     * Constructor instantiates a new <code>Light</code> object. All light color values are set to white.
080     * 
081     */
082    public Light() {}
083
084    /**
085     * 
086     * <code>getType</code> returns the type of the light that has been created.
087     * 
088     * @return the type of light that has been created.
089     */
090    public abstract Type getType();
091
092    /**
093     * <code>getConstant</code> returns the value for the constant attenuation.
094     * 
095     * @return the value for the constant attenuation.
096     */
097    public float getConstant() {
098        return _constant;
099    }
100
101    /**
102     * <code>setConstant</code> sets the value for the constant attentuation.
103     * 
104     * @param constant
105     *            the value for the constant attenuation.
106     */
107    public void setConstant(final float constant) {
108        _constant = constant;
109    }
110
111    /**
112     * <code>getLinear</code> returns the value for the linear attenuation.
113     * 
114     * @return the value for the linear attenuation.
115     */
116    public float getLinear() {
117        return _linear;
118    }
119
120    /**
121     * <code>setLinear</code> sets the value for the linear attentuation.
122     * 
123     * @param linear
124     *            the value for the linear attenuation.
125     */
126    public void setLinear(final float linear) {
127        _linear = linear;
128    }
129
130    /**
131     * <code>getQuadratic</code> returns the value for the quadratic attentuation.
132     * 
133     * @return the value for the quadratic attenuation.
134     */
135    public float getQuadratic() {
136        return _quadratic;
137    }
138
139    /**
140     * <code>setQuadratic</code> sets the value for the quadratic attenuation.
141     * 
142     * @param quadratic
143     *            the value for the quadratic attenuation.
144     */
145    public void setQuadratic(final float quadratic) {
146        _quadratic = quadratic;
147    }
148
149    /**
150     * <code>isAttenuate</code> returns true if attenuation is to be used for this light.
151     * 
152     * @return true if attenuation is to be used, false otherwise.
153     */
154    public boolean isAttenuate() {
155        return _attenuate;
156    }
157
158    /**
159     * <code>setAttenuate</code> sets if attenuation is to be used. True sets it on, false otherwise.
160     * 
161     * @param attenuate
162     *            true to use attenuation, false not to.
163     */
164    public void setAttenuate(final boolean attenuate) {
165        _attenuate = attenuate;
166    }
167
168    /**
169     * 
170     * <code>isEnabled</code> returns true if the light is enabled, false otherwise.
171     * 
172     * @return true if the light is enabled, false if it is not.
173     */
174    public boolean isEnabled() {
175        return _enabled;
176    }
177
178    /**
179     * 
180     * <code>setEnabled</code> sets the light on or off. True turns it on, false turns it off.
181     * 
182     * @param value
183     *            true to turn the light on, false to turn it off.
184     */
185    public void setEnabled(final boolean value) {
186        _enabled = value;
187    }
188
189    /**
190     * <code>getSpecular</code> returns the specular color value for this light.
191     * 
192     * @return the specular color value of the light.
193     */
194    public ReadOnlyColorRGBA getSpecular() {
195        return _specular;
196    }
197
198    /**
199     * <code>setSpecular</code> sets the specular color value for this light.
200     * 
201     * @param specular
202     *            the specular color value of the light.
203     */
204    public void setSpecular(final ReadOnlyColorRGBA specular) {
205        _specular.set(specular);
206    }
207
208    /**
209     * <code>getDiffuse</code> returns the diffuse color value for this light.
210     * 
211     * @return the diffuse color value for this light.
212     */
213    public ReadOnlyColorRGBA getDiffuse() {
214        return _diffuse;
215    }
216
217    /**
218     * <code>setDiffuse</code> sets the diffuse color value for this light.
219     * 
220     * @param diffuse
221     *            the diffuse color value for this light.
222     */
223    public void setDiffuse(final ReadOnlyColorRGBA diffuse) {
224        _diffuse.set(diffuse);
225    }
226
227    /**
228     * <code>getAmbient</code> returns the ambient color value for this light.
229     * 
230     * @return the ambient color value for this light.
231     */
232    public ReadOnlyColorRGBA getAmbient() {
233        return _ambient;
234    }
235
236    /**
237     * <code>setAmbient</code> sets the ambient color value for this light.
238     * 
239     * @param ambient
240     *            the ambient color value for this light.
241     */
242    public void setAmbient(final ReadOnlyColorRGBA ambient) {
243        _ambient.set(ambient);
244    }
245
246    /**
247     * @return Returns the lightMask - default is 0 or not masked.
248     */
249    public int getLightMask() {
250        return _lightMask;
251    }
252
253    /**
254     * <code>setLightMask</code> sets what attributes of this light to apply as an int comprised of bitwise |'ed values
255     * from LightState.Mask_XXXX. LightMask.MASK_GLOBALAMBIENT is ignored.
256     * 
257     * @param lightMask
258     *            The lightMask to set.
259     */
260    public void setLightMask(final int lightMask) {
261        _lightMask = lightMask;
262    }
263
264    /**
265     * Saves the light mask to a back store. That backstore is recalled with popLightMask. Despite the name, this is not
266     * a stack and additional pushes will simply overwrite the backstored value.
267     */
268    public void pushLightMask() {
269        _backLightMask = _lightMask;
270    }
271
272    /**
273     * Recalls the light mask from a back store or 0 if none was pushed.
274     * 
275     * @see com.ardor3d.light.Light#pushLightMask()
276     */
277    public void popLightMask() {
278        _lightMask = _backLightMask;
279    }
280
281    /**
282     * @return Returns whether this light is able to cast shadows.
283     */
284    public boolean isShadowCaster() {
285        return _shadowCaster;
286    }
287
288    /**
289     * @param mayCastShadows
290     *            true if this light can be used to derive shadows (when used in conjunction with a shadow pass.)
291     */
292    public void setShadowCaster(final boolean mayCastShadows) {
293        _shadowCaster = mayCastShadows;
294    }
295
296    /**
297     * Copies the light values from the given light into this Light.
298     * 
299     * @param light
300     *            the Light to copy from.
301     */
302    public void copyFrom(final Light light) {
303        _ambient.set(light._ambient);
304        _attenuate = light._attenuate;
305        _constant = light._constant;
306        _diffuse.set(light._diffuse);
307        _enabled = light._enabled;
308        _linear = light._linear;
309        _quadratic = light._quadratic;
310        _shadowCaster = light._shadowCaster;
311        _specular.set(light._specular);
312    }
313
314    public String getName() {
315        return _name;
316    }
317
318    public void setName(final String name) {
319        _name = name;
320    }
321
322    @Override
323    public void write(final OutputCapsule capsule) throws IOException {
324        capsule.write(_ambient, "ambient", new ColorRGBA(DEFAULT_AMBIENT));
325        capsule.write(_diffuse, "diffuse", new ColorRGBA(DEFAULT_DIFFUSE));
326        capsule.write(_specular, "specular", new ColorRGBA(DEFAULT_SPECULAR));
327        capsule.write(_attenuate, "attenuate", false);
328        capsule.write(_constant, "constant", 1);
329        capsule.write(_linear, "linear", 0);
330        capsule.write(_quadratic, "quadratic", 0);
331        capsule.write(_lightMask, "lightMask", 0);
332        capsule.write(_backLightMask, "backLightMask", 0);
333        capsule.write(_enabled, "enabled", false);
334        capsule.write(_shadowCaster, "shadowCaster", false);
335        capsule.write(_name, "name", null);
336    }
337
338    @Override
339    public void read(final InputCapsule capsule) throws IOException {
340        _ambient.set((ColorRGBA) capsule.readSavable("ambient", new ColorRGBA(DEFAULT_AMBIENT)));
341        _diffuse.set((ColorRGBA) capsule.readSavable("diffuse", new ColorRGBA(DEFAULT_DIFFUSE)));
342        _specular.set((ColorRGBA) capsule.readSavable("specular", new ColorRGBA(DEFAULT_SPECULAR)));
343        _attenuate = capsule.readBoolean("attenuate", false);
344        _constant = capsule.readFloat("constant", 1);
345        _linear = capsule.readFloat("linear", 0);
346        _quadratic = capsule.readFloat("quadratic", 0);
347        _lightMask = capsule.readInt("lightMask", 0);
348        _backLightMask = capsule.readInt("backLightMask", 0);
349        _enabled = capsule.readBoolean("enabled", false);
350        _shadowCaster = capsule.readBoolean("shadowCaster", false);
351        _name = capsule.readString("name", null);
352    }
353
354    @Override
355    public Class<? extends Light> getClassTag() {
356        return this.getClass();
357    }
358}