Home | History | Annotate | Download | only in math
      1 /*
      2  * Copyright (c) 2009-2010 jMonkeyEngine All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are met:
      6  *  *
      7  * * Redistributions of source code must retain the above copyright notice,
      8  * this list of conditions and the following disclaimer.
      9  *
     10  * * Redistributions in binary form must reproduce the above copyright
     11  * notice, this list of conditions and the following disclaimer in the
     12  * documentation and/or other materials provided with the distribution.
     13  *
     14  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
     15  * may be used to endorse or promote products derived from this software
     16  * without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     28  * POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 package com.jme3.math;
     31 
     32 import com.jme3.export.*;
     33 import java.io.IOException;
     34 
     35 /**
     36  * <code>ColorRGBA</code> defines a color made from a collection of red, green
     37  * and blue values. An alpha value determines is transparency. All values must
     38  * be between 0 and 1. If any value is set higher or lower than these
     39  * constraints they are clamped to the min or max. That is, if a value smaller
     40  * than zero is set the value clamps to zero. If a value higher than 1 is
     41  * passed, that value is clamped to 1. However, because the attributes r, g, b,
     42  * a are public for efficiency reasons, they can be directly modified with
     43  * invalid values. The client should take care when directly addressing the
     44  * values. A call to clamp will assure that the values are within the
     45  * constraints.
     46  *
     47  * @author Mark Powell
     48  * @version $Id: ColorRGBA.java,v 1.29 2007/09/09 18:25:14 irrisor Exp $
     49  */
     50 public final class ColorRGBA implements Savable, Cloneable, java.io.Serializable {
     51 
     52     static final long serialVersionUID = 1;
     53     /**
     54      * the color black (0,0,0).
     55      */
     56     public static final ColorRGBA Black = new ColorRGBA(0f, 0f, 0f, 1f);
     57     /**
     58      * the color white (1,1,1).
     59      */
     60     public static final ColorRGBA White = new ColorRGBA(1f, 1f, 1f, 1f);
     61     /**
     62      * the color gray (.2,.2,.2).
     63      */
     64     public static final ColorRGBA DarkGray = new ColorRGBA(0.2f, 0.2f, 0.2f, 1.0f);
     65     /**
     66      * the color gray (.5,.5,.5).
     67      */
     68     public static final ColorRGBA Gray = new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f);
     69     /**
     70      * the color gray (.8,.8,.8).
     71      */
     72     public static final ColorRGBA LightGray = new ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f);
     73     /**
     74      * the color red (1,0,0).
     75      */
     76     public static final ColorRGBA Red = new ColorRGBA(1f, 0f, 0f, 1f);
     77     /**
     78      * the color green (0,1,0).
     79      */
     80     public static final ColorRGBA Green = new ColorRGBA(0f, 1f, 0f, 1f);
     81     /**
     82      * the color blue (0,0,1).
     83      */
     84     public static final ColorRGBA Blue = new ColorRGBA(0f, 0f, 1f, 1f);
     85     /**
     86      * the color yellow (1,1,0).
     87      */
     88     public static final ColorRGBA Yellow = new ColorRGBA(1f, 1f, 0f, 1f);
     89     /**
     90      * the color magenta (1,0,1).
     91      */
     92     public static final ColorRGBA Magenta = new ColorRGBA(1f, 0f, 1f, 1f);
     93     /**
     94      * the color cyan (0,1,1).
     95      */
     96     public static final ColorRGBA Cyan = new ColorRGBA(0f, 1f, 1f, 1f);
     97     /**
     98      * the color orange (251/255, 130/255,0).
     99      */
    100     public static final ColorRGBA Orange = new ColorRGBA(251f / 255f, 130f / 255f, 0f, 1f);
    101     /**
    102      * the color brown (65/255, 40/255, 25/255).
    103      */
    104     public static final ColorRGBA Brown = new ColorRGBA(65f / 255f, 40f / 255f, 25f / 255f, 1f);
    105     /**
    106      * the color pink (1, 0.68, 0.68).
    107      */
    108     public static final ColorRGBA Pink = new ColorRGBA(1f, 0.68f, 0.68f, 1f);
    109     /**
    110      * the black color with no alpha (0, 0, 0, 0);
    111      */
    112     public static final ColorRGBA BlackNoAlpha = new ColorRGBA(0f, 0f, 0f, 0f);
    113     /**
    114      * The red component of the color.
    115      */
    116     public float r;
    117     /**
    118      * The green component of the color.
    119      */
    120     public float g;
    121     /**
    122      * the blue component of the color.
    123      */
    124     public float b;
    125     /**
    126      * the alpha component of the color. 0 is transparent and 1 is opaque
    127      */
    128     public float a;
    129 
    130     /**
    131      * Constructor instantiates a new <code>ColorRGBA</code> object. This
    132      * color is the default "white" with all values 1.
    133      *
    134      */
    135     public ColorRGBA() {
    136         r = g = b = a = 1.0f;
    137     }
    138 
    139     /**
    140      * Constructor instantiates a new <code>ColorRGBA</code> object. The
    141      * values are defined as passed parameters. These values are then clamped
    142      * to insure that they are between 0 and 1.
    143      * @param r the red component of this color.
    144      * @param g the green component of this color.
    145      * @param b the blue component of this color.
    146      * @param a the alpha component of this color.
    147      */
    148     public ColorRGBA(float r, float g, float b, float a) {
    149         this.r = r;
    150         this.g = g;
    151         this.b = b;
    152         this.a = a;
    153     }
    154 
    155     /**
    156      * Copy constructor creates a new <code>ColorRGBA</code> object, based on
    157      * a provided color.
    158      * @param rgba the <code>ColorRGBA</code> object to copy.
    159      */
    160     public ColorRGBA(ColorRGBA rgba) {
    161         this.a = rgba.a;
    162         this.r = rgba.r;
    163         this.g = rgba.g;
    164         this.b = rgba.b;
    165     }
    166 
    167     /**
    168      *
    169      * <code>set</code> sets the RGBA values of this color. The values are then
    170      * clamped to insure that they are between 0 and 1.
    171      *
    172      * @param r the red component of this color.
    173      * @param g the green component of this color.
    174      * @param b the blue component of this color.
    175      * @param a the alpha component of this color.
    176      * @return this
    177      */
    178     public ColorRGBA set(float r, float g, float b, float a) {
    179         this.r = r;
    180         this.g = g;
    181         this.b = b;
    182         this.a = a;
    183         return this;
    184     }
    185 
    186     /**
    187      * <code>set</code> sets the values of this color to those set by a parameter
    188      * color.
    189      *
    190      * @param rgba ColorRGBA the color to set this color to.
    191      * @return this
    192      */
    193     public ColorRGBA set(ColorRGBA rgba) {
    194         if (rgba == null) {
    195             r = 0;
    196             g = 0;
    197             b = 0;
    198             a = 0;
    199         } else {
    200             r = rgba.r;
    201             g = rgba.g;
    202             b = rgba.b;
    203             a = rgba.a;
    204         }
    205         return this;
    206     }
    207 
    208     /**
    209      * <code>clamp</code> insures that all values are between 0 and 1. If any
    210      * are less than 0 they are set to zero. If any are more than 1 they are
    211      * set to one.
    212      *
    213      */
    214     public void clamp() {
    215         if (r < 0) {
    216             r = 0;
    217         } else if (r > 1) {
    218             r = 1;
    219         }
    220 
    221         if (g < 0) {
    222             g = 0;
    223         } else if (g > 1) {
    224             g = 1;
    225         }
    226 
    227         if (b < 0) {
    228             b = 0;
    229         } else if (b > 1) {
    230             b = 1;
    231         }
    232 
    233         if (a < 0) {
    234             a = 0;
    235         } else if (a > 1) {
    236             a = 1;
    237         }
    238     }
    239 
    240     /**
    241      *
    242      * <code>getColorArray</code> retrieves the color values of this object as
    243      * a four element float array.
    244      * @return the float array that contains the color elements.
    245      */
    246     public float[] getColorArray() {
    247         return new float[]{r, g, b, a};
    248     }
    249 
    250     /**
    251      * Stores the current r/g/b/a values into the tempf array.  The tempf array must have a
    252      * length of 4 or greater, or an array index out of bounds exception will be thrown.
    253      * @param store The array of floats to store the values into.
    254      * @return The float[] after storage.
    255      */
    256     public float[] getColorArray(float[] store) {
    257         store[0] = r;
    258         store[1] = g;
    259         store[2] = b;
    260         store[3] = a;
    261         return store;
    262     }
    263 
    264     public float getAlpha() {
    265         return a;
    266     }
    267 
    268     public float getRed() {
    269         return r;
    270     }
    271 
    272     public float getBlue() {
    273         return b;
    274     }
    275 
    276     public float getGreen() {
    277         return g;
    278     }
    279 
    280     /**
    281      * Sets this color to the interpolation by changeAmnt from this to the finalColor
    282      * this=(1-changeAmnt)*this + changeAmnt * finalColor
    283      * @param finalColor The final color to interpolate towards
    284      * @param changeAmnt An amount between 0.0 - 1.0 representing a precentage
    285      *  change from this towards finalColor
    286      */
    287     public void interpolate(ColorRGBA finalColor, float changeAmnt) {
    288         this.r = (1 - changeAmnt) * this.r + changeAmnt * finalColor.r;
    289         this.g = (1 - changeAmnt) * this.g + changeAmnt * finalColor.g;
    290         this.b = (1 - changeAmnt) * this.b + changeAmnt * finalColor.b;
    291         this.a = (1 - changeAmnt) * this.a + changeAmnt * finalColor.a;
    292     }
    293 
    294     /**
    295      * Sets this color to the interpolation by changeAmnt from beginColor to finalColor
    296      * this=(1-changeAmnt)*beginColor + changeAmnt * finalColor
    297      * @param beginColor The begining color (changeAmnt=0)
    298      * @param finalColor The final color to interpolate towards (changeAmnt=1)
    299      * @param changeAmnt An amount between 0.0 - 1.0 representing a precentage
    300      *  change from beginColor towards finalColor
    301      */
    302     public void interpolate(ColorRGBA beginColor, ColorRGBA finalColor, float changeAmnt) {
    303         this.r = (1 - changeAmnt) * beginColor.r + changeAmnt * finalColor.r;
    304         this.g = (1 - changeAmnt) * beginColor.g + changeAmnt * finalColor.g;
    305         this.b = (1 - changeAmnt) * beginColor.b + changeAmnt * finalColor.b;
    306         this.a = (1 - changeAmnt) * beginColor.a + changeAmnt * finalColor.a;
    307     }
    308 
    309     /**
    310      *
    311      * <code>randomColor</code> is a utility method that generates a random
    312      * color.
    313      *
    314      * @return a random color.
    315      */
    316     public static ColorRGBA randomColor() {
    317         ColorRGBA rVal = new ColorRGBA(0, 0, 0, 1);
    318         rVal.r = FastMath.nextRandomFloat();
    319         rVal.g = FastMath.nextRandomFloat();
    320         rVal.b = FastMath.nextRandomFloat();
    321         return rVal;
    322     }
    323 
    324     /**
    325      * Multiplies each r/g/b/a of this color by the r/g/b/a of the given color and
    326      * returns the result as a new ColorRGBA.  Used as a way of combining colors and lights.
    327      * @param c The color to multiply.
    328      * @return The new ColorRGBA.  this*c
    329      */
    330     public ColorRGBA mult(ColorRGBA c) {
    331         return new ColorRGBA(c.r * r, c.g * g, c.b * b, c.a * a);
    332     }
    333 
    334     /**
    335      * Multiplies each r/g/b/a of this color by the given scalar and
    336      * returns the result as a new ColorRGBA.  Used as a way of making colors dimmer
    337      * or brighter..
    338      * @param scalar The scalar to multiply.
    339      * @return The new ColorRGBA.  this*scalar
    340      */
    341     public ColorRGBA mult(float scalar) {
    342         return new ColorRGBA(scalar * r, scalar * g, scalar * b, scalar * a);
    343     }
    344 
    345     /**
    346      * Multiplies each r/g/b/a of this color by the r/g/b/a of the given color and
    347      * returns the result as a new ColorRGBA.  Used as a way of combining colors and lights.
    348      * @param scalar scalar to multiply with
    349      * @return The new ColorRGBA.  this*c
    350      */
    351     public ColorRGBA multLocal(float scalar) {
    352         this.r *= scalar;
    353         this.g *= scalar;
    354         this.b *= scalar;
    355         this.a *= scalar;
    356         return this;
    357     }
    358 
    359     /**
    360      * Adds each r/g/b/a of this color by the r/g/b/a of the given color and
    361      * returns the result as a new ColorRGBA.
    362      * @param c The color to add.
    363      * @return The new ColorRGBA.  this+c
    364      */
    365     public ColorRGBA add(ColorRGBA c) {
    366         return new ColorRGBA(c.r + r, c.g + g, c.b + b, c.a + a);
    367     }
    368 
    369     /**
    370      * Multiplies each r/g/b/a of this color by the r/g/b/a of the given color and
    371      * returns the result as a new ColorRGBA.  Used as a way of combining colors and lights.
    372      * @param c The color to multiply.
    373      * @return The new ColorRGBA.  this*c
    374      */
    375     public ColorRGBA addLocal(ColorRGBA c) {
    376         set(c.r + r, c.g + g, c.b + b, c.a + a);
    377         return this;
    378     }
    379 
    380     /**
    381      * <code>toString</code> returns the string representation of this color.
    382      * The format of the string is:<br>
    383      * <Class Name>: [R=RR.RRRR, G=GG.GGGG, B=BB.BBBB, A=AA.AAAA]
    384      * @return the string representation of this color.
    385      */
    386     public String toString() {
    387         return "Color[" + r + ", " + g + ", " + b + ", " + a + "]";
    388     }
    389 
    390     @Override
    391     public ColorRGBA clone() {
    392         try {
    393             return (ColorRGBA) super.clone();
    394         } catch (CloneNotSupportedException e) {
    395             throw new AssertionError(); // can not happen
    396         }
    397     }
    398 
    399     /**
    400      * Saves this ColorRGBA into the given float[] object.
    401      *
    402      * @param floats
    403      *            The float[] to take this ColorRGBA. If null, a new float[4] is
    404      *            created.
    405      * @return The array, with R, G, B, A float values in that order
    406      */
    407     public float[] toArray(float[] floats) {
    408         if (floats == null) {
    409             floats = new float[4];
    410         }
    411         floats[0] = r;
    412         floats[1] = g;
    413         floats[2] = b;
    414         floats[3] = a;
    415         return floats;
    416     }
    417 
    418     /**
    419      * <code>equals</code> returns true if this color is logically equivalent
    420      * to a given color. That is, if the values of the two colors are the same.
    421      * False is returned otherwise.
    422      * @param o the object to compare againts.
    423      * @return true if the colors are equal, false otherwise.
    424      */
    425     public boolean equals(Object o) {
    426         if (!(o instanceof ColorRGBA)) {
    427             return false;
    428         }
    429 
    430         if (this == o) {
    431             return true;
    432         }
    433 
    434         ColorRGBA comp = (ColorRGBA) o;
    435         if (Float.compare(r, comp.r) != 0) {
    436             return false;
    437         }
    438         if (Float.compare(g, comp.g) != 0) {
    439             return false;
    440         }
    441         if (Float.compare(b, comp.b) != 0) {
    442             return false;
    443         }
    444         if (Float.compare(a, comp.a) != 0) {
    445             return false;
    446         }
    447         return true;
    448     }
    449 
    450     /**
    451      * <code>hashCode</code> returns a unique code for this color object based
    452      * on it's values. If two colors are logically equivalent, they will return
    453      * the same hash code value.
    454      * @return the hash code value of this color.
    455      */
    456     public int hashCode() {
    457         int hash = 37;
    458         hash += 37 * hash + Float.floatToIntBits(r);
    459         hash += 37 * hash + Float.floatToIntBits(g);
    460         hash += 37 * hash + Float.floatToIntBits(b);
    461         hash += 37 * hash + Float.floatToIntBits(a);
    462         return hash;
    463     }
    464 
    465     public void write(JmeExporter e) throws IOException {
    466         OutputCapsule capsule = e.getCapsule(this);
    467         capsule.write(r, "r", 0);
    468         capsule.write(g, "g", 0);
    469         capsule.write(b, "b", 0);
    470         capsule.write(a, "a", 0);
    471     }
    472 
    473     public void read(JmeImporter e) throws IOException {
    474         InputCapsule capsule = e.getCapsule(this);
    475         r = capsule.readFloat("r", 0);
    476         g = capsule.readFloat("g", 0);
    477         b = capsule.readFloat("b", 0);
    478         a = capsule.readFloat("a", 0);
    479     }
    480 
    481     public byte[] asBytesRGBA() {
    482         byte[] store = new byte[4];
    483         store[0] = (byte) ((int) (r * 255) & 0xFF);
    484         store[1] = (byte) ((int) (g * 255) & 0xFF);
    485         store[2] = (byte) ((int) (b * 255) & 0xFF);
    486         store[3] = (byte) ((int) (a * 255) & 0xFF);
    487         return store;
    488     }
    489 
    490     public int asIntARGB() {
    491         int argb = (((int) (a * 255) & 0xFF) << 24)
    492                 | (((int) (r * 255) & 0xFF) << 16)
    493                 | (((int) (g * 255) & 0xFF) << 8)
    494                 | (((int) (b * 255) & 0xFF));
    495         return argb;
    496     }
    497 
    498     public int asIntRGBA() {
    499         int rgba = (((int) (r * 255) & 0xFF) << 24)
    500                 | (((int) (g * 255) & 0xFF) << 16)
    501                 | (((int) (b * 255) & 0xFF) << 8)
    502                 | (((int) (a * 255) & 0xFF));
    503         return rgba;
    504     }
    505 
    506     public int asIntABGR() {
    507         int abgr = (((int) (a * 255) & 0xFF) << 24)
    508                 | (((int) (b * 255) & 0xFF) << 16)
    509                 | (((int) (g * 255) & 0xFF) << 8)
    510                 | (((int) (r * 255) & 0xFF));
    511         return abgr;
    512     }
    513 
    514     public void fromIntARGB(int color) {
    515         a = ((byte) (color >> 24) & 0xFF) / 255f;
    516         r = ((byte) (color >> 16) & 0xFF) / 255f;
    517         g = ((byte) (color >> 8) & 0xFF) / 255f;
    518         b = ((byte) (color) & 0xFF) / 255f;
    519     }
    520 
    521     public void fromIntRGBA(int color) {
    522         r = ((byte) (color >> 24) & 0xFF) / 255f;
    523         g = ((byte) (color >> 16) & 0xFF) / 255f;
    524         b = ((byte) (color >> 8) & 0xFF) / 255f;
    525         a = ((byte) (color) & 0xFF) / 255f;
    526     }
    527 
    528     /**
    529      * Transform the current ColorRGBA to a Vector3f using
    530      * x = r, y = g, z = b. The Alpha value is not used.
    531      *
    532      * This method is useful to use for shaders assignment.
    533      * @return A Vector3f containing the RGB value of current color definition.
    534      */
    535     public Vector3f toVector3f() {
    536         return new Vector3f(r, g, b);
    537     }
    538 
    539     /**
    540      * Transform the current ColorRGBA to a Vector4f using
    541      * x = r, y = g, z = b, w = a.
    542      *
    543      * This method is useful to use for shaders assignment.
    544      * @return A Vector4f containing the RGBA value of current color definition.
    545      */
    546     public Vector4f toVector4f() {
    547         return new Vector4f(r, g, b, a);
    548     }
    549 }
    550