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