1 // TortoiseSVN - a Windows shell extension for easy version control
\r
3 // Copyright (C) 2003-2006 - Stefan Kueng
\r
5 // This program is free software; you can redistribute it and/or
\r
6 // modify it under the terms of the GNU General Public License
\r
7 // as published by the Free Software Foundation; either version 2
\r
8 // of the License, or (at your option) any later version.
\r
10 // This program is distributed in the hope that it will be useful,
\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 // GNU General Public License for more details.
\r
15 // You should have received a copy of the GNU General Public License
\r
16 // along with this program; if not, write to the Free Software Foundation,
\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\r
20 #include "WaterEffect.h"
\r
25 CWaterEffect::CWaterEffect()
\r
33 m_iLightModifier = 10;
\r
38 CWaterEffect::~CWaterEffect()
\r
41 if (m_iBuffer1 != NULL)
\r
42 delete [] m_iBuffer1;
\r
43 if (m_iBuffer2 != NULL)
\r
44 delete [] m_iBuffer2;
\r
50 void CWaterEffect::Create(int iWidth, int iHeight)
\r
52 if (m_iBuffer1 != NULL)
\r
53 delete [] m_iBuffer1;
\r
54 if (m_iBuffer2 != NULL)
\r
55 delete [] m_iBuffer2;
\r
57 m_iBuffer1 = new int[(iWidth*iHeight)];
\r
58 m_iBuffer2 = new int[(iWidth*iHeight)];
\r
61 m_iHeight = iHeight;
\r
69 void CWaterEffect::Blob(int x, int y, int radius, int height, int page)
\r
73 int left, top, right, bottom;
\r
80 pNew = &m_iBuffer1[0];
\r
81 pOld = &m_iBuffer2[0];
\r
85 pNew = &m_iBuffer2[0];
\r
86 pOld = &m_iBuffer1[0];
\r
89 rquad = radius * radius;
\r
92 x = 1 + radius + rand() % (m_iWidth - 2 * radius - 1);
\r
94 y = 1 + radius + rand() % (m_iHeight - 2 * radius - 1);
\r
102 if (x - radius < 1)
\r
103 left -= (x-radius-1);
\r
104 if (y - radius < 1)
\r
105 top -= (y-radius-1);
\r
106 if (x + radius > m_iWidth-1)
\r
107 right -= (x+radius-m_iWidth+1);
\r
108 if (y + radius > m_iHeight-1)
\r
109 bottom-= (y+radius-m_iHeight+1);
\r
111 for(cy = top; cy < bottom; cy++)
\r
114 for(cx = left; cx < right; cx++)
\r
116 if (cx*cx + cyq < rquad)
\r
118 pNew[m_iWidth*(cy+y) + (cx+x)] += height;
\r
124 void CWaterEffect::ClearWater()
\r
126 // clear height fields
\r
127 memset(m_iBuffer1,0, (m_iWidth*m_iHeight)*sizeof(int));
\r
128 memset(m_iBuffer2,0, (m_iWidth*m_iHeight)*sizeof(int));
\r
131 void CWaterEffect::Render(DWORD* pSrcImage, DWORD* pTargetImage)
\r
133 DrawWater(m_iHpage, m_iLightModifier, pSrcImage, pTargetImage);
\r
135 CalcWater(m_iHpage, m_iDensity);
\r
137 //change the field from 0 to 1 and vice versa
\r
142 void CWaterEffect::CalcWater(int npage, int density)
\r
145 int count = m_iWidth + 1;
\r
151 pNew = &m_iBuffer1[0];
\r
152 pOld = &m_iBuffer2[0];
\r
156 pNew = &m_iBuffer2[0];
\r
157 pOld = &m_iBuffer1[0];
\r
162 // a description of the algorithm and an implementation
\r
163 // in 'pseudocode' can be found here:
\r
164 // http://freespace.virgin.net/hugo.elias/graphics/x_water.htm
\r
165 for (y = (m_iHeight-1)*m_iWidth; count < y; count += 2)
\r
167 for (x = count+m_iWidth-2; count < x; count++)
\r
169 // use eight pixels
\r
170 newh = ((pOld[count + m_iWidth]
\r
171 + pOld[count - m_iWidth]
\r
174 + pOld[count - m_iWidth - 1]
\r
175 + pOld[count - m_iWidth + 1]
\r
176 + pOld[count + m_iWidth - 1]
\r
177 + pOld[count + m_iWidth + 1]
\r
181 pNew[count] = newh - (newh >> density);
\r
186 void CWaterEffect::SmoothWater(int npage)
\r
188 //flatten and spread the waves
\r
190 int count = m_iWidth + 1;
\r
197 pNew = &m_iBuffer1[0];
\r
198 pOld = &m_iBuffer2[0];
\r
202 pNew = &m_iBuffer2[0];
\r
203 pOld = &m_iBuffer1[0];
\r
208 // a description of the algorithm and an implementation
\r
209 // in 'pseudocode' can be found here:
\r
210 // http://freespace.virgin.net/hugo.elias/graphics/x_water.htm
\r
211 for(y=1; y<m_iHeight-1; y++)
\r
213 for(x=1; x<m_iWidth-1; x++)
\r
215 newh = ((pOld[count + m_iWidth]
\r
216 + pOld[count - m_iWidth]
\r
219 + pOld[count - m_iWidth - 1]
\r
220 + pOld[count - m_iWidth + 1]
\r
221 + pOld[count + m_iWidth - 1]
\r
222 + pOld[count + m_iWidth + 1]
\r
226 pNew[count] = newh>>1;
\r
233 void CWaterEffect::DrawWater(int /*page*/, int /*LightModifier*/, DWORD* pSrcImage, DWORD* pTargetImage)
\r
239 int offset = m_iWidth + 1;
\r
241 long lBreak = m_iWidth*m_iHeight;
\r
243 int *ptr = &m_iBuffer1[0];
\r
246 for (y = (m_iHeight-1)*m_iWidth; offset < y; offset += 2)
\r
248 for (x = offset + m_iWidth - 2; offset < x; offset++)
\r
250 dx = ptr[offset] - ptr[offset+1];
\r
251 dy = ptr[offset] - ptr[offset+m_iWidth];
\r
253 lIndex = offset + m_iWidth*(dy>>3) + (dx>>3);
\r
254 if (lIndex < lBreak && lIndex > 0)
\r
256 c = pSrcImage[lIndex];
\r
257 c = GetShiftedColor(c,dx);
\r
258 pTargetImage[offset] = c;
\r
262 dx = ptr[offset] - ptr[offset+1];
\r
263 dy = ptr[offset] - ptr[offset+m_iWidth];
\r
265 lIndex = offset + m_iWidth*(dy>>3) + (dx>>3);
\r
266 if (lIndex < lBreak && lIndex > 0)
\r
268 c = pSrcImage[lIndex];
\r
269 c = GetShiftedColor(c,dx);
\r
270 pTargetImage[offset] = c;
\r
276 COLORREF CWaterEffect::GetShiftedColor(COLORREF color, int shift)
\r
285 R = GetRValue(color)-shift;
\r
286 G = GetGValue(color)-shift;
\r
287 B = GetBValue(color)-shift;
\r
289 ir = (R < 0) ? 0 : (R > 255) ? 255 : R;
\r
290 ig = (G < 0) ? 0 : (G > 255) ? 255 : G;
\r
291 ib = (B < 0) ? 0 : (B > 255) ? 255 : B;
\r
293 return RGB(ir,ig,ib);
\r