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