1 #include "pch.h"
2 #include "Def_Str.h"
3 #include "RenderConst.h"
4 #include "../../vdrift/track.h"
5 #include "GuiCom.h"
6 #include "CScene.h"
7 #ifndef SR_EDITOR
8 	#include "../CGame.h"
9 	#include "../CHud.h"
10 	#include "../../vdrift/game.h"
11 	#include "../SplitScreen.h"  //-
12 #else
13 	#include "../../editor/CApp.h"
14 	#include "../../editor/CGui.h"
15 	#include "../../editor/settings.h"
16 	#include "../../vdrift/pathmanager.h"
17 #endif
18 #include <BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h>
19 #include <BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h>
20 #include <BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h>
21 #include <boost/filesystem.hpp>
22 #include <Ogre.h> //!
23 using namespace Ogre;
24 
25 
26 ///---------------------------------------------------------------------------------------------------------------
27 ///  track
28 ///---------------------------------------------------------------------------------------------------------------
29 
CreateVdrTrack(std::string strack,TRACK * pTrack)30 void App::CreateVdrTrack(std::string strack, TRACK* pTrack)
31 {
32 	//  materials  -------------
33 	std::vector<OGRE_MESH>& meshes = pTrack->ogre_meshes;
34 	std::string sMatCache = strack + ".matdef", sMatOrig = "_" + sMatCache,
35 		sPathCache = PATHMANAGER::ShaderDir() + "/" + sMatCache, sPathOrig = gcom->TrkDir() +"objects/"+ sMatOrig;
36 	bool hasMatOrig = boost::filesystem::exists(sPathOrig), hasMatCache = boost::filesystem::exists(sPathCache);
37 	bool bGenerate = 0, gen = !hasMatOrig && !hasMatCache || bGenerate;  // set 1 to force generate for new vdrift tracks
38 
39 
40 	//TODO .mat ..rewrite this code for new system
41 #if 0
42 	if (gen)
43 	{
44 		String sMtrs;
45 		for (int i=0; i < meshes.size(); ++i)
46 		{
47 			OGRE_MESH& msh = meshes[i];
48 			if (msh.sky /*&& ownSky*/)  continue;
49 			if (!msh.newMtr)  continue;  //  create material if new
50 
51 			bool found = true;
52 			TexturePtr tex = TextureManager::getSingleton().getByName(msh.material);
53 			if (tex.isNull())
54 			try{
55 				tex = TextureManager::getSingleton().load(msh.material, rgDef);  }
56 			catch(...){
57 				found = false;  }
58 			msh.found = found;  // dont create meshes for not found textures, test
59 			if (!found)  continue;
60 
61 			#if 0  // use 0 for some tracks (eg.zandvoort) - have alpha textures for all!
62 			if (!tex.isNull() && tex->hasAlpha())
63 				msh.alpha = true;  // for textures that have alpha
64 			#endif
65 
66 			if (msh.alpha)
67 				sMtrs += "["+msh.material+"]\n"+
68 					"	parent = 0vdrAlpha\n"+
69 					"	diffuseMap_512 = "+msh.material+"\n";
70 			else
71 				sMtrs += "["+msh.material+"]\n"+
72 					"	parent = 0vdrTrk\n"+
73 					"	diffuseMap_512 = "+msh.material+"\n";
74 		}
75 
76 		std::ofstream fileout(sPathCache.c_str());
77 		if (!fileout)  LogO("Error: Can't save vdrift track matdef!");
78 		fileout.write(sMtrs.c_str(), sMtrs.size());
79 		fileout.close();
80 		hasMatCache = true;
81 	}
82 #endif
83 
84 
85 	//  meshes  -------------
86 	std::vector<Entity*> ents;
87 	static int ii = 0;  int i;
88 	for (i=0; i < meshes.size(); ++i)
89 	{
90 		OGRE_MESH& msh = meshes[i];
91 		if (msh.sky /*&& ownSky*/)  continue;
92 		if (!msh.found)  continue;
93 
94 		//if (strstr(msh.material.c_str(), "tree")!=0)  continue;
95 
96 		//LogO( String("---  model: ") + msh.name + " mtr:" + msh.material +
97 		//" v:" + toStr(msh.mesh->vertices.size()) + " f:" + toStr(msh.mesh->faces.size()) );
98 
99 		//if (ownSky && msh.sky)
100 		if (!msh.sky)
101 		{
102 		ManualObject* m = CreateModel(mSceneMgr, msh.material, msh.mesh, Vector3(0,0,0), false, true);
103 		//if (!m)  continue;
104 		if (msh.sky)
105 			m->setCastShadows(false);
106 
107 		MeshPtr mp = m->convertToMesh("m"+toStr(ii+i));
108 		Entity* e = mSceneMgr->createEntity(mp);
109 
110 		ents.push_back(e);
111 		}
112 	}
113 	ii += i;
114 
115 	//  static geom  -------------
116 	scn->vdrTrack = mSceneMgr->createStaticGeometry("track");
117 	scn->vdrTrack->setRegionDimensions(Vector3::UNIT_SCALE * 1000);  // 1000
118 	scn->vdrTrack->setOrigin(Vector3::ZERO);
119 	scn->vdrTrack->setCastShadows(true);
120 
121 	for (std::vector<Entity*>::iterator it = ents.begin(); it != ents.end(); ++it)
122 		scn->vdrTrack->addEntity(*it, Vector3::ZERO);
123 
124 	scn->vdrTrack->build();
125 	//mStaticGeom->dump("_track-sg.txt");
126 }
127 
128 
129 #ifndef SR_EDITOR
130 
131 //---------------------------------------------------------------------------------------------------------------
132 ///	 track 2D minimap
133 //---------------------------------------------------------------------------------------------------------------
134 
CreateVdrMinimap()135 ManualObject* CHud::CreateVdrMinimap()
136 {
137 	asp = float(app->mWindow->getWidth())/float(app->mWindow->getHeight());
138 
139 	//  get track sizes
140 	minX=FLT_MAX; maxX=FLT_MIN;  minY=FLT_MAX; maxY=FLT_MIN;
141 
142 	const std::list <ROADSTRIP>& roads = app->pGame->track.GetRoadList();
143 	for (std::list <ROADSTRIP>::const_iterator it = roads.begin(); it != roads.end(); ++it)
144 	{
145 		const std::list <ROADPATCH>& pats = (*it).GetPatchList();
146 		for (std::list <ROADPATCH>::const_iterator i = pats.begin(); i != pats.end(); ++i)
147 		{
148 			for (int iy=0; iy<4; ++iy)
149 			for (int ix=0; ix<4; ++ix)
150 			{
151 				const MATHVECTOR<float,3>& vec = (*i).GetPatch().GetPoint(ix,iy);
152 
153 				Real x = vec[0], y = vec[2];
154 				if (x < minX)  minX = x;	if (x > maxX)  maxX = x;
155 				if (y < minY)  minY = y;	if (y > maxY)  maxY = y;
156 			}
157 		}
158 	}
159 
160 	float fMapSizeX = maxX - minX, fMapSizeY = maxY - minY;  // map size
161 	float size = std::max(fMapSizeX, fMapSizeY);
162 	scX = 1.f / size;  scY = 1.f / size;
163 
164 	ManualObject* m = app->mSceneMgr->createManualObject();
165 	m->begin("hud/Minimap", RenderOperation::OT_TRIANGLE_LIST);
166 	int ii = 0;
167 
168 	for (std::list <ROADSTRIP>::const_iterator it = roads.begin(); it != roads.end(); ++it)
169 	{
170 		const std::list <ROADPATCH>& pats = (*it).GetPatchList();
171 		for (std::list <ROADPATCH>::const_iterator i = pats.begin(); i != pats.end(); ++i)
172 		{
173 			float p[16][3];  int a=0;
174 			for (int y=0; y<4; ++y)
175 			for (int x=0; x<4; ++x)
176 			{
177 				const MATHVECTOR<float,3>& vec = (*i).GetPatch().GetPoint(x,y);
178 				p[a][0] = vec[0];  p[a][1] = vec[2];  p[a][2] = vec[1];  a++;
179 			}
180 			a = 0;
181 
182 			// normal
183 			Vector3 pos (p[a  ][2], -p[a  ][0], p[a  ][1]);
184 			Vector3 posX(p[a+3][2], -p[a+3][0], p[a+3][1]);   posX-=pos;  posX.normalise();
185 			Vector3 posY(p[a+12][2],-p[a+12][0],p[a+12][1]);  posY-=pos;  posY.normalise();
186 			Vector3 norm = posX.crossProduct(posY);  norm.normalise();/**/
187 
188 			for (int y=0; y<4; ++y)
189 			for (int x=0; x<4; ++x)
190 			{
191 				Vector3 pos( (p[a][0] - minX)*scX*2-1,	// pos x,y = -1..1
192 							-(p[a][1] - minY)*scY*2+1, 0);  a++;
193 				m->position(pos);
194 				m->normal(norm);/**/
195 
196 				Real c = std::min(1.f, std::max(0.3f, 1.f - 2.4f * powf( fabs(norm.y)
197 					/*norm.absDotProduct(vLi)*/, 0.7f) ));
198 				m->colour(ColourValue(c,c,c,1));
199 
200 				m->textureCoord(x/3.f,y/3.f);
201 				if (x<3 && y<3)
202 				{
203 					int a = ii+x+y*4;
204 					m->index(a+0);	m->index(a+1);	m->index(a+4);
205 					m->index(a+1);	m->index(a+4);	m->index(a+5);
206 				}
207 			}
208 			ii += 16;
209 		}
210 	}
211 	m->end();
212 	m->setUseIdentityProjection(true);  m->setUseIdentityView(true);  // on hud
213 	m->setCastShadows(false);
214 	AxisAlignedBox aab;  aab.setInfinite();  m->setBoundingBox(aab);  // draw always
215 	m->setRenderingDistance(100000.f);
216 	m->setRenderQueueGroup(RQG_Hud2);  m->setVisibilityFlags(RV_Hud);
217 	return m;
218 }
219 #endif
220 
221 
222 //  utility - create VDrift model in Ogre
223 //-------------------------------------------------------------------------------------------------------
CreateModel(SceneManager * sceneMgr,const String & mat,class VERTEXARRAY * a,Vector3 vPofs,bool flip,bool track,const String & name)224 ManualObject* App::CreateModel(SceneManager* sceneMgr, const String& mat,
225 	class VERTEXARRAY* a, Vector3 vPofs, bool flip, bool track, const String& name)
226 {
227 	int verts = a->vertices.size();
228 	if (verts == 0)  return NULL;
229 	int tcs   = a->texcoords[0].size(); //-
230 	int norms = a->normals.size();
231 	int faces = a->faces.size();
232 	// norms = verts, verts % 3 == 0
233 
234 	ManualObject* m;
235 	if (name == "")
236 		m = sceneMgr->createManualObject();
237 	else
238 		m = sceneMgr->createManualObject(name);
239 	m->begin(mat, RenderOperation::OT_TRIANGLE_LIST);
240 
241 	int t = 0;
242 	if (track)
243 	{	for (int v = 0; v < verts; v += 3)
244 		{
245 			m->position(a->vertices[v+0], a->vertices[v+2], -a->vertices[v+1]);
246 			if (norms)
247 			m->normal(	a->normals [v+0], a->normals [v+2], -a->normals [v+1]);
248 			if (t < tcs)
249 			{	m->textureCoord(a->texcoords[0][t], a->texcoords[0][t+1]);  t += 2;	}
250 		}
251 		for (int f = 0; f < faces; ++f)
252 			m->index(a->faces[f]);
253 	}else
254 	if (flip)
255 	{	for (int v = 0; v < verts; v += 3)
256 		{
257 			m->position(a->vertices[v], a->vertices[v+1], a->vertices[v+2]);
258 			if (norms)
259 			m->normal(  a->normals [v], a->normals [v+1], a->normals [v+2]);
260 			if (t < tcs)
261 			{	m->textureCoord(a->texcoords[0][t], a->texcoords[0][t+1]);  t += 2;	}
262 		}
263 		for (int f = 0; f < faces; f += 3)
264 		{	m->index(a->faces[f+2]);  m->index(a->faces[f+1]);  m->index(a->faces[f]);	}
265 	}else
266 	{	for (int v = 0; v < verts; v += 3)
267 		{
268 			m->position(-a->vertices[v+1]+vPofs.x, -a->vertices[v+2]+vPofs.y, a->vertices[v]+vPofs.z);
269 			if (norms)
270 			m->normal(	-a->normals [v+1], -a->normals [v+2], a->normals [v]);
271 			if (t < tcs)
272 			{	m->textureCoord(a->texcoords[0][t], a->texcoords[0][t+1]);  t += 2;	}
273 		}
274 		for (int f = 0; f < faces; f += 3)
275 		{	m->index(a->faces[f+2]);  m->index(a->faces[f+1]);  m->index(a->faces[f]);	}
276 	}
277 	m->end();
278 	return m;
279 }
280 
281 
282 //----------------------------------------------------
IsVdrTrack()283 bool App::IsVdrTrack()
284 {
285 	//  vdrift track has roads.trk
286 	String svdr = gcom->TrkDir()+"roads.trk";
287 	bool vdr = boost::filesystem::exists(svdr);
288 	return vdr;
289 }
290 
291 
292 #ifdef SR_EDITOR
GetIndexedMesh(const MODEL & model)293 btIndexedMesh GetIndexedMesh(const MODEL & model)
294 {
295 	const float * vertices;  int vcount;
296 	const int * faces;  int fcount;
297 	model.GetVertexArray().GetVertices(vertices, vcount);
298 	model.GetVertexArray().GetFaces(faces, fcount);
299 
300 	assert(fcount % 3 == 0); //Face count is not a multiple of 3
301 
302 	btIndexedMesh mesh;
303 	mesh.m_numTriangles = fcount / 3;
304 	mesh.m_triangleIndexBase = (const unsigned char *)faces;
305 	mesh.m_triangleIndexStride = sizeof(int) * 3;
306 	mesh.m_numVertices = vcount;
307 	mesh.m_vertexBase = (const unsigned char *)vertices;
308 	mesh.m_vertexStride = sizeof(float) * 3;
309 	mesh.m_vertexType = PHY_FLOAT;
310 	return mesh;
311 }
312 
DestroyVdrTrackBlt()313 void App::DestroyVdrTrackBlt()
314 {
315 	//  remove old track
316 	if (trackObject)
317 	{
318 		world->removeCollisionObject(trackObject);
319 
320 		delete trackObject->getCollisionShape();
321 		trackObject->setCollisionShape(NULL);
322 
323 		delete trackObject;
324 		trackObject = NULL;
325 
326 		delete trackMesh;
327 		trackMesh = NULL;
328 	}
329 }
330 
CreateVdrTrackBlt()331 void App::CreateVdrTrackBlt()
332 {
333 	DestroyVdrTrackBlt();
334 
335 	//  setup new track
336 	trackMesh = new btTriangleIndexVertexArray();
337 	const std::list<TRACK_OBJECT> & objects = track->GetTrackObjects();
338 	for (std::list<TRACK_OBJECT>::const_iterator ob = objects.begin(); ob != objects.end(); ++ob)
339 	{
340 		//if (ob->GetSurface() != NULL)
341 		{
342 			MODEL & model = *ob->GetModel();
343 			btIndexedMesh mesh = GetIndexedMesh(model);
344 			trackMesh->addIndexedMesh(mesh);
345 		}
346 	}
347 
348 	btCollisionShape * trackShape = new btBvhTriangleMeshShape(trackMesh, false);
349 	trackObject = new btCollisionObject();
350 	trackObject->setCollisionShape(trackShape);
351 	trackObject->setUserPointer(NULL);
352 
353 	world->addCollisionObject(trackObject);
354 }
355 #endif
356