1 #include "pch.h"
2 #include "../ogre/common/RenderConst.h"
3 #include "../ogre/common/Def_Str.h"
4 #include "../ogre/common/CScene.h"
5 #include "settings.h"
6 #include "CApp.h"
7 #include "CGui.h"
8 #include <OgreTerrain.h>
9 #include <OgreHardwarePixelBuffer.h>
10 //#include "../vdrift/settings.h"
11 #include <MyGUI.h>
12 #include <OgreTimer.h>
13 #include <OgreOverlay.h>
14 #include <OgreOverlayElement.h>
15 #include <OgreTextureManager.h>
16 #include <OgreMaterialManager.h>
17 #include <OgreTechnique.h>
18 using namespace Ogre;
19 
20 
21 //  color factors for edit mode D,S,E,F
22 const float App::brClr[4][3] = {
23 	{0.3, 0.8, 0.1}, {0.2, 0.8, 0.6}, {0.6, 0.9, 0.6}, {0.4, 0.7, 1.0} };
24 
25 
btnBrushPreset(WP img)26 void CGui::btnBrushPreset(WP img)
27 {
28 	int id = 0;
29 	sscanf(img->getName().c_str(), "brI%d", &id);
30 	app->SetBrushPreset(id);
31 }
SetBrushPreset(int id)32 void App::SetBrushPreset(int id)
33 {
34 	const BrushSet& st = brSets[id];  // copy params
35 	if (!shift)  SetEdMode(st.edMode);  curBr = st.curBr;
36 	mBrSize[curBr] = st.Size;  mBrIntens[curBr] = st.Intens;  mBrShape[curBr] = st.shape;
37 	mBrPow[curBr] = st.Pow;  mBrFq[curBr] = st.Fq;  mBrNOf[curBr] = st.NOf;  mBrOct[curBr] = st.Oct;
38 	if (st.Filter > 0.f)  mBrFilt = st.Filter;
39 	if (st.HSet != -0.01f)  terSetH = st.HSet;
40 
41 	updBrush();  UpdEditWnds();
42 }
43 
44 
GetAngle(float x,float y)45 static float GetAngle(float x, float y)
46 {
47 	if (x == 0.f && y == 0.f)
48 		return 0.f;
49 
50 	if (y == 0.f)
51 		return (x < 0.f) ? PI_d : 0.f;
52 	else
53 		return (y < 0.f) ? atan2f(-y, x) : (2*PI_d - atan2f(y, x));
54 }
55 
56 
57 ///  update brush preview texture
58 //--------------------------------------------------------------------------------------------------------------------------
updateBrushPrv(bool first)59 void App::updateBrushPrv(bool first)
60 {
61 	if (!first && (!ovBrushPrv || edMode >= ED_Road /*|| bMoveCam/*|| !bEdit()*/))  return;
62 	if (!pSet->brush_prv || brushPrvTex.isNull())  return;
63 
64 	//  Lock texture and fill pixel data
65 	HardwarePixelBufferSharedPtr pbuf = brushPrvTex->getBuffer();
66 	pbuf->lock(HardwareBuffer::HBL_DISCARD);
67 	const PixelBox& pb = pbuf->getCurrentLock();
68 	uint8* p = static_cast<uint8*>(pb.data);
69 
70 	const float fB = brClr[edMode][0]*255.f, fG = brClr[edMode][1]*255.f, fR = brClr[edMode][2]*255.f;
71 
72 	const float s = BrPrvSize * 0.5f, s1 = 1.f/s,
73 		fP = mBrPow[curBr], fQ = mBrFq[curBr]*5.f, nof = mBrNOf[curBr];
74 	int oct = mBrOct[curBr];	const float PiN = PI_d/oct;
75 
76 	switch (mBrShape[curBr])
77 	{
78 	case BRS_Noise2:
79 		for (size_t y = 0; y < BrPrvSize; ++y)
80 		for (size_t x = 0; x < BrPrvSize; ++x)
81 		{	float fx = ((float)x - s)*s1, fy = ((float)y - s)*s1;  // -1..1
82 			float d = std::max(0.f, 1.f - float(sqrt(fx*fx + fy*fy)));  // 0..1
83 
84 			float c = d * (1.0-pow( fabs(CScene::Noise(x*s1+nof,y*s1+nof, fQ, oct, 0.5f)), fP*d)) * (1.5f-fP*0.1);
85 			c = std::max(0.f, c);
86 
87 			uint8 bR = c * fR, bG = c * fG, bB = c * fB;
88 			*p++ = bR;  *p++ = bG;  *p++ = bB;  *p++ = bG > 32 ? 255 : 0;
89 		}	break;
90 
91 	case BRS_Noise:
92 		for (size_t y = 0; y < BrPrvSize; ++y)
93 		for (size_t x = 0; x < BrPrvSize; ++x)
94 		{	float fx = ((float)x - s)*s1, fy = ((float)y - s)*s1;  // -1..1
95 			float d = std::max(0.f, 1.f - float(sqrt(fx*fx + fy*fy)));  // 0..1
96 
97 			float c = d * pow( fabs(CScene::Noise(x*s1+nof,y*s1+nof, fQ, oct, 0.5f)), fP*0.5f) * 0.9f;
98 
99 			uint8 bR = c * fR, bG = c * fG, bB = c * fB;
100 			*p++ = bR;  *p++ = bG;  *p++ = bB;  *p++ = bG > 32 ? 255 : 0;
101 		}	break;
102 
103 	case BRS_Sinus:
104 		for (size_t y = 0; y < BrPrvSize; ++y)
105 		for (size_t x = 0; x < BrPrvSize; ++x)
106 		{	float fx = ((float)x - s)*s1, fy = ((float)y - s)*s1;  // -1..1
107 			float d = std::max(0.f, 1.f - float(sqrt(fx*fx + fy*fy)));  // 0..1
108 
109 			float c = powf( sinf(d * PI_d*0.5f), fP);
110 
111 			uint8 bR = c * fR, bG = c * fG, bB = c * fB;
112 			*p++ = bR;  *p++ = bG;  *p++ = bB;  *p++ = bG > 32 ? 255 : 0;
113 		}	break;
114 
115 	case BRS_Ngon:
116 		for (size_t y = 0; y < BrPrvSize; ++y)
117 		for (size_t x = 0; x < BrPrvSize; ++x)
118 		{	float fx = ((float)x - s)*s1, fy = ((float)y - s)*s1;  // -1..1
119 			float d = std::max(0.f, 1.f - float(sqrt(fx*fx + fy*fy)));  // 0..1
120 			float k = GetAngle(fx,fy);  // 0..2Pi
121 
122     		float c = std::max(0.f, std::min(1.f,
123     			fQ * powf( fabs(d / (-1.f+nof + cosf(PiN) / cosf( fmodf(k, 2*PiN) - PiN ) )),fP) ));
124 
125 			uint8 bR = c * fR, bG = c * fG, bB = c * fB;
126 			*p++ = bR;  *p++ = bG;  *p++ = bB;  *p++ = bG > 32 ? 255 : 0;
127 		}	break;
128 
129 	case BRS_Triangle:
130 		for (size_t y = 0; y < BrPrvSize; ++y)
131 		for (size_t x = 0; x < BrPrvSize; ++x)
132 		{	float fx = ((float)x - s)*s1, fy = ((float)y - s)*s1;  // -1..1
133 			float d = std::max(0.f, 1.f - float(sqrt(fx*fx + fy*fy)));  // 0..1
134 
135 			float c = powf( fabs(d), fP);
136 
137 			uint8 bR = c * fR, bG = c * fG, bB = c * fB;
138 			*p++ = bR;  *p++ = bG;  *p++ = bB;  *p++ = bG > 32 ? 255 : 0;
139 		}	break;
140 	}
141 	pbuf->unlock();
142 }
143 
144 ///  fill brush data (shape), after size change
145 //--------------------------------------------------------------------------------------------------------------------------
updBrush()146 void App::updBrush()
147 {
148 	if (mBrSize[curBr] < 2)  mBrSize[curBr] = 2;
149 	if (mBrSize[curBr] > BrushMaxSize)  mBrSize[curBr] = BrushMaxSize;
150 	if (mBrFq[curBr] < 0.1)  mBrFq[curBr] = 0.1;
151 	if (mBrPow[curBr] < 0.02)  mBrPow[curBr] = 0.02;
152 
153 	int size = (int)mBrSize[curBr], a = 0;
154 	float s = size * 0.5f, s1 = 1.f/s,
155 		fP = mBrPow[curBr], fQ = mBrFq[curBr]*5.f, nof = mBrNOf[curBr];
156 	int oct = mBrOct[curBr];	const float PiN = PI_d/oct;
157 
158 	switch (mBrShape[curBr])
159 	{
160 	case BRS_Noise2:
161 		for (int y = 0; y < size; ++y) {  a = y * BrushMaxSize;
162 		for (int x = 0; x < size; ++x,++a)
163 		{	float fx = ((float)x - s)*s1, fy = ((float)y - s)*s1;  // -1..1
164 			float d = std::max(0.f, 1.f - float(sqrt(fx*fx + fy*fy)));  // 0..1
165 
166 			float c = d * (1.0-pow( fabs(CScene::Noise(x*s1+nof,y*s1+nof, fQ, oct, 0.5f)), fP*d)) * (1.5f-fP*0.1);
167 			c = std::max(0.f, c);
168 
169 			mBrushData[a] = std::min(1.f, c );
170 		}	}	break;
171 
172 
173 	case BRS_Noise:
174 		for (int y = 0; y < size; ++y) {  a = y * BrushMaxSize;
175 		for (int x = 0; x < size; ++x,++a)
176 		{	float fx = ((float)x - s)*s1, fy = ((float)y - s)*s1;  // -1..1
177 			float d = std::max(0.f, 1.f - float(sqrt(fx*fx + fy*fy)));  // 0..1
178 
179 			float c = d * pow( fabs(CScene::Noise(x*s1+nof,y*s1+nof, fQ, oct, 0.5f)), fP*0.5f);
180 
181 			mBrushData[a] = std::max(-1.f, std::min(1.f, c ));
182 		}	}	break;
183 
184 	case BRS_Sinus:
185 		for (int y = 0; y < size; ++y) {  a = y * BrushMaxSize;
186 		for (int x = 0; x < size; ++x,++a)
187 		{	float fx = ((float)x - s)*s1, fy = ((float)y - s)*s1;  // -1..1
188 			float d = std::max(0.f, 1.f - float(sqrt(fx*fx + fy*fy)));  // 0..1
189 
190 			float c = powf( sinf(d * PI_d*0.5f), fP);
191 			mBrushData[a] = c;
192 		}	}	break;
193 
194 	case BRS_Ngon:
195 		for (int y = 0; y < size; ++y) {  a = y * BrushMaxSize;
196 		for (int x = 0; x < size; ++x,++a)
197 		{	float fx = ((float)x - s)*s1, fy = ((float)y - s)*s1;  // -1..1
198 			float d = std::max(0.f, 1.f - float(sqrt(fx*fx + fy*fy)));  // 0..1
199 			float k = GetAngle(fx,fy);  // 0..2Pi
200 
201 			float c = std::max(0.f, std::min(1.f,
202 				fQ * powf( fabs(d / (-1.f+nof + cosf(PiN) / cosf( fmodf(k, 2*PiN) - PiN ) )),fP) ));
203 			mBrushData[a] = c;
204 		}	}	break;
205 
206 	case BRS_Triangle:
207 		for (int y = 0; y < size; ++y) {  a = y * BrushMaxSize;
208 		for (int x = 0; x < size; ++x,++a)
209 		{	float fx = ((float)x - s)*s1, fy = ((float)y - s)*s1;  // -1..1
210 			float d = std::max(0.f, 1.f - float(sqrt(fx*fx + fy*fy)));  // 0..1
211 
212 			float c = powf( fabs(d), fP);
213 			mBrushData[a] = c;
214 		}	}	break;
215 	}
216 
217 	//  filter brush kernel  ------
218 	if (mBrFilt != mBrFiltOld)
219 	{	mBrFilt = std::max(0.f, std::min(8.f, mBrFilt));
220 		mBrFiltOld = mBrFilt;
221 
222 		delete[] pBrFmask;  pBrFmask = 0;
223 		const float fl = mBrFilt;
224 		const int f = ceil(fl);  float fd = 1.f + fl - floor(fl);
225 		register int m,i,j;
226 
227 		//  gauss kernel for smoothing
228 		const int mm = (f*2+1)*(f*2+1);
229 		pBrFmask = new float[mm];  m = 0;
230 
231 		float fm = 0.f;  //sum
232 		for (j = -f; j <= f; ++j)
233 		{
234 			float fj = float(j)/f;
235 			for (i = -f; i <= f; ++i, ++m)
236 			{
237 				float fi = float(i)/f;
238 				float u = std::max(0.f, fd - sqrtf(fi*fi+fj*fj) );
239 				pBrFmask[m] = u;  fm += u;
240 			}
241 		}
242 		fm = 1.f / fm;  //avg
243 		for (m = 0; m < mm; ++m)
244 			pBrFmask[m] *= fm;
245 	}
246 
247 	updateBrushPrv();  // upd skip..
248 }
249 
250 
251 ///  Terrain  generate
252 ///--------------------------------------------------------------------------------------------------------------------------
btnTerGenerate(WP wp)253 void CGui::btnTerGenerate(WP wp)
254 {
255 	const std::string& n = wp->getName();
256 	bool add = false, sub = false;
257 	if (n == "TerrainGenAdd")  add = true;  else
258 	if (n == "TerrainGenSub")  sub = true;/*else
259 	if (n == "TerrainGenMul")  mul = true;*/
260 
261 	float* hfData = sc->td.hfHeight; //, *hfAng = sc->td.hfAngle;
262 	const int sx = sc->td.iVertsX;  // sx=sy
263 	const float s = sx * 0.5f, s1 = 1.f/s;
264 	const float ox = pSet->gen_ofsx, oy = pSet->gen_ofsy;
265 
266 	//)  road test
267 	bool bRoad = pSet->gen_roadsm > 0.1f;
268 	float rdPow = pSet->gen_roadsm;  //-
269 	int r = 0;
270 	Image imgRoad;
271 	if (bRoad)
272 	{
273 		try {	imgRoad.load(String("roadDensity.png"),"General");  }
274 		catch(...) {	}
275 		r = imgRoad.getWidth();
276 	}
277 
278 	Ogre::Timer ti;
279 
280 	//  generate noise terrain hmap
281 	register int a,x,y;  register float c;
282 
283 	for (y=0; y < sx; ++y)  {  a = y * sx;
284 	for (x=0; x < sx; ++x,++a)
285 	{	float fx = ((float)x - s)*s1, fy = ((float)y - s)*s1;  // -1..1
286 
287 		c = CScene::Noise(y*s1-oy, x*s1+ox, pSet->gen_freq, pSet->gen_oct, pSet->gen_persist) * 0.8f;
288 		c = c >= 0.f ? powf(c, pSet->gen_pow) : -powf(-c, pSet->gen_pow);
289 
290 		//)  check if on road - uses roadDensity.png
291 		//  todo: smooth depends on -smooth grass dens par, own val?
292 		if (bRoad)
293 		{
294 			int mx = ( fx+1.f)*0.5f*r, my = (-fy+1.f)*0.5f*r;
295 
296 			float cr = imgRoad.getColourAt(
297 				std::max(0,std::min(r-1, mx)), std::max(0,std::min(r-1, my)), 0).r;
298 
299 			//c = c + std::max(0.f, std::min(1.f, 2*c-cr)) * pow(cr, rdPow);
300 			c *= pow(cr, rdPow);
301 		}
302 		//FIXME: ter gen ang pars
303 		//c *= app->linRange(hfAng[a],  pSet->gen_terMinA,pSet->gen_terMaxA, pSet->gen_terSmA);
304 		c *= CScene::linRange(hfData[a], pSet->gen_terMinH,pSet->gen_terMaxH, pSet->gen_terSmH);
305 
306 		hfData[a] = add ? (hfData[a] + c * pSet->gen_scale + pSet->gen_ofsh) : (
307 					sub ? (hfData[a] - c * pSet->gen_scale - pSet->gen_ofsh) :
308 						  (hfData[a] * c * pSet->gen_mul) );
309 	}	}
310 
311 	LogO(String("::: Time Ter Gen: ") + fToStr(ti.getMilliseconds(),0,3) + " ms");  ti.reset();
312 
313 	std::ofstream of;
314 	of.open(getHMapNew().c_str(), std::ios_base::binary);
315 	int siz = sx * sx * sizeof(float);
316 	of.write((const char*)&hfData[0], siz);
317 	of.close();
318 
319 	LogO(String("::: Time Ter Gen save: ") + fToStr(ti.getMilliseconds(),0,3) + " ms");
320 
321 	app->bNewHmap = true;	app->UpdateTrack();
322 }
323 
324 ///  update terrain generator preview texture
325 //--------------------------------------------------------------------------------------------------------------------------
updateTerPrv(bool first)326 void App::updateTerPrv(bool first)
327 {
328 	if (!first && !ovTerPrv)  return;
329 	if (terPrvTex.isNull())  return;
330 
331 	HardwarePixelBufferSharedPtr pbuf = terPrvTex->getBuffer();
332 	pbuf->lock(HardwareBuffer::HBL_DISCARD);
333 	const PixelBox& pb = pbuf->getCurrentLock();  using Ogre::uint8;
334 	uint8* p = static_cast<uint8*>(pb.data);
335 
336 	const static float fB[2] = { 90.f, 90.f}, fG[2] = {255.f,160.f}, fR[2] = { 90.f,255.f};
337 
338 	const float s = TerPrvSize * 0.5f, s1 = 1.f/s;
339 	const float ox = pSet->gen_ofsx, oy = pSet->gen_ofsy;
340 
341 	for (int y = 0; y < TerPrvSize; ++y)
342 	for (int x = 0; x < TerPrvSize; ++x)
343 	{	float fx = ((float)x - s)*s1, fy = ((float)y - s)*s1;  // -1..1
344 
345 		float c = CScene::Noise(x*s1-oy, y*s1+ox, pSet->gen_freq, pSet->gen_oct, pSet->gen_persist) * 0.8f;  // par fit
346 		bool b = c >= 0.f;
347 		c = b ? powf(c, pSet->gen_pow) : -powf(-c, pSet->gen_pow);
348 
349 		int i = b ? 0 : 1;  c = b ? c : -c;
350 		//c *= pSet->gen_scale;  //no
351 
352 		uint8 bR = c * fR[i], bG = c * fG[i], bB = c * fB[i];
353 		*p++ = bR;  *p++ = bG;  *p++ = bB;  *p++ = 255;//bG > 32 ? 255 : 0;
354 	}
355 	pbuf->unlock();
356 }
357 
358 
359 
360 ///  get edit rect
361 //-----------------------------------------------------------------------------------------------
getEditRect(Vector3 & pos,Rect & rcBrush,Rect & rcMap,int size,int & cx,int & cy)362 bool App::getEditRect(Vector3& pos, Rect& rcBrush, Rect& rcMap, int size,  int& cx, int& cy)
363 {
364 	float tws = scn->sc->td.fTerWorldSize;
365 	int t = scn->sc->td.iTerSize;
366 
367 	//  world float to map int
368 	int mapX = (pos.x + 0.5*tws)/tws*t, mapY = (-pos.z + 0.5*tws)/tws*t;
369 	mapX = std::max(0,std::min(t-1, mapX)), mapY = std::max(0,std::min(t-1, mapY));
370 
371 	int brS = (int)mBrSize[curBr];
372 	float hBr = brS * 0.5f;
373 	rcMap = Rect(mapX-hBr, mapY-hBr, mapX+hBr, mapY+hBr);
374 	rcBrush = Rect(0,0, brS,brS);
375 	cx = 0;  cy = 0;
376 
377 	if (rcMap.left < 0)  // trim
378 	{	rcBrush.left += 0 - rcMap.left;  cx += -rcMap.left;
379 		rcMap.left = 0;
380 	}
381 	if (rcMap.top < 0)
382 	{	rcBrush.top  += 0 - rcMap.top;   cy += -rcMap.top;
383 		rcMap.top = 0;
384 	}
385 	if (rcMap.right > size)
386 	{	rcBrush.right  -= rcMap.right - size;
387 		rcMap.right = size;
388 	}
389 	if (rcMap.bottom > size)
390 	{	rcBrush.bottom -= rcMap.bottom - size;
391 		rcMap.bottom = size;
392 	}
393 
394 	if (rcMap.right - rcMap.left < 1 ||
395 		rcMap.bottom - rcMap.top < 1)
396 		return false;  // no area
397 
398 	/*sprintf(sBrushTest,
399 		" ---br rect--- \n"
400 		"size: %3d %6.3f \n"
401 		"pos %3d %3d  c: %3d %3d \n"
402 		"rect:  %3d %3d  %3d %3d \n"
403 		"map: %3d %3d  %3d %3d \n"
404 		"br: %3d %3d  %3d %3d \n"
405 		,brS, mBrSize[curBr]
406 		,mapX, mapY, cx, cy
407 		 ,rcMap.right-rcMap.left, rcMap.bottom-rcMap.top
408 		 ,rcBrush.right-rcBrush.left, rcBrush.bottom-rcBrush.top
409 		,rcMap.left, rcMap.top, rcMap.right, rcMap.bottom
410 		,rcBrush.left, rcBrush.top, rcBrush.right, rcBrush.bottom);
411 	LogO(String(sBrushTest));/**/
412 	return true;
413 }
414 
415 
416 ///  ^v Deform
417 //-----------------------------------------------------------------------------------------------
deform(Vector3 & pos,float dtime,float brMul)418 void App::deform(Vector3 &pos, float dtime, float brMul)
419 {
420 	Rect rcBrush, rcMap;  int cx,cy;
421 	if (!getEditRect(pos, rcBrush, rcMap, scn->sc->td.iTerSize, cx,cy))
422 		return;
423 
424 	float *fHmap = scn->terrain->getHeightData();
425 
426 	float its = mBrIntens[curBr] * dtime * brMul;
427 	int mapPos, brPos, jj = cy;
428 
429 	for (int j = rcMap.top; j < rcMap.bottom; ++j,++jj)
430 	{
431 		mapPos = j * scn->sc->td.iTerSize + rcMap.left;
432 		brPos = jj * BrushMaxSize + cx;
433 		//brPos = std::max(0, std::min(BrushMaxSize*BrushMaxSize-1, brPos ));
434 
435 		for (int i = rcMap.left; i < rcMap.right; ++i)
436 		{
437 			///  pos float -> brush data compute here (for small size brushes) ..
438 			fHmap[mapPos] += mBrushData[brPos] * its;  // deform
439 			++mapPos;  ++brPos;
440 		}
441 	}
442 	scn->terrain->dirtyRect(rcMap);
443 	scn->UpdBlendmap();
444 	bTerUpd = true;
445 }
446 
447 
448 ///  -_ set Height
449 //-----------------------------------------------------------------------------------------------
height(Vector3 & pos,float dtime,float brMul)450 void App::height(Vector3 &pos, float dtime, float brMul)
451 {
452 	Rect rcBrush, rcMap;  int cx,cy;
453 	if (!getEditRect(pos, rcBrush, rcMap, scn->sc->td.iTerSize, cx,cy))
454 		return;
455 
456 	float *fHmap = scn->terrain->getHeightData();
457 
458 	float its = mBrIntens[curBr] * dtime * brMul;
459 	int mapPos, brPos, jj = cy;
460 
461 	for (int j = rcMap.top; j < rcMap.bottom; ++j,++jj)
462 	{
463 		mapPos = j * scn->sc->td.iTerSize + rcMap.left;
464 		brPos = jj * BrushMaxSize + cx;
465 
466 		for (int i = rcMap.left; i < rcMap.right; ++i)
467 		{
468 			float d = terSetH - fHmap[mapPos];
469 			d = d > 2.f ? 2.f : d < -2.f ? -2.f : d;  // par speed-
470 			fHmap[mapPos] += d * mBrushData[brPos] * its;
471 			++mapPos;  ++brPos;
472 		}
473 	}
474 	scn->terrain->dirtyRect(rcMap);
475 	scn->UpdBlendmap();
476 	bTerUpd = true;
477 }
478 
479 
480 ///  ~- Smooth (Flatten)
481 //-----------------------------------------------------------------------------------------------
smooth(Vector3 & pos,float dtime)482 void App::smooth(Vector3 &pos, float dtime)
483 {
484 	float avg = 0.0f;
485 	int sample_count = 0;
486 	calcSmoothFactor(pos, avg, sample_count);
487 
488 	if (sample_count)
489 		smoothTer(pos, avg / (float)sample_count, dtime);
490 }
491 
calcSmoothFactor(Vector3 & pos,float & avg,int & sample_count)492 void App::calcSmoothFactor(Vector3 &pos, float& avg, int& sample_count)
493 {
494 	Rect rcBrush, rcMap;  int cx,cy;
495 	if (!getEditRect(pos, rcBrush, rcMap, scn->sc->td.iTerSize, cx,cy))
496 		return;
497 
498 	float *fHmap = scn->terrain->getHeightData();
499 	int mapPos;
500 
501 	avg = 0.0f;  sample_count = 0;
502 
503 	for (int j = rcMap.top;j < rcMap.bottom; ++j)
504 	{
505 		mapPos = j * scn->sc->td.iTerSize + rcMap.left;
506 		for (int i = rcMap.left;i < rcMap.right; ++i)
507 		{
508 			avg += fHmap[mapPos];  ++mapPos;
509 		}
510 	}
511 	sample_count = (rcMap.right - rcMap.left) * (rcMap.bottom - rcMap.top);
512 }
513 
514 //-----------------------------------------------------------------------------------------------
smoothTer(Vector3 & pos,float avg,float dtime)515 void App::smoothTer(Vector3 &pos, float avg, float dtime)
516 {
517 	Rect rcBrush, rcMap;  int cx,cy;
518 	if (!getEditRect(pos, rcBrush, rcMap, scn->sc->td.iTerSize, cx,cy))
519 		return;
520 
521 	float *fHmap = scn->terrain->getHeightData();
522 	float mRatio = 1.f, brushPos;
523 	int mapPos;
524 	float mFactor = mBrIntens[curBr] * dtime * 0.1f;
525 
526 	for(int j = rcMap.top;j < rcMap.bottom;j++)
527 	{
528 		brushPos = (rcBrush.top + (int)((j - rcMap.top) * mRatio)) * BrushMaxSize;
529 		brushPos += rcBrush.left;
530 		//**/brushPos += cy * BrushMaxSize + cx;
531 		mapPos = j * scn->sc->td.iTerSize + rcMap.left;
532 
533 		for(int i = rcMap.left;i < rcMap.right;i++)
534 		{
535 			float val = avg - fHmap[mapPos];
536 			val = val * std::min(mBrushData[(int)brushPos] * mFactor, 1.0f);
537 			fHmap[mapPos] += val;
538 			++mapPos;
539 			brushPos += mRatio;
540 		}
541 	}
542 	scn->terrain->dirtyRect(rcMap);
543 	scn->UpdBlendmap();
544 	bTerUpd = true;
545 }
546 
547 
548 ///  ^v \ Filter - low pass, removes noise
549 //-----------------------------------------------------------------------------------------------
filter(Vector3 & pos,float dtime,float brMul)550 void App::filter(Vector3 &pos, float dtime, float brMul)
551 {
552 	Rect rcBrush, rcMap;  int cx,cy;
553 	if (!getEditRect(pos, rcBrush, rcMap, scn->sc->td.iTerSize, cx,cy))
554 		return;
555 
556 	float *fHmap = scn->terrain->getHeightData();
557 
558 	float its = mBrIntens[curBr] * dtime * std::min(1.f,brMul);  //mul >1 errors
559 	int mapPos, brPos, jj = cy,
560 		ter = scn->sc->td.iTerSize, ter2 = ter*ter, ter1 = ter+1;
561 
562 	const float fl = mBrFilt;  const int f = ceil(fl);
563 	register int x,y,m,yy,i,j;
564 
565 	for (j = rcMap.top; j < rcMap.bottom; ++j,++jj)
566 	{
567 		mapPos = j * ter + rcMap.left;
568 		brPos = jj * BrushMaxSize + cx;
569 
570 		for (i = rcMap.left; i < rcMap.right; ++i)
571 		if (mapPos -f*ter1 >= 0 && mapPos +f*ter1 < ter2)  // ter borders
572 		{
573 			//  sum in kernel
574 			register float s = 0.f;  m = 0;
575 			for (y = -f; y <= f; ++y) {  yy = y*ter-f;
576 			for (x = -f; x <= f; ++x, ++m, ++yy)
577 				s += fHmap[mapPos + yy] * pBrFmask[m];  }
578 
579 			fHmap[mapPos] += (s-fHmap[mapPos]) * mBrushData[brPos] * its;  // filter
580 			++mapPos;  ++brPos;
581 		}
582 	}
583 
584 	scn->terrain->dirtyRect(rcMap);
585 	scn->UpdBlendmap();
586 	bTerUpd = true;
587 }
588 
589 
590 
591 //  preview texture for brush and noise ter gen
592 //--------------------------------------------------------------------------------------------------------------------------
createBrushPrv()593 void App::createBrushPrv()
594 {
595 	//  brush
596 	brushPrvTex = TextureManager::getSingleton().createManual(
597 		"BrushPrvTex", rgDef, TEX_TYPE_2D,
598 		BrPrvSize,BrPrvSize,0, PF_BYTE_RGBA, TU_DYNAMIC);
599 
600 	MaterialPtr mat = MaterialManager::getSingleton().create(
601 		"BrushPrvMtr", rgDef);
602 
603 	Pass* pass = mat->getTechnique(0)->getPass(0);
604 	pass->createTextureUnitState("BrushPrvTex");
605 	pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
606 
607 	if (ovBrushMtr)
608 		ovBrushMtr->setMaterialName("BrushPrvMtr");
609 
610 	updateBrushPrv(true);
611 
612 	//  ter gen
613 	terPrvTex = TextureManager::getSingleton().createManual(
614 		"TerPrvTex", rgDef, TEX_TYPE_2D,
615 		TerPrvSize,TerPrvSize,0, PF_BYTE_RGBA, TU_DYNAMIC);
616 
617 	mat = MaterialManager::getSingleton().create(
618 		"TerPrvMtr", rgDef);
619 
620 	pass = mat->getTechnique(0)->getPass(0);
621 	pass->createTextureUnitState("TerPrvTex");
622 	pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
623 
624 	if (ovTerMtr)
625 		ovTerMtr->setMaterialName("TerPrvMtr");
626 
627 	updateTerPrv(true);
628 }
629