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

其他游戏

开发平台:

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. #include "Master.h"
  28. #include "PixelBuffer.h"
  29. /*
  30. COMPUTING CRATER DIAMETERS FROM EARTH-IMPACTING ASTEROIDS
  31. Astrogeologist Gene Shoemaker proposes the following formula, based on
  32. studies of cratering caused by nuclear tests. Units are MKS unless
  33. otherwise noted; impact energy is sometimes expressed in nuclear bomb
  34. terms (kilotons TNT equivalent) due to the origin of the model.
  35. D = Sg Sp Kn W^(1/3.4)
  36. Crater diameter, meters. On Earth, if D > 3 km, the crater is
  37. assumed to collapse by a factor of 1.3 due to gravity.
  38. Sg = (ge/gt)^(1/6)
  39. Gravity correction factor cited for craters on the Moon. May hold
  40. true for other bodies. ge = 9.8 m/s^2 is Earth gravity, gt is
  41. gravity of the target body.
  42. Sp = (pa/pt)^(1/3.4)
  43. Density correction factor for target material relative to the Jangle
  44. U nuclear crater site. pa = 1.8e3 kg/m^3 (1.8 gm/cm^3) for alluvium,
  45. pt = density at the impact site. For reference, average rock on the
  46. continental shields has a density of 2.6e3 kg/m^3 (2.6 gm/cm^3).
  47. Kn = 74 m / (kiloton TNT equivalent)^(1/3.4)
  48. Empirically determined scaling factor from bomb yield to crater
  49. diameter at Jangle U.
  50. W = Ke / (4.185e12 joules/KT)
  51. Kinetic energy of asteroid, kilotons TNT equivalent.
  52. Ke = 1/2 m v^2
  53. Kinetic energy of asteroid, joules.
  54. v = impact velocity of asteroid, m/s.
  55. 2e4 m/s (20 km/s) is common for an asteroid in an Earth-crossing
  56. orbit.
  57. m = 4/3 pi r^3 rho
  58. Mass of asteroid, kg.
  59. r = radius of asteroid, m
  60. rho = density of asteroid, kg/m^3
  61. 3.3e3 kg/m^3 (3 gm/cm^3) is reasonable for a common S-type asteroid.
  62. For an example, let's work the body which created the 1.1 km diameter
  63. Barringer Meteor Crater in Arizona (in reality the model was run
  64. backwards from the known crater size to estimate the meteor size, but
  65. this is just to show how the math works):
  66. r = 40 m     Meteor radius
  67. rho = 7.8e3 kg/m^3  Density of nickel-iron meteor
  68. v = 2e4 m/s     Impact velocity characteristic of asteroids in Earth-crossing orbits
  69. pt = 2.3e3 kg/m^3   Density of Arizona at impact site
  70. Sg = 1     No correction for impact on Earth
  71. Sp = (1.8/2.3)^(1/3.4) = .93
  72. m = 4/3 pi 40^3 7.8e3 = 2.61e8 kg
  73. Ke = 1/2 * 2.61e8 kg * (2e4 m/s)^2
  74.    = 5.22e16 joules
  75. W = 5.22e16 / 4.185e12 = 12,470 KT
  76. D = 1 * .93 * 74 * 12470^(1/3.4) = 1100 meters
  77. More generally, one can use (after Gehrels, 1985):
  78. Asteroid     Number of Impact probability  Impact energy as multiple
  79. diameter (km)   Objects    (impacts/year)     of Hiroshima bomb
  80. -------------   --------- ------------------  -------------------------
  81.  10 10   10e-8   1e9 (1 billion)
  82.   1     1e3   10e-6   1e6 (1 million)
  83.   0.1     1e5   10e-4   1e3 (1 thousand)
  84. The Hiroshima explosion is assumed to be 13 kilotons.
  85. Finally, a back of the envelope rule is that an object moving at a speed
  86. of 3 km/s has kinetic energy equal to the explosive energy of an equal
  87. mass of TNT; thus a 10 ton asteroid moving at 30 km/sec would have an
  88. impact energy of (10 ton) (30 km/sec / 3 km/sec)^2 = 1 KT.
  89. Impact craters are divided into two groups based on morphology:
  90. simple craters and complex craters. Simple craters are relatively
  91. small with depth-to-diameter ratios of about 1:5 to 1:7 and a
  92. smooth bowl shape. In larger craters, however, gravity causes the
  93. initially steep crater walls to collapse downward and inward, forming
  94. a complex structure with a central peak or peak ring and a shallower
  95. depth compared to diameter (1:10 to 1:20). The diameter at which
  96. craters become complex depends on the surface gravity of the planet:
  97. The greater the gravity, the smaller the diameter that will produce
  98. a complex structure. On Earth, this transition diameter is 2 to 4
  99. kilometers (1.2 to 2.5 miles) depending on target rock properties;
  100. on the Moon, at one-sixth Earth's gravity, the transition diameter
  101. is 15 to 20 kilometers (9 to 12 miles).
  102. (For objects with diameter >100 meters, as in the Popigai and Chesapeake
  103. Bay impactors, the Earth抯 atmosphere does not have almost any effect on
  104. their mass or velocity.)
  105. Notes: A power function going from 0 to 1 should do the trick
  106. inside the bowl, with depth, wall height, and radius all being
  107. determined first. From the rim outward, it could be a graduated
  108. blend between rim height and actual ground height from 1x to 1.1x
  109. the radius. The power should get lower as the radius gets larger,
  110. making the walls less high and steep (proportionally). Gravity
  111. will determine how quickly the power drops, as well as how soon
  112. a central peak will form. Perhaps the outer peaks start at 50% up
  113. the amount the center goes down, but gravity may pull the walls
  114. lower for larger craters.
  115. */
  116. void CPixelBuffer::MakeRandom(unsigned int nSeed)
  117. {
  118. // Instead of calling Random() to fill a byte every pixel,
  119. // call it every 4 pixels to fill a dword
  120. srand(nSeed);
  121. int nSize = (m_nWidth * m_nHeight * m_nChannels) >> 1;
  122. unsigned short *pDest = (unsigned short *)m_pBuffer;
  123. for(int i=0; i<nSize; i++)
  124. *pDest++ = rand();
  125. }
  126. void CPixelBuffer::MakeNoise(unsigned long nSeed)
  127. {
  128. const unsigned char nMin = 224, nMax = 255;
  129. const float fHalf = (nMax + 1 - nMin) / 2;
  130. CFractal fractal(2, nSeed, 0.5f, 2.0f);
  131. int nHalfWidth = m_nWidth >> 1, nHalfHeight = m_nHeight >> 1;
  132. float f[2];
  133. unsigned char *pBuffer = (unsigned char *)GetBuffer();
  134. for(int y=0; y<m_nHeight; y++)
  135. {
  136. for(int x=0; x<m_nWidth; x++)
  137. {
  138. if(x < nHalfWidth+1 && y < nHalfHeight+1)
  139. {
  140. f[0] = 32.0f * (float)x / (float)m_nWidth;
  141. f[1] = 32.0f * (float)y / (float)m_nHeight;
  142. float fValue = fractal.fBm(f, 4.0f);
  143. unsigned char nValue = (unsigned char)Max(nMin, Min(nMax, ((fValue+1.0f) * fHalf + nMin)));
  144. *pBuffer++ = nValue;
  145. }
  146. else
  147. {
  148. int xTemp = x, yTemp = y;
  149. if(xTemp > nHalfWidth)
  150. xTemp = m_nWidth - xTemp;
  151. if(yTemp > nHalfHeight)
  152. yTemp = m_nHeight - yTemp;
  153. *pBuffer++ = *(unsigned char *)operator()(xTemp, yTemp);
  154. }
  155. }
  156. }
  157. }
  158. void CPixelBuffer::MakeGlow(float fExpose, float fSizeDisc)
  159. {
  160. int i;
  161. int n = 0;
  162. unsigned char nIntensity;
  163. for(int y=0; y<m_nHeight; y++)
  164. {
  165. float fDy = (float)y/(m_nHeight-1) - 0.5f;
  166. for(int x=0; x<m_nWidth; x++)
  167. {
  168. float fDx = (float)x/(m_nWidth-1) - 0.5f;
  169. float fDist = sqrtf(fDx*fDx + fDy*fDy);
  170. float fIntensity = expf(-Max(fDist-fSizeDisc,0)*fExpose);
  171. switch(m_nDataType)
  172. {
  173. case GL_UNSIGNED_BYTE:
  174. nIntensity = (unsigned char)(fIntensity*255 + 0.5f);
  175. for(i=0; i<m_nChannels; i++)
  176. ((unsigned char *)m_pBuffer)[n++] = nIntensity;
  177. break;
  178. case GL_FLOAT:
  179. for(i=0; i<m_nChannels; i++)
  180. ((float *)m_pBuffer)[n++] = fIntensity;
  181. break;
  182. }
  183. }
  184. }
  185. }
  186. #ifdef ATMOSPHERE_2D
  187. void CPixelBuffer::MakeAtmosphere(float fExpose)
  188. {
  189. int i;
  190. int n = 0;
  191. unsigned char nIntensity;
  192. for(int y=0; y<m_nHeight; y++)
  193. {
  194. float fDy = /*(y == 0 || y == m_nHeight-1) ? 0 : */(float)y/(m_nHeight-1) - 0.5f;
  195. for(int x=0; x<m_nWidth; x++)
  196. {
  197. float fDx = /*(x == 0 || x == m_nWidth-1) ? 0 : */(float)x/(m_nWidth-1) - 0.5f;
  198. float fDist = sqrtf(fDx*fDx + fDy*fDy);
  199. float fIntensity = expf(-Max(Abs(0.4f - fDist),0)*fExpose);
  200. if(fDist < 0.4f)
  201. fIntensity = 0.5f + fIntensity*0.5f;
  202. switch(m_nDataType)
  203. {
  204. case GL_UNSIGNED_BYTE:
  205. nIntensity = (unsigned char)(fIntensity*255 + 0.5f);
  206. for(i=0; i<m_nChannels; i++)
  207. ((unsigned char *)m_pBuffer)[n++] = nIntensity;
  208. break;
  209. case GL_FLOAT:
  210. for(i=0; i<m_nChannels; i++)
  211. ((float *)m_pBuffer)[n++] = fIntensity;
  212. break;
  213. }
  214. }
  215. }
  216. }
  217. #else
  218. void CPixelBuffer::MakeAtmosphere(float fExpose)
  219. {
  220. int i;
  221. int n = 0;
  222. unsigned char nIntensity;
  223. for(int x=0; x<m_nWidth; x++)
  224. {
  225. float fDx = /*(x == 0 || x == m_nWidth-1) ? 0 : */(float)x/(m_nWidth-1);
  226. float fDist = sqrtf(fDx*fDx);
  227. float fIntensity = expf(-Max(Abs(0.8f - fDist),0)*fExpose);
  228. if(fDist < 0.8f)
  229. fIntensity = 0.5f + fIntensity*0.5f;
  230. switch(m_nDataType)
  231. {
  232. case GL_UNSIGNED_BYTE:
  233. nIntensity = (unsigned char)(fIntensity*255 + 0.5f);
  234. for(i=0; i<m_nChannels; i++)
  235. ((unsigned char *)m_pBuffer)[n++] = nIntensity;
  236. break;
  237. case GL_FLOAT:
  238. for(i=0; i<m_nChannels; i++)
  239. ((float *)m_pBuffer)[n++] = fIntensity;
  240. break;
  241. }
  242. }
  243. }
  244. #endif
  245. void CPixelBuffer::MakeCloudCell(float fExpose, float fSizeDisc)
  246. {
  247. int i;
  248. int n = 0;
  249. unsigned char nIntensity;
  250. for(int y=0; y<m_nHeight; y++)
  251. {
  252. float fDy = (y+0.5f)/m_nHeight - 0.5f;
  253. for(int x=0; x<m_nWidth; x++)
  254. {
  255. float fDx = (x+0.5f)/m_nWidth - 0.5f;
  256. float fDist = sqrtf(fDx*fDx + fDy*fDy);
  257. float fIntensity = 2 - Min(2, powf(2.0f, Max(fDist-fSizeDisc,0)*fExpose));
  258. switch(m_nDataType)
  259. {
  260. case GL_UNSIGNED_BYTE:
  261. nIntensity = (unsigned char)(fIntensity*255 + 0.5f);
  262. for(i=0; i<m_nChannels; i++)
  263. ((unsigned char *)m_pBuffer)[n++] = nIntensity;
  264. break;
  265. case GL_FLOAT:
  266. for(i=0; i<m_nChannels; i++)
  267. ((float *)m_pBuffer)[n++] = fIntensity;
  268. break;
  269. }
  270. }
  271. }
  272. }