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