Noise.h
上传用户:ghyvgy
上传日期:2009-05-26
资源大小:547k
文件大小:10k
源码类别:

其他游戏

开发平台:

Python

  1. /*
  2. s_p_oneil@hotmail.com
  3. Copyright (c) 2000, Sean O'Neil
  4. All rights reserved.
  5. Redistribution and use in source and binary forms, with or without
  6. modification, are permitted provided that the following conditions are met:
  7. * Redistributions of source code must retain the above copyright notice,
  8.   this list of conditions and the following disclaimer.
  9. * Redistributions in binary form must reproduce the above copyright notice,
  10.   this list of conditions and the following disclaimer in the documentation
  11.   and/or other materials provided with the distribution.
  12. * Neither the name of this project nor the names of its contributors
  13.   may be used to endorse or promote products derived from this software
  14.   without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  19. LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  20. CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  21. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22. INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  23. CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  24. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #ifndef __Noise_h__
  28. #define __Noise_h__
  29. #include <math.h>
  30. #include <float.h>
  31. // Defines
  32. #define PI 3.14159f // PI
  33. #define HALF_PI 1.57080f // PI / 2
  34. #define TWO_PI 6.28318f // PI * 2
  35. #define INV_PI 0.318310f // 1 / PI
  36. #define INV_TWO_PI 0.159155f // 1 / (PI*2)
  37. #define INV_HALF_PI 0.636618f // 1 / (PI/2)
  38. #define LOGHALF -0.693147f // log(0.5)
  39. #define LOGHALFI -1.442695f // Inverse of log(0.5)
  40. #define DELTA 1e-6f // Small number for comparing floating point numbers
  41. #define MAX_DIMENSIONS 4 // Maximum number of dimensions in a noise object
  42. #define MAX_OCTAVES 128 // Maximum # of octaves in an fBm object
  43. #define HALF_RAND (RAND_MAX/2)
  44. // Macros
  45. #define SQUARE(a) ((a) * (a))
  46. #define FLOOR(a) ((int)(a) - ((a) < 0 && (a) != (int)(a)))
  47. #define CEILING(a) ((int)(a) + ((a) > 0 && (a) != (int)(a)))
  48. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  49. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  50. #define ABS(a) ((a) < 0 ? -(a) : (a))
  51. #define CLAMP(a, b, x) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x)))
  52. #define LERP(a, b, x) ((a) + (x) * ((b) - (a)))
  53. #define CUBIC(a) ((a) * (a) * (3 - 2*(a)))
  54. #define STEP(a, x) ((x) >= (a))
  55. #define BOXSTEP(a, b, x) Clamp(0, 1, ((x)-(a))/((b)-(a)))
  56. #define PULSE(a, b, x) (((x) >= (a)) - ((x) >= (b)))
  57. #define GAMMA(a, g) powf(a, 1/g)
  58. #define BIAS(a, b) powf(a, logf(b) * LOGHALFI)
  59. #define EXPOSE(l, k) (1 - expf(l * k))
  60. #define DEGTORAD(x) ((x) * 0.01745329251994f)
  61. #define RADTODEG(x) ((x) * 57.29577951308f)
  62. #define SWAP(a, b, t) { t = a; a = b; b = t; }
  63. // Inline functions (use instead of macros to avoid performing slow operations twice)
  64. inline float Square(float a) { return a * a; }
  65. inline int Floor(float a) { return ((int)a - (a < 0 && a != (int)a)); }
  66. inline int Ceiling(float a) { return ((int)a + (a > 0 && a != (int)a)); }
  67. inline float Min(float a, float b) { return (a < b ? a : b); }
  68. inline float Max(float a, float b) { return (a > b ? a : b); }
  69. inline float Abs(float a) { return (a < 0 ? -a : a); }
  70. inline float Clamp(float a, float b, float x) { return (x < a ? a : (x > b ? b : x)); }
  71. inline float Lerp(float a, float b, float x) { return a + x * (b - a); }
  72. inline float Cubic(float a) { return a * a * (3 - 2*a); }
  73. inline float Step(float a, float x) { return (float)(x >= a); }
  74. inline float Boxstep(float a, float b, float x) { return Clamp(0, 1, (x-a)/(b-a)); }
  75. inline float Pulse(float a, float b, float x) { return (float)((x >= a) - (x >= b)); }
  76. inline float Gamma(float a, float g) { return powf(a, 1/g); }
  77. inline float Bias(float a, float b) { return powf(a, logf(b) * LOGHALFI); }
  78. inline float Expose(float l, float k) { return (1 - expf(-l * k)); }
  79. inline float Gain(float a, float b)
  80. {
  81. if(a <= DELTA)
  82. return 0;
  83. if(a >= 1-DELTA)
  84. return 1;
  85. register float p = (logf(1 - b) * LOGHALFI);
  86. if(a < 0.5)
  87. return powf(2 * a, p) * 0.5f;
  88. else
  89. return 1 - powf(2 * (1 - a), p) * 0.5f;
  90. }
  91. inline float Smoothstep(float a, float b, float x)
  92. {
  93. if(x <= a)
  94. return 0;
  95. if(x >= b)
  96. return 1;
  97. return Cubic((x - a) / (b - a));
  98. }
  99. inline float Mod(float a, float b)
  100. {
  101. a -= ((int)(a / b)) * b;
  102. if(a < 0)
  103. a += b;
  104. return a;
  105. }
  106. inline void Normalize(float *f, int n)
  107. {
  108. float fMagnitude = 0;
  109. for(int i=0; i<n; i++)
  110. fMagnitude += f[i]*f[i];
  111. fMagnitude = 1 / sqrtf(fMagnitude);
  112. for(i=0; i<n; i++)
  113. f[i] *= fMagnitude;
  114. }
  115. /*******************************************************************************
  116. * Class: CRandom
  117. ********************************************************************************
  118. * This class wraps a random number generator. I plan to implement my own random
  119. * number generator so I can keep the seeds as member variables (which is more
  120. * flexible than using statics or globals). I was using one I found on the
  121. * Internet implemented in assembler, but I was having problems with it so I
  122. * removed it for this demo.
  123. *******************************************************************************/
  124. class CRandom
  125. {
  126. public:
  127. CRandom() {}
  128. CRandom(unsigned int nSeed) { Init(nSeed); }
  129. void Init(unsigned int nSeed) { srand(nSeed); }
  130. double Random() { return (double)rand()/(double)RAND_MAX; }
  131. double RandomD(double dMin, double dMax)
  132. {
  133. double dInterval = dMax - dMin;
  134. double d = dInterval * Random();
  135. return dMin + MIN(d, dInterval);
  136. }
  137. unsigned int RandomI(unsigned int nMin, unsigned int nMax)
  138. {
  139. unsigned int nInterval = nMax - nMin;
  140. unsigned int i = (unsigned int)((nInterval+1.0) * Random());
  141. return nMin + MIN(i, nInterval);
  142. }
  143. };
  144. /*******************************************************************************
  145. * Class: CNoise
  146. ********************************************************************************
  147. * This class implements the Perlin noise function. Initialize it with the number
  148. * of dimensions (1 to 4) and a random seed. I got the source for the first 3
  149. * dimensions from "Texturing & Modeling: A Procedural Approach". I added the
  150. * extra dimension because it may be desirable to use 3 spatial dimensions and
  151. * one time dimension. The noise buffers are set up as member variables so that
  152. * there may be several instances of this class in use at the same time, each
  153. * initialized with different parameters.
  154. *******************************************************************************/
  155. class CNoise
  156. {
  157. protected:
  158. int m_nDimensions; // Number of dimensions used by this object
  159. unsigned char m_nMap[256]; // Randomized map of indexes into buffer
  160. float m_nBuffer[256][MAX_DIMENSIONS]; // Random n-dimensional buffer
  161. float Lattice(int ix, float fx, int iy=0, float fy=0, int iz=0, float fz=0, int iw=0, float fw=0)
  162. {
  163. int n[4] = {ix, iy, iz, iw};
  164. float f[4] = {fx, fy, fz, fw};
  165. int nIndex = 0;
  166. for(int i=0; i<m_nDimensions; i++)
  167. nIndex = m_nMap[(nIndex + n[i]) & 0xFF];
  168. float fValue = 0;
  169. for(i=0; i<m_nDimensions; i++)
  170. fValue += m_nBuffer[nIndex][i] * f[i];
  171. return fValue;
  172. }
  173. public:
  174. CNoise() {}
  175. CNoise(int nDimensions, unsigned int nSeed) { Init(nDimensions, nSeed); }
  176. void Init(int nDimensions, unsigned int nSeed);
  177. float Noise(float *f);
  178. };
  179. /*******************************************************************************
  180. * Class: CSeededNoise
  181. ********************************************************************************
  182. *******************************************************************************/
  183. class CSeededNoise
  184. {
  185. protected:
  186. float m_nBuffer[64][64];
  187. float Lattice(int ix, float fx, int iy=0, float fy=0, int iz=0, float fz=0)
  188. {
  189. float fValue = m_nBuffer[ix][iy];
  190. return fValue;
  191. }
  192. public:
  193. CSeededNoise() {}
  194. CSeededNoise(unsigned int nSeed) { Init(nSeed); }
  195. void Init(unsigned int nSeed);
  196. float Noise(float *f);
  197. };
  198. /*******************************************************************************
  199. * Class: CFractal
  200. ********************************************************************************
  201. * This class implements fBm, or fractal Brownian motion. Since fBm uses Perlin
  202. * noise, this class is derived from CNoise. Initialize it with the number of
  203. * dimensions (1 to 4), a random seed, H (roughness ranging from 0 to 1), and
  204. * the lacunarity (2.0 is often used). Many of the fractal routines came from
  205. * "Texturing & Modeling: A Procedural Approach". fBmTest() is my own creation,
  206. * and I created it to generate my first planet.
  207. *******************************************************************************/
  208. class CFractal : public CNoise
  209. {
  210. protected:
  211. float m_fH;
  212. float m_fLacunarity;
  213. float m_fExponent[MAX_OCTAVES];
  214. public:
  215. CFractal() {}
  216. CFractal(int nDimensions, unsigned int nSeed, float fH, float fLacunarity)
  217. {
  218. Init(nDimensions, nSeed, fH, fLacunarity);
  219. }
  220. void Init(int nDimensions, unsigned int nSeed, float fH, float fLacunarity)
  221. {
  222. CNoise::Init(nDimensions, nSeed);
  223. m_fH = fH;
  224. m_fLacunarity = fLacunarity;
  225. float f = 1;
  226. for(int i=0; i<MAX_OCTAVES; i++) 
  227. {
  228. m_fExponent[i] = powf(f, -m_fH);
  229. f *= m_fLacunarity;
  230. }
  231. }
  232. float fBm(float *f, float fOctaves);
  233. float Turbulence(float *f, float fOctaves);
  234. float Multifractal(float *f, float fOctaves, float fOffset);
  235. float Heterofractal(float *f, float fOctaves, float fOffset);
  236. float HybridMultifractal(float *f, float fOctaves, float fOffset, float fGain);
  237. float RidgedMultifractal(float *f, float fOctaves, float fOffset, float fThreshold);
  238. float fBmTest(float *f, int nStart, int nEnd, float fInitial=0.0f);
  239. float fBmTest(float *f, float fOctaves);
  240. };
  241. #endif // __Noise_h__