1 #include "pch.h"
2 #include "../common/RenderConst.h"
3 #include "../common/Def_Str.h"
4 #include "../common/data/SceneXml.h"
5 #include "../common/CScene.h"
6 #include "../../vdrift/pathmanager.h"
7 #ifdef SR_EDITOR
8 	#include "../../editor/CApp.h"
9 #else
10 	#include "../CGame.h"
11 #endif
12 #include <OgreRoot.h>
13 #include <OgreTimer.h>
14 #include <OgreTerrain.h>
15 #include <OgreCamera.h>
16 #include <OgreHardwarePixelBuffer.h>
17 #include <OgreRectangle2D.h>
18 #include <OgreViewport.h>
19 #include <OgreSceneNode.h>
20 #include <OgreTextureManager.h>
21 #include <OgreRenderTexture.h>
22 #include "../../shiny/Main/Factory.hpp"
23 #include "../../paged-geom/GrassLoader.h"
24 using namespace Ogre;
25 
26 
27 //  common rtt setup
Setup(Root * rt,String sName,TexturePtr pTex,String sMtr)28 void CScene::RenderToTex::Setup(Root* rt, String sName, TexturePtr pTex, String sMtr)
29 {
30 	if (!scm)  scm = rt->createSceneManager(ST_GENERIC);  // once-
31 	//  destroy old
32 	if (cam)  scm->destroyCamera(cam);
33 	if (nd)  scm->destroySceneNode(nd);
34 	delete rect;
35 
36 	cam = scm->createCamera(sName+"C");
37 	cam->setPosition(Vector3(0,10,0));  cam->setOrientation(Quaternion(0.5,-0.5,0.5,0.5));
38 	cam->setNearClipDistance(0.5f);     cam->setFarClipDistance(500.f);
39 	cam->setAspectRatio(1.f);   cam->setProjectionType(PT_ORTHOGRAPHIC);
40 	cam->setOrthoWindow(1.f,1.f);
41 
42 	rnd = pTex->getBuffer()->getRenderTarget();
43 	rnd->setAutoUpdated(false);  //rnd->addListener(this);
44 	vp = rnd->addViewport(cam);
45 	vp->setClearEveryFrame(true);   vp->setBackgroundColour(ColourValue(0,0,0,0));
46 	vp->setOverlaysEnabled(false);  vp->setSkiesEnabled(false);
47 	vp->setShadowsEnabled(false);   //vp->setVisibilityMask();
48 	vp->setMaterialScheme("reflection");
49 
50 	rect = new Rectangle2D(true);   rect->setCorners(-1,1,1,-1);
51 	AxisAlignedBox aab;  aab.setInfinite();
52 	rect->setBoundingBox(aab);  rect->setCastShadows(false);
53 	rect->setMaterial( sMtr );
54 
55 	nd = scm->getRootSceneNode()->createChildSceneNode(sName+"N");
56 	nd->attachObject(rect);
57 }
58 
59 ///  blendmap setup
60 //  every time terrain hmap size changes
61 //----------------------------------------------------------------------------------------------------
62 const String CScene::sHmap = "HmapTex",
63 	CScene::sAng = "AnglesRTT", CScene::sBlend = "blendmapRTT",
64 	CScene::sAngMat = "anglesMat", CScene::sBlendMat = "blendMat",
65 	CScene::sGrassDens = "GrassDensRTT", CScene::sGrassDensMat = "grassDensMat";
66 
CreateBlendTex()67 void CScene::CreateBlendTex()
68 {
69 	uint size = sc->td.iTerSize-1;
70 	TextureManager& texMgr = TextureManager::getSingleton();
71 	texMgr.remove(sHmap);  texMgr.remove(sAng);
72 	texMgr.remove(sBlend);  texMgr.remove(sGrassDens);
73 
74 	//  Hmap tex
75 	heightTex = texMgr.createManual( sHmap, rgDef, TEX_TYPE_2D,
76 		size, size, 0, PF_FLOAT32_R, TU_DYNAMIC_WRITE_ONLY); //TU_STATIC_WRITE_ONLY?
77 	if (heightTex.isNull())
78 		LogO("Error: Can't create Float32 (HMap) texture!");
79 
80 	//  Angles rtt
81 	angleRTex = texMgr.createManual( sAng, rgDef, TEX_TYPE_2D,
82 		size, size, 0, PF_FLOAT32_R, TU_RENDERTARGET);
83 	if (angleRTex.isNull())
84 		LogO("Error: Can't create Float32 (Angles) RenderTarget!");
85 
86 	//  Blendmap rtt
87 	blendRTex = texMgr.createManual( sBlend, rgDef, TEX_TYPE_2D,
88 		size, size, 0, PF_R8G8B8A8, TU_RENDERTARGET);
89 	if (blendRTex.isNull())
90 		LogO("Error: Can't create RGBA (Blendmap) RenderTarget!");
91 
92 	//  rtt copy  (not needed)
93 	//blMap = texMgr.createManual("blendmapT", rgDef, TEX_TYPE_2D,
94 	//	size, size, 0, PF_R8G8B8A8, TU_DEFAULT);
95 
96 	//  Grass Density rtt
97 	grassDensRTex = texMgr.createManual( sGrassDens, rgDef, TEX_TYPE_2D,
98 		size, size, 0, PF_R8G8B8A8, TU_RENDERTARGET);
99 	if (grassDensRTex.isNull())
100 		LogO("Error: Can't create RGBA (GrassDens) RenderTarget!");
101 
102 	blendRTT.Setup(app->mRoot, "bl", blendRTex, sBlendMat);
103 	angleRTT.Setup(app->mRoot, "ang", angleRTex, sAngMat);
104 	grassDensRTT.Setup(app->mRoot, "grd", grassDensRTex, sGrassDensMat);
105 
106 	//UpdBlendmap();  //
107 }
108 
109 
110 ///  update, fill hmap texture from cpu floats
111 //  every terrain hmap edit
112 //--------------------------------------------------------------------------
UpdBlendmap()113 void CScene::UpdBlendmap()
114 {
115 	//if (!terrain)  return;
116 	Ogre::Timer ti;
117 
118 	size_t size = sc->td.iTerSize-1;  //!^ same as in create
119 	float* fHmap = terrain ? terrain->getHeightData() : sc->td.hfHeight;
120 	if (!fHmap)  return;
121 
122 	//  fill hmap  (copy to tex, full is fast)
123 	HardwarePixelBufferSharedPtr pt = heightTex->getBuffer();
124 	pt->lock(HardwareBuffer::HBL_DISCARD);
125 
126 	const PixelBox& pb = pt->getCurrentLock();
127 	float* pD = static_cast<float*>(pb.data);
128 	size_t aD = pb.getRowSkip() * PixelUtil::getNumElemBytes(pb.format);
129 
130 	register size_t j,i,a=0;
131 	for (j = 0; j < size; ++j)
132 	{
133 		for (i = 0; i < size; ++i)
134 		{
135 			*pD++ = fHmap[a++];
136 		}
137 		pD += aD;  a++;  //Hmap is size+1
138 	}
139 	pt->unlock();
140 
141 	//  rtt
142 	if (angleRTT.rnd && blendRTT.rnd)
143 	{
144 		UpdLayerPars();
145 
146 		angleRTT.rnd->update();
147 		blendRTT.rnd->update();
148 
149 		//  copy from rtt to normal texture
150 		//HardwarePixelBufferSharedPtr b = blendRTT.rnd->getBuffer();
151 		//b->blit(pt);
152 
153 		//  test  save
154 		//Image im;
155 		//heightTex->convertToImage(im);
156 		//im.save(PATHMANAGER::DataUser()+ "/../hmap.png");
157 
158 		//angleRTT.rnd->writeContentsToFile(PATHMANAGER::DataUser()+ "/../angle.png");
159 		//blendRTT.rnd->writeContentsToFile(PATHMANAGER::DataUser()+ "/../blend.jpg");
160 	}
161 	else
162 		LogO("Error: Didn't update blendmap !");
163 
164 	//LogO(String("::: Time Upd blendmap: ") + fToStr(ti.getMilliseconds(),0,1) + " ms");  // 1ms on 512, 4ms on 1k
165 }
166 
167 
168 ///  for game, wheel contacts
169 //--------------------------------------------------------------------------
170 #ifndef SR_EDITOR
GetTerMtrIds()171 void App::GetTerMtrIds()
172 {
173 	//Ogre::Timer ti;
174 
175 	size_t size = scn->sc->td.iTerSize-1;  //!^ same as in create
176 	size_t size2 = size*size;
177 	//  new
178 	delete[] blendMtr;
179 	blendMtr = new char[size2];
180 	memset(blendMtr,0,size2);  // zero
181 
182 	if (!scn->terrain)  return;
183 	blendMapSize = size;
184 	uint8* pd = new uint8[size2*4];  // temp
185 
186 	HardwarePixelBufferSharedPtr pt = scn->blendRTex->getBuffer();
187 	PixelBox pb(pt->getWidth(), pt->getHeight(), pt->getDepth(), pt->getFormat(), pd);
188 	assert(pt->getWidth() == size && pt->getHeight() == size);
189 
190 	pt->blitToMemory(pb);
191 	//RenderTexture* pTex = pt->getRenderTarget();
192 	//pTex->copyContentsToMemory(pb, RenderTarget::FB_AUTO);
193 
194 	register size_t aa = pb.getRowSkip() * PixelUtil::getNumElemBytes(pb.format);
195 	register uint8* p = pd, v, h;
196 	register size_t j,i,a=0;
197 	register char mtr;
198 	for (j = 0; j < size; ++j)
199 	{
200 		for (i = 0; i < size; ++i)
201 		{
202 			mtr = 0;  h = 0;  // layers B,G,R,A
203 			v = *p++;  if (v > h) {  h = v;  mtr = 2;  }
204 			v = *p++;  if (v > h) {  h = v;  mtr = 1;  }
205 			v = *p++;  if (v > h) {  h = v;  mtr = 0;  }
206 			v = *p++;  if (v > h) {  h = v;  mtr = 3;  }
207 			blendMtr[a++] = mtr;
208 		}
209 		pd += aa;
210 	}
211 	delete[] pd;
212 
213 	//LogO(String("::: Time Ter Ids: ") + fToStr(ti.getMilliseconds(),3,5) + " ms");  // 10ms on 1k
214 }
215 #endif
216 
217 
218 ///  update blendmap layer params in shader
219 //--------------------------------------------------------------------------
UpdLayerPars()220 void CScene::UpdLayerPars()
221 {
222 	//  angles
223 	sh::MaterialInstance* mat = sh::Factory::getInstance().getMaterialInstance(sAngMat);
224 	mat->setProperty("InvTerSize", sh::makeProperty<sh::FloatValue>(new sh::FloatValue( 1.f / float(sc->td.iTerSize) )));
225 	mat->setProperty("TriSize",    sh::makeProperty<sh::FloatValue>(new sh::FloatValue( 2.f * sc->td.fTriangleSize )));
226 
227 	//  blendmap
228 	mat = sh::Factory::getInstance().getMaterialInstance(sBlendMat);
229 	int i;
230 	float Hmin[4],Hmax[4],Hsmt[4], Amin[4],Amax[4],Asmt[4];
231 	float Nnext[4],Nprev[3],Nnext2[2], Nonly[4];
232 	float Nfreq[3],Noct[3],Npers[3],Npow[3];
233 	float Nfreq2[2],Noct2[2],Npers2[2],Npow2[2];
234 	//  zero
235 	for (i=0; i < 4; ++i)
236 	{	Hmin[i]=0.f; Hmax[i]=0.f; Hsmt[i]=0.f;  Amin[i]=0.f; Amax[i]=0.f; Asmt[i]=0.f;
237 		Nnext[i]=0.f;  Nonly[i]=0.f;  }
238 	for (i=0; i < 3; ++i)
239 	{	Nprev[i]=0.f;  Nfreq[i]=0.f; Noct[i]=0.f; Npers[i]=0.f; Npow[i]=0.f;  }
240 	for (i=0; i < 2; ++i)
241 	{	Nnext2[i]=0.f;  Nfreq2[i]=0.f; Noct2[i]=0.f; Npers2[i]=0.f; Npow2[i]=0.f;  }
242 
243 	int nl = std::min(4, (int)sc->td.layers.size());
244 	for (i=0; i < nl; ++i)
245 	{	//  range
246 		const TerLayer& l = sc->td.layersAll[sc->td.layers[i]];
247 		Hmin[i] = l.hMin;	Hmax[i] = l.hMax;	Hsmt[i] = l.hSm;
248 		Amin[i] = l.angMin;	Amax[i] = l.angMax;	Asmt[i] = l.angSm;
249 		//  noise
250 		Nonly[i] = !l.nOnly ? 1.f : 0.f;
251 		Nnext[i] = i < nl-1 ? l.noise : 0.f;  // dont +1 last
252 		if (i > 0)  Nprev[i-1] = l.nprev;  // dont -1 first
253 		if (i < 2)  Nnext2[i] = nl > 2 ? l.nnext2 : 0.f;
254 		//  n par +1,-1, +2
255 		if (i < nl-1){  Nfreq[i] = l.nFreq[0];  Noct[i] = l.nOct[0];  Npers[i] = l.nPers[0];  Npow[i] = l.nPow[0];  }
256 		if (i < nl-2){  Nfreq2[i]= l.nFreq[1];  Noct2[i]= l.nOct[1];  Npers2[i]= l.nPers[1];  Npow2[i]= l.nPow[1];  }
257 	}
258 	#define Set4(s,v)  mat->setProperty(s, sh::makeProperty<sh::Vector4>(new sh::Vector4(v[0], v[1], v[2], v[3])))
259 	#define Set3(s,v)  mat->setProperty(s, sh::makeProperty<sh::Vector3>(new sh::Vector3(v[0], v[1], v[2])))
260 	#define Set2(s,v)  mat->setProperty(s, sh::makeProperty<sh::Vector2>(new sh::Vector2(v[0], v[1])))
261 	#define Set1(s,v)  mat->setProperty(s, sh::makeProperty<sh::FloatValue>(new sh::FloatValue(v)))
262 	Set4("Hmin", Hmin);  Set4("Hmax", Hmax);  Set4("Hsmt", Hsmt);
263 	Set4("Amin", Amin);  Set4("Amax", Amax);  Set4("Asmt", Asmt);  Set4("Nonly", Nonly);
264 	Set3("Nnext", Nnext);  Set3("Nprev", Nprev);  Set2("Nnext2", Nnext2);
265 	Set3("Nfreq", Nfreq);  Set3("Noct", Noct);  Set3("Npers", Npers);  Set3("Npow", Npow);
266 	Set2("Nfreq2", Nfreq2);  Set2("Noct2", Noct2);  Set2("Npers2", Npers2);  Set2("Npow2", Npow2);
267 }
268 
269 
270 ///  update grass density channel params in shader
271 //--------------------------------------------------------------------------
UpdGrassDens()272 void CScene::UpdGrassDens()
273 {
274 	if (!grassDensRTT.rnd)  return;
275 
276 	Ogre::Timer ti;
277 
278 	UpdGrassPars();
279 
280 	grassDensRTT.rnd->update();
281 
282 	//grassDensRTT.rnd->writeContentsToFile(PATHMANAGER::DataUser()+"/grassRD.png");
283 
284 	LogO(String("::: Time Grass Dens: ") + fToStr(ti.getMilliseconds(),0,1) + " ms");
285 }
286 
UpdGrassPars()287 void CScene::UpdGrassPars()
288 {
289 	sh::MaterialInstance* mat = sh::Factory::getInstance().getMaterialInstance(sGrassDensMat);
290 
291 	float Hmin[4],Hmax[4],Hsmt[4], Amin[4],Amax[4],Asmt[4];
292 	float Nmul[4], Nfreq[4],Noct[4],Npers[4],Npow[4], Rpow[4];
293 
294 	for (int i=0; i < 4; ++i)
295 	{	//  range
296 		const SGrassChannel& gr = sc->grChan[i];
297 		Hmin[i] = gr.hMin;  Hmax[i] = gr.hMax;  Hsmt[i] = gr.hSm;
298 		Amin[i] = gr.angMin;  Amax[i] = gr.angMax;  Asmt[i] = gr.angSm;
299 		Rpow[i] = powf(2.f, gr.rdPow);
300 		//  noise
301 		Nmul[i] = gr.noise;  Nfreq[i] = gr.nFreq;
302 		Noct[i] = gr.nOct;  Npers[i] = gr.nPers;  Npow[i] = gr.nPow;
303 	}
304 	Set4("Hmin", Hmin);  Set4("Hmax", Hmax);  Set4("Hsmt", Hsmt);
305 	Set4("Amin", Amin);  Set4("Amax", Amax);  Set4("Asmt", Asmt);
306 	Set4("Nmul", Nmul);  Set4("Nfreq", Nfreq);  Set4("Rpow", Rpow);
307 	Set4("Noct", Noct);  Set4("Npers", Npers);  Set4("Npow", Npow);
308 }
309