/starLiGHT.Engine/starLiGHT.Noise/Utils/ColorGradient.cs
C# | 297 lines | 119 code | 29 blank | 149 comment | 16 complexity | ed3d9bf6f0c193eed324203739d342af MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0
- #region COPYRIGHT
- //--------------------------------------------------------------------------------
- // <copyright file="ColorGradient.cs" company="starLiGHT Entertainment Studios">
- // Copyright (c) 2007, 2008, 2009, 2010, 2011
- // Roland Rosenkranz (Glatzemann@email.de)
- //
- // Based on libnoise by Jason Bevins
- // Copyright (C) 2003, 2004 Jason Bevins (licensed under LGPL)
- // </copyright>
- // <license>
- // This file is part of starLiGHT.Noise.
- //
- // starLiGHT.Noise is free software: you can redistribute it and/or modify
- // it under the terms of the GNU Lesser General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // starLiGHT.Noise is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU Lesser General Public License for more details.
- //
- // You should have received a copy of the GNU Lesser General Public License
- // along with starLiGHT.Noise. If not, see http://www.gnu.org/licenses/.
- //
- // ADDITIONAL (commercial) LICENSES for starLiGHT.Noise are available on request.
- // </license>
- // <version>
- // **************[ starLiGHT.Engine SVN ]**********************
- // * $Rev:: 10385 $: Revision of last commit *
- // * $Author:: unknown $: Author of last commit *
- // * $Date:: 2011-06-14 07:59:17 #$: Date of last commit *
- // ************************************************************
- // </version>
- //--------------------------------------------------------------------------------
- #endregion
-
- namespace starLiGHT.Noise.Noise
- {
- #region Using Statements
- using System;
- using System.Collections.Generic;
- using System.Text;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Graphics;
-
- #endregion
-
- /// Defines a color gradient.
- ///
- /// A color gradient is a list of gradually-changing colors. A color
- /// gradient is defined by a list of <i>gradient points</i>. Each
- /// gradient point has a position and a color. In a color gradient, the
- /// colors between two adjacent gradient points are linearly interpolated.
- ///
- /// To add a gradient point to the color gradient, pass its position and
- /// color to the AddGradientPoint() method.
- ///
- /// To retrieve a color from a specific position in the color gradient,
- /// pass that position to the GetColor() method.
- ///
- /// This class is a useful tool for coloring height maps based on
- /// elevation.
- ///
- /// <b>Gradient example</b>
- ///
- /// Suppose a gradient object contains the following gradient points:
- /// - -1.0 maps to black.
- /// - 0.0 maps to white.
- /// - 1.0 maps to red.
- ///
- /// If an application passes -0.5 to the GetColor() method, this method
- /// will return a gray color that is halfway between black and white.
- ///
- /// If an application passes 0.25 to the GetColor() method, this method
- /// will return a very light pink color that is one quarter of the way
- /// between white and red.
- class GradientColor
- {
- /// Number of gradient points.
- private int gradientPointCount;
-
- /// Array that stores the gradient points.
- private List<GradientPoint> gradientPoints;
-
- /// A color object that is used by a gradient object to store a
- /// temporary value.
- private Color workingColor;
-
- /// Constructor.
- public GradientColor()
- {
- this.gradientPoints = null;
- }
-
- /// Adds a gradient point to this gradient object.
- ///
- /// @param gradientPos The position of this gradient point.
- /// @param gradientColor The color of this gradient point.
- ///
- /// @pre No two gradient points have the same position.
- ///
- /// @throw noise::ExceptionInvalidParam See the precondition.
- ///
- /// It does not matter which order these gradient points are added.
- public void AddGradientPoint(double gradientPos, Color gradientColor)
- {
- int insertionPos = this.FindInsertionPos(gradientPos);
- this.InsertAtPos(insertionPos, gradientPos, gradientColor);
- }
-
- /// Deletes all the gradient points from this gradient object.
- ///
- /// @post All gradient points from this gradient object are deleted.
- public void Clear()
- {
- this.gradientPoints = null;
- this.gradientPointCount = 0;
- }
-
- /// Returns the color at the specified position in the color gradient.
- ///
- /// @param gradientPos The specified position.
- ///
- /// @returns The color at that position.
- public Color GetColor(double gradientPos)
- {
- ////assert (this.gradientPointCount >= 2);
-
- // Find the first element in the gradient point array that has a gradient
- // position larger than the gradient position passed to this method.
- int indexPos;
- for (indexPos = 0; indexPos < this.gradientPointCount; indexPos++)
- {
- if (gradientPos < this.gradientPoints[indexPos].pos)
- {
- break;
- }
- }
-
- // Find the two nearest gradient points so that we can perform linear
- // interpolation on the color.
- int index0 = this.ClampValue(indexPos - 1, 0, this.gradientPoints.Count - 1);
- int index1 = this.ClampValue(indexPos, 0, this.gradientPoints.Count - 1);
-
- // If some gradient points are missing (which occurs if the gradient
- // position passed to this method is greater than the largest gradient
- // position or less than the smallest gradient position in the array), get
- // the corresponding gradient color of the nearest gradient point and exit
- // now.
- if (index0 == index1)
- {
- this.workingColor = this.gradientPoints[index1].color;
- return this.workingColor;
- }
-
- // Compute the alpha value used for linear interpolation.
- double input0 = this.gradientPoints[index0].pos;
- double input1 = this.gradientPoints[index1].pos;
- double alpha = (gradientPos - input0) / (input1 - input0);
-
- // Now perform the linear interpolation given the alpha value.
- Color color0 = this.gradientPoints[index0].color;
- Color color1 = this.gradientPoints[index1].color;
- this.workingColor = this.LinearInterpColor(color0, color1, (float)alpha);
- return this.workingColor;
- }
-
- /// Returns a pointer to the array of gradient points in this object.
- ///
- /// @returns A pointer to the array of gradient points.
- ///
- /// Before calling this method, call GetGradientPointCount() to
- /// determine the number of gradient points in this array.
- ///
- /// It is recommended that an application does not store this pointer
- /// for later use since the pointer to the array may change if the
- /// application calls another method of this object.
- public List<GradientPoint> GetGradientPointArray()
- {
- return this.gradientPoints;
- }
-
- /// Returns the number of gradient points stored in this object.
- ///
- /// @returns The number of gradient points stored in this object.
- public int GetGradientPointCount()
- {
- return this.gradientPoints.Count;
- }
-
- /// Determines the array index in which to insert the gradient point
- /// into the internal gradient-point array.
- ///
- /// @param gradientPos The position of this gradient point.
- ///
- /// @returns The array index in which to insert the gradient point.
- ///
- /// @pre No two gradient points have the same input value.
- ///
- /// @throw noise::ExceptionInvalidParam See the precondition.
- ///
- /// By inserting the gradient point at the returned array index, this
- /// object ensures that the gradient-point array is sorted by input
- /// value. The code that maps a value to a color requires a sorted
- /// gradient-point array.
- private int FindInsertionPos(double gradientPos)
- {
- if (this.gradientPoints == null) this.gradientPoints = new List<GradientPoint>();
-
- int insertionPos;
- for (insertionPos = 0; insertionPos < this.gradientPoints.Count; insertionPos++)
- {
- if (gradientPos < this.gradientPoints[insertionPos].pos)
- {
- // We found the array index in which to insert the new gradient point.
- // Exit now.
- break;
- }
- else if (gradientPos == this.gradientPoints[insertionPos].pos)
- {
- // Each gradient point is required to contain a unique gradient
- // position, so throw an exception.
- throw new Exception("invalid params");
- }
- }
- return insertionPos;
- }
-
- /// Inserts the gradient point at the specified position in the
- /// internal gradient-point array.
- ///
- /// @param insertionPos The zero-based array position in which to
- /// insert the gradient point.
- /// @param gradientPos The position of this gradient point.
- /// @param gradientColor The color of this gradient point.
- ///
- /// To make room for this new gradient point, this method reallocates
- /// the gradient-point array and shifts all gradient points occurring
- /// after the insertion position up by one.
- ///
- /// Because this object requires that all gradient points in the array
- /// must be sorted by the position, the new gradient point should be
- /// inserted at the position in which the order is still preserved.
- private void InsertAtPos(int insertionPos, double gradientPos, Color gradientColor)
- {
- if (this.gradientPoints == null) this.gradientPoints = new List<GradientPoint>();
-
- GradientPoint gp = new GradientPoint();
- gp.pos = gradientPos;
- gp.color = gradientColor;
- this.gradientPoints.Insert(insertionPos, gp);
- this.gradientPointCount++;
- }
-
- int ClampValue(int value, int begin, int end)
- {
- if (value < begin)
- value = begin;
- else if (value > end)
- value = end;
-
- return value;
- }
-
- // Performs linear interpolation between two colors and stores the result
- // in out.
- Color LinearInterpColor(Color color0, Color color1, float alpha)
- {
- ////////TODO: diese Funktion prüfen...
-
- Color outCol;
-
- float a = this.BlendChannel(color0.A, color1.A, alpha);
- float b = this.BlendChannel(color0.B, color1.B, alpha);
- float g = this.BlendChannel(color0.G, color1.G, alpha);
- float r = this.BlendChannel(color0.R, color1.R, alpha);
-
- #if XNA4
- outCol = new Color(r, g, b) * a;
- #else
- outCol = new Color((byte)r, (byte)g, (byte)b, (byte)a);
- #endif
-
- return outCol;
- }
-
- // Performs linear interpolation between two 8-bit channel values.
- float BlendChannel(float channel0, float channel1, float alpha)
- {
- float c0 = channel0 / 255.0f;
- float c1 = channel1 / 255.0f;
- return ((c1 * alpha) + (c0 * (1.0f - alpha))) * 255.0f;
- }
- }
- }
-