PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/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
  1. #region COPYRIGHT
  2. //--------------------------------------------------------------------------------
  3. // <copyright file="ColorGradient.cs" company="starLiGHT Entertainment Studios">
  4. // Copyright (c) 2007, 2008, 2009, 2010, 2011
  5. // Roland Rosenkranz (Glatzemann@email.de)
  6. //
  7. // Based on libnoise by Jason Bevins
  8. // Copyright (C) 2003, 2004 Jason Bevins (licensed under LGPL)
  9. // </copyright>
  10. // <license>
  11. // This file is part of starLiGHT.Noise.
  12. //
  13. // starLiGHT.Noise is free software: you can redistribute it and/or modify
  14. // it under the terms of the GNU Lesser General Public License as published by
  15. // the Free Software Foundation, either version 3 of the License, or
  16. // (at your option) any later version.
  17. //
  18. // starLiGHT.Noise is distributed in the hope that it will be useful,
  19. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. // GNU Lesser General Public License for more details.
  22. //
  23. // You should have received a copy of the GNU Lesser General Public License
  24. // along with starLiGHT.Noise. If not, see http://www.gnu.org/licenses/.
  25. //
  26. // ADDITIONAL (commercial) LICENSES for starLiGHT.Noise are available on request.
  27. // </license>
  28. // <version>
  29. // **************[ starLiGHT.Engine SVN ]**********************
  30. // * $Rev:: 10385 $: Revision of last commit *
  31. // * $Author:: unknown $: Author of last commit *
  32. // * $Date:: 2011-06-14 07:59:17 #$: Date of last commit *
  33. // ************************************************************
  34. // </version>
  35. //--------------------------------------------------------------------------------
  36. #endregion
  37. namespace starLiGHT.Noise.Noise
  38. {
  39. #region Using Statements
  40. using System;
  41. using System.Collections.Generic;
  42. using System.Text;
  43. using Microsoft.Xna.Framework;
  44. using Microsoft.Xna.Framework.Graphics;
  45. #endregion
  46. /// Defines a color gradient.
  47. ///
  48. /// A color gradient is a list of gradually-changing colors. A color
  49. /// gradient is defined by a list of <i>gradient points</i>. Each
  50. /// gradient point has a position and a color. In a color gradient, the
  51. /// colors between two adjacent gradient points are linearly interpolated.
  52. ///
  53. /// To add a gradient point to the color gradient, pass its position and
  54. /// color to the AddGradientPoint() method.
  55. ///
  56. /// To retrieve a color from a specific position in the color gradient,
  57. /// pass that position to the GetColor() method.
  58. ///
  59. /// This class is a useful tool for coloring height maps based on
  60. /// elevation.
  61. ///
  62. /// <b>Gradient example</b>
  63. ///
  64. /// Suppose a gradient object contains the following gradient points:
  65. /// - -1.0 maps to black.
  66. /// - 0.0 maps to white.
  67. /// - 1.0 maps to red.
  68. ///
  69. /// If an application passes -0.5 to the GetColor() method, this method
  70. /// will return a gray color that is halfway between black and white.
  71. ///
  72. /// If an application passes 0.25 to the GetColor() method, this method
  73. /// will return a very light pink color that is one quarter of the way
  74. /// between white and red.
  75. class GradientColor
  76. {
  77. /// Number of gradient points.
  78. private int gradientPointCount;
  79. /// Array that stores the gradient points.
  80. private List<GradientPoint> gradientPoints;
  81. /// A color object that is used by a gradient object to store a
  82. /// temporary value.
  83. private Color workingColor;
  84. /// Constructor.
  85. public GradientColor()
  86. {
  87. this.gradientPoints = null;
  88. }
  89. /// Adds a gradient point to this gradient object.
  90. ///
  91. /// @param gradientPos The position of this gradient point.
  92. /// @param gradientColor The color of this gradient point.
  93. ///
  94. /// @pre No two gradient points have the same position.
  95. ///
  96. /// @throw noise::ExceptionInvalidParam See the precondition.
  97. ///
  98. /// It does not matter which order these gradient points are added.
  99. public void AddGradientPoint(double gradientPos, Color gradientColor)
  100. {
  101. int insertionPos = this.FindInsertionPos(gradientPos);
  102. this.InsertAtPos(insertionPos, gradientPos, gradientColor);
  103. }
  104. /// Deletes all the gradient points from this gradient object.
  105. ///
  106. /// @post All gradient points from this gradient object are deleted.
  107. public void Clear()
  108. {
  109. this.gradientPoints = null;
  110. this.gradientPointCount = 0;
  111. }
  112. /// Returns the color at the specified position in the color gradient.
  113. ///
  114. /// @param gradientPos The specified position.
  115. ///
  116. /// @returns The color at that position.
  117. public Color GetColor(double gradientPos)
  118. {
  119. ////assert (this.gradientPointCount >= 2);
  120. // Find the first element in the gradient point array that has a gradient
  121. // position larger than the gradient position passed to this method.
  122. int indexPos;
  123. for (indexPos = 0; indexPos < this.gradientPointCount; indexPos++)
  124. {
  125. if (gradientPos < this.gradientPoints[indexPos].pos)
  126. {
  127. break;
  128. }
  129. }
  130. // Find the two nearest gradient points so that we can perform linear
  131. // interpolation on the color.
  132. int index0 = this.ClampValue(indexPos - 1, 0, this.gradientPoints.Count - 1);
  133. int index1 = this.ClampValue(indexPos, 0, this.gradientPoints.Count - 1);
  134. // If some gradient points are missing (which occurs if the gradient
  135. // position passed to this method is greater than the largest gradient
  136. // position or less than the smallest gradient position in the array), get
  137. // the corresponding gradient color of the nearest gradient point and exit
  138. // now.
  139. if (index0 == index1)
  140. {
  141. this.workingColor = this.gradientPoints[index1].color;
  142. return this.workingColor;
  143. }
  144. // Compute the alpha value used for linear interpolation.
  145. double input0 = this.gradientPoints[index0].pos;
  146. double input1 = this.gradientPoints[index1].pos;
  147. double alpha = (gradientPos - input0) / (input1 - input0);
  148. // Now perform the linear interpolation given the alpha value.
  149. Color color0 = this.gradientPoints[index0].color;
  150. Color color1 = this.gradientPoints[index1].color;
  151. this.workingColor = this.LinearInterpColor(color0, color1, (float)alpha);
  152. return this.workingColor;
  153. }
  154. /// Returns a pointer to the array of gradient points in this object.
  155. ///
  156. /// @returns A pointer to the array of gradient points.
  157. ///
  158. /// Before calling this method, call GetGradientPointCount() to
  159. /// determine the number of gradient points in this array.
  160. ///
  161. /// It is recommended that an application does not store this pointer
  162. /// for later use since the pointer to the array may change if the
  163. /// application calls another method of this object.
  164. public List<GradientPoint> GetGradientPointArray()
  165. {
  166. return this.gradientPoints;
  167. }
  168. /// Returns the number of gradient points stored in this object.
  169. ///
  170. /// @returns The number of gradient points stored in this object.
  171. public int GetGradientPointCount()
  172. {
  173. return this.gradientPoints.Count;
  174. }
  175. /// Determines the array index in which to insert the gradient point
  176. /// into the internal gradient-point array.
  177. ///
  178. /// @param gradientPos The position of this gradient point.
  179. ///
  180. /// @returns The array index in which to insert the gradient point.
  181. ///
  182. /// @pre No two gradient points have the same input value.
  183. ///
  184. /// @throw noise::ExceptionInvalidParam See the precondition.
  185. ///
  186. /// By inserting the gradient point at the returned array index, this
  187. /// object ensures that the gradient-point array is sorted by input
  188. /// value. The code that maps a value to a color requires a sorted
  189. /// gradient-point array.
  190. private int FindInsertionPos(double gradientPos)
  191. {
  192. if (this.gradientPoints == null) this.gradientPoints = new List<GradientPoint>();
  193. int insertionPos;
  194. for (insertionPos = 0; insertionPos < this.gradientPoints.Count; insertionPos++)
  195. {
  196. if (gradientPos < this.gradientPoints[insertionPos].pos)
  197. {
  198. // We found the array index in which to insert the new gradient point.
  199. // Exit now.
  200. break;
  201. }
  202. else if (gradientPos == this.gradientPoints[insertionPos].pos)
  203. {
  204. // Each gradient point is required to contain a unique gradient
  205. // position, so throw an exception.
  206. throw new Exception("invalid params");
  207. }
  208. }
  209. return insertionPos;
  210. }
  211. /// Inserts the gradient point at the specified position in the
  212. /// internal gradient-point array.
  213. ///
  214. /// @param insertionPos The zero-based array position in which to
  215. /// insert the gradient point.
  216. /// @param gradientPos The position of this gradient point.
  217. /// @param gradientColor The color of this gradient point.
  218. ///
  219. /// To make room for this new gradient point, this method reallocates
  220. /// the gradient-point array and shifts all gradient points occurring
  221. /// after the insertion position up by one.
  222. ///
  223. /// Because this object requires that all gradient points in the array
  224. /// must be sorted by the position, the new gradient point should be
  225. /// inserted at the position in which the order is still preserved.
  226. private void InsertAtPos(int insertionPos, double gradientPos, Color gradientColor)
  227. {
  228. if (this.gradientPoints == null) this.gradientPoints = new List<GradientPoint>();
  229. GradientPoint gp = new GradientPoint();
  230. gp.pos = gradientPos;
  231. gp.color = gradientColor;
  232. this.gradientPoints.Insert(insertionPos, gp);
  233. this.gradientPointCount++;
  234. }
  235. int ClampValue(int value, int begin, int end)
  236. {
  237. if (value < begin)
  238. value = begin;
  239. else if (value > end)
  240. value = end;
  241. return value;
  242. }
  243. // Performs linear interpolation between two colors and stores the result
  244. // in out.
  245. Color LinearInterpColor(Color color0, Color color1, float alpha)
  246. {
  247. ////////TODO: diese Funktion prüfen...
  248. Color outCol;
  249. float a = this.BlendChannel(color0.A, color1.A, alpha);
  250. float b = this.BlendChannel(color0.B, color1.B, alpha);
  251. float g = this.BlendChannel(color0.G, color1.G, alpha);
  252. float r = this.BlendChannel(color0.R, color1.R, alpha);
  253. #if XNA4
  254. outCol = new Color(r, g, b) * a;
  255. #else
  256. outCol = new Color((byte)r, (byte)g, (byte)b, (byte)a);
  257. #endif
  258. return outCol;
  259. }
  260. // Performs linear interpolation between two 8-bit channel values.
  261. float BlendChannel(float channel0, float channel1, float alpha)
  262. {
  263. float c0 = channel0 / 255.0f;
  264. float c1 = channel1 / 255.0f;
  265. return ((c1 * alpha) + (c0 * (1.0f - alpha))) * 255.0f;
  266. }
  267. }
  268. }