1 #include "pch.h"
2 #include "common/Def_Str.h"
3 #include "common/Gui_Def.h"
4 #include "CGame.h"
5 #include "CHud.h"
6 #include "CGui.h"
7 #include "common/GuiCom.h"
8 #include "common/CScene.h"
9 #include "common/WaterRTT.h"
10 #include "common/data/SceneXml.h"
11 #include "common/data/FluidsXml.h"
12 #include "FollowCamera.h"
13 #include "../road/Road.h"
14 #include "../road/PaceNotes.h"
15 #include "../vdrift/game.h"
16 #include "../vdrift/quickprof.h"
17 #include "../paged-geom/PagedGeometry.h"
18 #include "../network/masterclient.hpp"
19 #include "../network/gameclient.hpp"
20 #include "LinearMath/btDefaultMotionState.h"
21 #include "SplitScreen.h"
22 #include "../shiny/Main/Factory.hpp"
23 #include "../sdl4ogre/sdlinputwrapper.hpp"
24
25 #include <OgreParticleSystem.h>
26 #include <OgreManualObject.h>
27 #include <OgreMaterialManager.h>
28 #include <OgreSceneNode.h>
29 #include <OgreViewport.h>
30 #include <OgreTimer.h>
31 #include "common/MultiList2.h"
32 #include "common/Slider.h"
33 #include <MyGUI.h>
34 using namespace Ogre;
35 using namespace MyGUI;
36
37
38 #define isKey(a) mInputWrapper->isKeyDown(a)
39
40
41 // simulation (2nd) thread
42 //---------------------------------------------------------------------------------------------------------------
43
UpdThr()44 void App::UpdThr()
45 {
46 Ogre::Timer gtim;
47 //#ifdef _WIN32
48 //DWORD af = 2;
49 //gtim.setOption("QueryAffinityMask", &af);
50 //#endif
51 gtim.reset();
52
53 while (!mShutDown)
54 {
55 /// step Game **
56
57 double dt = double(gtim.getMicroseconds()) * 0.000001;
58 gtim.reset();
59
60 if (pSet->multi_thr == 1 && !bLoading && !mShutDown)
61 {
62 bSimulating = true;
63 bool ret = pGame->OneLoop(dt);
64 if (!ret)
65 mShutDown = true; //ShutDown();
66
67 DoNetworking();
68 bSimulating = false;
69 }
70 boost::this_thread::sleep(boost::posix_time::milliseconds(pSet->thread_sleep));
71 }
72 }
73
74
isTweakTab()75 bool App::isTweakTab()
76 {
77 int tt = !gui->tabTweak ? 0 : gui->tabTweak->getIndexSelected();
78 return isTweak() && tt != 1 && tt != 2;
79 }
80
81
82 /// Newtork update . . . .
DoNetworking()83 void App::DoNetworking()
84 {
85 bool doNetworking = (mClient && mClient->getState() == P2PGameClient::GAME);
86
87 // no pause in networked game
88 int tt = !gui->tabTweak ? 0 : gui->tabTweak->getIndexSelected();
89 bool gui = isFocGui || isTweakTab();
90 pGame->pause = bRplPlay ? (bRplPause || gui) : (gui && !doNetworking);
91
92 // handle networking stuff
93 if (doNetworking)
94 {
95 PROFILER.beginBlock("-network");
96
97 // update the local car's state to the client
98 protocol::CarStatePackage cs; // FIXME: Handles only one local car
99 for (CarModels::const_iterator it = carModels.begin(); it != carModels.end(); ++it)
100 {
101 if ((*it)->eType == CarModel::CT_LOCAL)
102 {
103 cs = (*it)->pCar->GetCarStatePackage();
104 cs.trackPercent = uint8_t( (*it)->trackPercent / 100.f * 255.f); // pack to uint8
105 break;
106 }
107 }
108 mClient->setLocalCarState(cs);
109
110 // check for new car states
111 protocol::CarStates states = mClient->getReceivedCarStates();
112 for (protocol::CarStates::const_iterator it = states.begin(); it != states.end(); ++it)
113 {
114 int8_t id = it->first; // Car number // FIXME: Various places assume carModels[0] is local
115 if (id == 0) id = mClient->getId();
116
117 CarModel* cm = carModels[id];
118 if (cm && cm->pCar)
119 {
120 cm->pCar->UpdateCarState(it->second);
121 cm->trackPercent = cm->pCar->trackPercentCopy; // got from client
122 }
123 }
124 PROFILER.endBlock("-network");
125 }
126 }
127
128
129 // Frame Start
130 //---------------------------------------------------------------------------------------------------------------
131
frameStart(Real time)132 bool App::frameStart(Real time)
133 {
134 PROFILER.beginBlock(" frameSt");
135 fLastFrameDT = time;
136
137
138 // input
139 for (int i=0; i<4; ++i)
140 {
141 boost::lock_guard<boost::mutex> lock(input->mPlayerInputStateMutex);
142 for (int a = 0; a < NumPlayerActions; ++a)
143 input->mPlayerInputState[i][a] = mInputCtrlPlayer[i]->getChannel(a)->getValue();
144 }
145
146 if (imgBack && pGame) // show/hide background image
147 {
148 bool backImgVis = !bLoading && pGame->cars.empty();
149 imgBack->setVisible(backImgVis);
150 }
151
152
153 // multi thread
154 if (pSet->multi_thr == 1 && pGame && !bLoading)
155 {
156 updatePoses(time);
157 }
158
159 /// graphs update -._/\_-.
160 if (pSet->show_graphs && graphs.size() > 0)
161 {
162 GraphsNewVals();
163 UpdateGraphs();
164 }
165
166 //...................................................................
167 ///* tire edit */
168 if ((pSet->graphs_type == Gh_TireEdit || pSet->graphs_type == Gh_Tires4Edit) &&
169 carModels.size() > 0 && !mWndTweak->getVisible())
170 {
171 int k = (isKey(SDL_SCANCODE_1) || isKey(SDL_SCANCODE_KP_DIVIDE) ? -1 : 0)
172 + (isKey(SDL_SCANCODE_2) || isKey(SDL_SCANCODE_KP_MULTIPLY) ? 1 : 0);
173 if (k)
174 {
175 double mul = shift ? 0.2 : (ctrl ? 4.0 : 1.0);
176 mul *= 0.005; // par
177
178 CARDYNAMICS& cd = carModels[0]->pCar->dynamics;
179 CARTIRE* tire = cd.GetTire(FRONT_LEFT);
180 if (iEdTire == 1) // longit |
181 {
182 Dbl& val = tire->longitudinal[iCurLong]; // modify 1st
183 val += mul*k * (1 + abs(val));
184 for (int i=1; i<4; ++i)
185 cd.GetTire(WHEEL_POSITION(i))->longitudinal[iCurLong] = val; // copy for rest
186 }
187 else if (iEdTire == 0) // lateral --
188 {
189 Dbl& val = tire->lateral[iCurLat];
190 val += mul*k * (1 + abs(val));
191 for (int i=1; i<4; ++i)
192 cd.GetTire(WHEEL_POSITION(i))->lateral[iCurLat] = val;
193 }
194 else // align o
195 {
196 Dbl& val = tire->aligning[iCurAlign];
197 val += mul*k * (1 + abs(val));
198 for (int i=1; i<4; ++i)
199 cd.GetTire(WHEEL_POSITION(i))->aligning[iCurAlign] = val;
200 }
201
202 // update hat, 1st
203 tire->CalculateSigmaHatAlphaHat();
204 for (int i=1; i<4; ++i) // copy for rest
205 { cd.GetTire(WHEEL_POSITION(i))->sigma_hat = tire->sigma_hat;
206 cd.GetTire(WHEEL_POSITION(i))->alpha_hat = tire->alpha_hat;
207 }
208 iUpdTireGr = 1;
209 }
210 }
211 //...................................................................
212
213
214 /// gui
215 gui->GuiUpdate();
216
217
218 if (bWindowResized)
219 { bWindowResized = false;
220
221 gcom->ResizeOptWnd();
222 gcom->SizeGUI();
223 gcom->updTrkListDim();
224 gui->updChampListDim(); // resize lists
225 gui->slSSS(0);
226 gui->listCarChng(gui->carList,0); // had wrong size
227 bRecreateHUD = true;
228
229 if (mSplitMgr) // reassign car cameras from new viewports
230 { std::list<Camera*>::iterator it = mSplitMgr->mCameras.begin();
231 for (int i=0; i < carModels.size(); ++i)
232 if (carModels[i]->fCam && it != mSplitMgr->mCameras.end())
233 { carModels[i]->fCam->mCamera = *it; ++it; }
234 }
235 if (!mSplitMgr->mCameras.empty())
236 {
237 Camera* cam1 = *mSplitMgr->mCameras.begin();
238 scn->mWaterRTT->setViewerCamera(cam1);
239 if (scn->grass) scn->grass->setCamera(cam1);
240 if (scn->trees) scn->trees->setCamera(cam1);
241 }
242
243 ///gui->InitCarPrv();
244 }
245
246 // hud update sizes, after res change
247 if (bRecreateHUD)
248 { bRecreateHUD = false;
249
250 hud->Destroy(); hud->Create();
251 }
252 if (bSizeHUD)
253 { bSizeHUD = false;
254
255 hud->Size();
256 }
257
258
259 if (bLoading)
260 {
261 NewGameDoLoad();
262 PROFILER.endBlock(" frameSt");
263 return true;
264 }
265 else
266 {
267 /// loading end ------
268 const int iFr = 3;
269 if (iLoad1stFrames >= 0)
270 { ++iLoad1stFrames;
271 if (iLoad1stFrames == iFr)
272 {
273 LoadingOff(); // hide loading overlay
274 mSplitMgr->mGuiViewport->setClearEveryFrame(true, FBT_DEPTH);
275 gui->Ch_LoadEnd();
276 bLoadingEnd = true;
277 iLoad1stFrames = -1; // for refl
278 }
279 }else if (iLoad1stFrames >= -1)
280 {
281 --iLoad1stFrames; // -2 end
282
283 imgLoad->setVisible(false); // hide back imgs
284 if (imgBack)
285 imgBack->setVisible(false);
286 }
287
288
289 // input
290 if (isFocGui && pSet->inMenu == MNU_Options && !pSet->isMain &&
291 mWndTabsOpts->getIndexSelected() == TABo_Input)
292 gui->UpdateInputBars();
293
294
295 // keys up/dn, for lists
296 static float dirU = 0.f,dirD = 0.f;
297 if (isFocGui && !pSet->isMain && !isTweak())
298 {
299 if (isKey(SDL_SCANCODE_UP) ||isKey(SDL_SCANCODE_KP_8)) dirD += time; else
300 if (isKey(SDL_SCANCODE_DOWN)||isKey(SDL_SCANCODE_KP_2)) dirU += time; else
301 { dirU = 0.f; dirD = 0.f; }
302 int d = ctrl ? 4 : 1;
303 if (dirU > 0.0f) { gui->LNext( d); dirU = -0.2f; }
304 if (dirD > 0.0f) { gui->LNext(-d); dirD = -0.2f; }
305 }
306
307 /// Gui updates from Networking
308 gui->UpdGuiNetw();
309
310
311 // replay forward,backward keys
312 if (bRplPlay)
313 {
314 isFocRpl = ctrl;
315 bool le = isKey(SDL_SCANCODE_LEFTBRACKET), ri = isKey(SDL_SCANCODE_RIGHTBRACKET), ctrlN = ctrl && (le || ri);
316 int ta = ((le || gui->bRplBack) ? -2 : 0) + ((ri || gui->bRplFwd) ? 2 : 0);
317 if (ta)
318 { double tadd = ta;
319 tadd *= (shift ? 0.2 : 1) * (ctrlN ? 4 : 1) * (alt ? 8 : 1); // multipliers
320 if (!bRplPause) tadd -= 1; // play compensate
321 double t = pGame->timer.GetReplayTime(0), len = replay.GetTimeLength();
322 t += tadd * time; // add
323 if (t < 0.0) t += len; // cycle
324 if (t > len) t -= len;
325 pGame->timer.SetReplayTime(0, t);
326 }
327 }
328
329 if (!pGame)
330 {
331 PROFILER.endBlock(" frameSt");
332 return false;
333 }
334
335
336 if (pSet->multi_thr == 0)
337 DoNetworking();
338
339
340 // single thread, sim on draw
341 bool ret = true;
342 if (pSet->multi_thr == 0)
343 {
344 ret = pGame->OneLoop(time);
345 if (!ret)
346 ShutDown();
347 updatePoses(time);
348 }
349
350 // align checkpoint arrow
351 // move in front of camera
352 if (pSet->check_arrow && hud->arrow.node && !bRplPlay && !carModels.empty())
353 {
354 FollowCamera* cam = carModels[0]->fCam;
355
356 Vector3 pos = cam->mCamera->getPosition();
357 Vector3 dir = cam->mCamera->getDirection(); dir.normalise();
358 Vector3 up = cam->mCamera->getUp(); up.normalise();
359 Vector3 arrowPos = pos + 10.0f * dir + 3.5f*up;
360 hud->arrow.node->setPosition(arrowPos);
361
362 // animate
363 bool bFirstFrame = carModels.front()->bGetStPos;
364 if (bFirstFrame) // 1st frame: dont animate
365 hud->arrow.qCur = hud->arrow.qEnd;
366 else
367 hud->arrow.qCur = Quaternion::Slerp(time*5, hud->arrow.qStart, hud->arrow.qEnd, true);
368 hud->arrow.nodeRot->setOrientation(hud->arrow.qCur);
369
370 // look down -y a bit so we can see the arrow better
371 hud->arrow.nodeRot->pitch(Degree(-20), SceneNode::TS_LOCAL);
372 }
373
374 // cam info text
375 if (pSet->show_cam && !carModels.empty() && hud->txCamInfo)
376 { FollowCamera* cam = carModels[0]->fCam;
377 if (cam)
378 { bool vis = cam->updInfo(time) && !isFocGui;
379 if (vis)
380 hud->txCamInfo->setCaption(String(cam->ss));
381 hud->txCamInfo->setVisible(vis);
382 } }
383
384
385 // update all cube maps
386 PROFILER.beginBlock("g.refl");
387 for (std::vector<CarModel*>::iterator it=carModels.begin(); it!=carModels.end(); it++)
388 if (!(*it)->isGhost() && (*it)->pReflect)
389 (*it)->pReflect->Update(iLoad1stFrames == -1);
390 PROFILER.endBlock("g.refl");
391
392
393 // trees
394 PROFILER.beginBlock("g.veget");
395 if (scn->road) {
396 if (scn->grass) scn->grass->update();
397 if (scn->trees) scn->trees->update(); }
398 PROFILER.endBlock("g.veget");
399
400
401 // road upd lods
402 if (scn->road)
403 {
404 //PROFILER.beginBlock("g.road"); // below 0.0 ms
405
406 // more than 1: in pre viewport, each frame
407 if (mSplitMgr->mNumViewports == 1)
408 {
409 roadUpdTm += time;
410 if (roadUpdTm > 0.1f) // interval [sec]
411 {
412 roadUpdTm = 0.f;
413 scn->road->UpdLodVis(pSet->road_dist);
414 }
415 }
416 //PROFILER.endBlock("g.road");
417 }
418
419 //[]() pace upd vis ~ ~ ~
420 if (scn->pace)
421 {
422 const CarModel* cm = *carModels.begin();
423 Vector3 p = cm->pMainNode->getPosition();
424 float vel = cm->pCar->GetSpeedometer();
425 scn->pace->carVel = vel;
426 scn->pace->rewind = cm->pCar->bRewind;
427 scn->pace->UpdVis(p);
428 }
429
430
431 //** bullet bebug draw
432 if (dbgdraw) { // DBG_DrawWireframe
433 dbgdraw->setDebugMode(pSet->bltDebug ? 1 /*+(1<<13) 255*/ : 0);
434 dbgdraw->step(); }
435
436
437 /// terrain mtr from blend maps
438 // now in CarModel::Update
439 //UpdWhTerMtr(pCar);
440
441 // stop rain/snow when paused
442 if (scn->pr && scn->pr2 && pGame)
443 {
444 if (pGame->pause)
445 { scn->pr->setSpeedFactor(0.f); scn->pr2->setSpeedFactor(0.f); }
446 else{ scn->pr->setSpeedFactor(1.f); scn->pr2->setSpeedFactor(1.f); }
447 }
448
449
450 // update shader time
451 mTimer += time;
452 mFactory->setSharedParameter("windTimer", sh::makeProperty <sh::FloatValue>(new sh::FloatValue(mTimer)));
453 mFactory->setSharedParameter("waterTimer", sh::makeProperty <sh::FloatValue>(new sh::FloatValue(mTimer)));
454
455
456 ///() grass sphere pos
457 bool hasCars = !carModels.empty();
458 if (hasCars)
459 {
460 Real r = 1.7; r *= r; //par
461 const Vector3* p = &carModels[0]->posSph[0];
462 mFactory->setSharedParameter("posSph0", sh::makeProperty <sh::Vector4>(new sh::Vector4(p->x,p->y,p->z,r)));
463 p = &carModels[0]->posSph[1];
464 mFactory->setSharedParameter("posSph1", sh::makeProperty <sh::Vector4>(new sh::Vector4(p->x,p->y,p->z,r)));
465 }else
466 { mFactory->setSharedParameter("posSph0", sh::makeProperty <sh::Vector4>(new sh::Vector4(0,0,500,-1)));
467 mFactory->setSharedParameter("posSph1", sh::makeProperty <sh::Vector4>(new sh::Vector4(0,0,500,-1)));
468 }
469
470 ///~~ fluid fog, send params to shaders
471 if (hasCars && pSet->game.local_players == 1)
472 {
473 int fi = carModels[0]->iCamFluid;
474 float p = carModels[0]->fCamFl;
475 //? if (fi != idFlOld) {
476 if (fi >= 0)
477 { const FluidBox* fb = &scn->sc->fluids[fi];
478 const FluidParams& fp = scn->sc->pFluidsXml->fls[fb->id];
479
480 mFactory->setSharedParameter("fogFluidH", sh::makeProperty <sh::Vector4>(new sh::Vector4(
481 fb->pos.y +p /*+0.5f par? ofsH..*/, 1.f / fp.fog.dens, fp.fog.densH +p*0.5f, 0)));
482
483 mFactory->setSharedParameter("fogFluidClr", sh::makeProperty <sh::Vector4>(new sh::Vector4(
484 fp.fog.r, fp.fog.g, fp.fog.b, fp.fog.a)));
485 }else
486 mFactory->setSharedParameter("fogFluidH", sh::makeProperty <sh::Vector4>(new sh::Vector4(
487 -900.f, 1.f/17.f, 0.15f, 0)));
488
489 }// no else, set in setFog default
490
491
492 // Signal loading finished to the peers
493 if (mClient && bLoadingEnd)
494 {
495 bLoadingEnd = false;
496 mClient->loadingFinished();
497 }
498
499 PROFILER.endBlock(" frameSt");
500
501 return ret;
502 }
503 PROFILER.endBlock(" frameSt");
504 }
505
frameEnd(Real time)506 bool App::frameEnd(Real time)
507 {
508 // sleep when in Gui
509 if (isFocGui && pSet->gui_sleep >= 0) // && gui && gui->bGI)
510 //!pSet->isMain && pSet->inMenu == MNU_Single && mWndTabsGame->getIndexSelected() == TAB_Multi)
511 boost::this_thread::sleep(boost::posix_time::milliseconds(pSet->gui_sleep));
512
513 return true;
514 }
515