/** * @file v3color.h * @brief LLColor3 class header file. * * $LicenseInfo:firstyear=2001&license=viewergpl$ * * Copyright (c) 2001-2007, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ #ifndef LL_V3COLOR_H #define LL_V3COLOR_H class LLColor4; class LLVector4; #include "llerror.h" #include "llmath.h" #include "llsd.h" // LLColor3 = |r g b| static const U32 LENGTHOFCOLOR3 = 3; class LLColor3 { public: F32 mV[LENGTHOFCOLOR3]; static LLColor3 white; static LLColor3 black; static LLColor3 grey; public: LLColor3(); // Initializes LLColor3 to (0, 0, 0) LLColor3(F32 r, F32 g, F32 b); // Initializes LLColor3 to (r, g, b) LLColor3(const F32 *vec); // Initializes LLColor3 to (vec[0]. vec[1], vec[2]) LLColor3(char *color_string); // html format color ie "#FFDDEE" explicit LLColor3(const LLColor4& color4); // "explicit" to avoid automatic conversion explicit LLColor3(const LLVector4& vector4); // "explicit" to avoid automatic conversion LLColor3(const LLSD& sd); LLSD getValue() const { LLSD ret; ret[0] = mV[0]; ret[1] = mV[1]; ret[2] = mV[2]; return ret; } void setValue(const LLSD& sd) { mV[0] = (F32) sd[0].asReal();; mV[1] = (F32) sd[1].asReal();; mV[2] = (F32) sd[2].asReal();; } void calcHSL(F32* hue, F32* saturation, F32* luminance) const; const LLColor3& setToBlack(); // Clears LLColor3 to (0, 0, 0) const LLColor3& setToWhite(); // Zero LLColor3 to (0, 0, 0) const LLColor3& setVec(F32 x, F32 y, F32 z); // Sets LLColor3 to (x, y, z) const LLColor3& setVec(const LLColor3 &vec); // Sets LLColor3 to vec const LLColor3& setVec(const F32 *vec); // Sets LLColor3 to vec F32 magVec() const; // Returns magnitude of LLColor3 F32 magVecSquared() const; // Returns magnitude squared of LLColor3 F32 normVec(); // Normalizes and returns the magnitude of LLColor3 F32 brightness() const; // Returns brightness of LLColor3 const LLColor3& operator=(const LLColor4 &a); friend std::ostream& operator<<(std::ostream& s, const LLColor3 &a); // Print a friend LLColor3 operator+(const LLColor3 &a, const LLColor3 &b); // Return vector a + b friend LLColor3 operator-(const LLColor3 &a, const LLColor3 &b); // Return vector a minus b friend const LLColor3& operator+=(LLColor3 &a, const LLColor3 &b); // Return vector a + b friend const LLColor3& operator-=(LLColor3 &a, const LLColor3 &b); // Return vector a minus b friend const LLColor3& operator*=(LLColor3 &a, const LLColor3 &b); friend LLColor3 operator*(const LLColor3 &a, const LLColor3 &b); // Return component wise a * b friend LLColor3 operator*(const LLColor3 &a, F32 k); // Return a times scaler k friend LLColor3 operator*(F32 k, const LLColor3 &a); // Return a times scaler k friend bool operator==(const LLColor3 &a, const LLColor3 &b); // Return a == b friend bool operator!=(const LLColor3 &a, const LLColor3 &b); // Return a != b friend const LLColor3& operator*=(LLColor3 &a, F32 k); // Return a times scaler k friend LLColor3 operator-(const LLColor3 &a); // Return vector 1-rgb (inverse) inline void clamp(); inline void exp(); // Do an exponential on the color }; LLColor3 lerp(const LLColor3 &a, const LLColor3 &b, F32 u); void LLColor3::clamp() { // Clamp the color... if (mV[0] < 0.f) { mV[0] = 0.f; } else if (mV[0] > 1.f) { mV[0] = 1.f; } if (mV[1] < 0.f) { mV[1] = 0.f; } else if (mV[1] > 1.f) { mV[1] = 1.f; } if (mV[2] < 0.f) { mV[2] = 0.f; } else if (mV[2] > 1.f) { mV[2] = 1.f; } } // Non-member functions F32 distVec(const LLColor3 &a, const LLColor3 &b); // Returns distance between a and b F32 distVec_squared(const LLColor3 &a, const LLColor3 &b);// Returns distance sqaured between a and b inline LLColor3::LLColor3(void) { mV[0] = 0.f; mV[1] = 0.f; mV[2] = 0.f; } inline LLColor3::LLColor3(F32 r, F32 g, F32 b) { mV[VX] = r; mV[VY] = g; mV[VZ] = b; } inline LLColor3::LLColor3(const F32 *vec) { mV[VX] = vec[VX]; mV[VY] = vec[VY]; mV[VZ] = vec[VZ]; } #if LL_WINDOWS # pragma warning( disable : 4996 ) // strncpy teh sux0r #endif inline LLColor3::LLColor3(char* color_string) // takes a string of format "RRGGBB" where RR is hex 00..FF { if (strlen(color_string) < 6) /* Flawfinder: ignore */ { mV[0] = 0.f; mV[1] = 0.f; mV[2] = 0.f; return; } static char tempstr[7]; /* Flawfinder: ignore */ strncpy(tempstr,color_string,6); /* Flawfinder: ignore */ tempstr[6] = '\0'; mV[VZ] = (F32)strtol(&tempstr[4],NULL,16)/255.f; tempstr[4] = '\0'; mV[VY] = (F32)strtol(&tempstr[2],NULL,16)/255.f; tempstr[2] = '\0'; mV[VX] = (F32)strtol(&tempstr[0],NULL,16)/255.f; } inline const LLColor3& LLColor3::setToBlack(void) { mV[0] = 0.f; mV[1] = 0.f; mV[2] = 0.f; return (*this); } inline const LLColor3& LLColor3::setToWhite(void) { mV[0] = 1.f; mV[1] = 1.f; mV[2] = 1.f; return (*this); } inline const LLColor3& LLColor3::setVec(F32 r, F32 g, F32 b) { mV[0] = r; mV[1] = g; mV[2] = b; return (*this); } inline const LLColor3& LLColor3::setVec(const LLColor3 &vec) { mV[0] = vec.mV[0]; mV[1] = vec.mV[1]; mV[2] = vec.mV[2]; return (*this); } inline const LLColor3& LLColor3::setVec(const F32 *vec) { mV[0] = vec[0]; mV[1] = vec[1]; mV[2] = vec[2]; return (*this); } inline F32 LLColor3::brightness(void) const { return (mV[0] + mV[1] + mV[2]) / 3.0f; } inline F32 LLColor3::magVec(void) const { return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); } inline F32 LLColor3::magVecSquared(void) const { return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]; } inline F32 LLColor3::normVec(void) { F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); F32 oomag; if (mag) { oomag = 1.f/mag; mV[0] *= oomag; mV[1] *= oomag; mV[2] *= oomag; } return (mag); } inline void LLColor3::exp() { #if 0 mV[0] = ::exp(mV[0]); mV[1] = ::exp(mV[1]); mV[2] = ::exp(mV[2]); #else mV[0] = (F32)LL_FAST_EXP(mV[0]); mV[1] = (F32)LL_FAST_EXP(mV[1]); mV[2] = (F32)LL_FAST_EXP(mV[2]); #endif } inline LLColor3 operator+(const LLColor3 &a, const LLColor3 &b) { return LLColor3( a.mV[0] + b.mV[0], a.mV[1] + b.mV[1], a.mV[2] + b.mV[2]); } inline LLColor3 operator-(const LLColor3 &a, const LLColor3 &b) { return LLColor3( a.mV[0] - b.mV[0], a.mV[1] - b.mV[1], a.mV[2] - b.mV[2]); } inline LLColor3 operator*(const LLColor3 &a, const LLColor3 &b) { return LLColor3( a.mV[0] * b.mV[0], a.mV[1] * b.mV[1], a.mV[2] * b.mV[2]); } inline LLColor3 operator*(const LLColor3 &a, F32 k) { return LLColor3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k ); } inline LLColor3 operator*(F32 k, const LLColor3 &a) { return LLColor3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k ); } inline bool operator==(const LLColor3 &a, const LLColor3 &b) { return ( (a.mV[0] == b.mV[0]) &&(a.mV[1] == b.mV[1]) &&(a.mV[2] == b.mV[2])); } inline bool operator!=(const LLColor3 &a, const LLColor3 &b) { return ( (a.mV[0] != b.mV[0]) ||(a.mV[1] != b.mV[1]) ||(a.mV[2] != b.mV[2])); } inline const LLColor3 &operator*=(LLColor3 &a, const LLColor3 &b) { a.mV[0] *= b.mV[0]; a.mV[1] *= b.mV[1]; a.mV[2] *= b.mV[2]; return a; } inline const LLColor3& operator+=(LLColor3 &a, const LLColor3 &b) { a.mV[0] += b.mV[0]; a.mV[1] += b.mV[1]; a.mV[2] += b.mV[2]; return a; } inline const LLColor3& operator-=(LLColor3 &a, const LLColor3 &b) { a.mV[0] -= b.mV[0]; a.mV[1] -= b.mV[1]; a.mV[2] -= b.mV[2]; return a; } inline const LLColor3& operator*=(LLColor3 &a, F32 k) { a.mV[0] *= k; a.mV[1] *= k; a.mV[2] *= k; return a; } inline LLColor3 operator-(const LLColor3 &a) { return LLColor3( 1.f - a.mV[0], 1.f - a.mV[1], 1.f - a.mV[2] ); } // Non-member functions inline F32 distVec(const LLColor3 &a, const LLColor3 &b) { F32 x = a.mV[0] - b.mV[0]; F32 y = a.mV[1] - b.mV[1]; F32 z = a.mV[2] - b.mV[2]; return fsqrtf( x*x + y*y + z*z ); } inline F32 distVec_squared(const LLColor3 &a, const LLColor3 &b) { F32 x = a.mV[0] - b.mV[0]; F32 y = a.mV[1] - b.mV[1]; F32 z = a.mV[2] - b.mV[2]; return x*x + y*y + z*z; } inline LLColor3 lerp(const LLColor3 &a, const LLColor3 &b, F32 u) { return LLColor3( a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u, a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u); } #endif