Rise
The Vieneo Province
TurnByTurn.cpp
Go to the documentation of this file.
1 #include "TurnByTurn.h"
2 #define _USE_MATH_DEFINES
3 #include <math.h>
4 #include "DXUT.h"
5 #include "globals.h"
6 
7 TurnByTurn::TurnByTurn(Bus* pBus, Logger* pLogger, Networking* pNetworking) {
8  bus = pBus;
9  logger = pLogger;
10  logger->AddToCallStack("TurnByTurn::ctor");
11  networking = pNetworking;
12 }
13 
15  SAFE_RELEASE(m_avRouteMap);
16 }
17 
18 void TurnByTurn::Update(bool pIsGrndVehicle, float pElapsedTime) {
19  logger->AddToCallStack("TurnByTurn::Update");
20  elapsedCounter += pElapsedTime;
21 
22  // formatting the display text and Bill's guide arrow idea
23  // requesting vocal guidance approach the next node
24  // advancing to the next node
25  // requesting vocal guidance for new node
26 
27  if (pIsGrndVehicle)
28  {
29  // If we recieved new nodes, we reset the indices
30  if (bus->turnByTurnDirty) {
33  }
34  // so your "x" value in the same scale is "(float)tcp.u + assayProgressU"
35  // and "y" should be "(float)tcp.v + assayProgressV"
36  vehiclePos.x = static_cast<float>(bus->tcp.u) + bus->assayProgressU;
37  vehiclePos.y = static_cast<float>(bus->tcp.v) + bus->assayProgressV;
39 
40  if (!bus->nodes.empty()) {
41  // First we get the distance between us and the current waypoint
42  float closestWaypointDist{ 0.0f };
43  float activeWaypointDist{ 0.0f };
44  try {
45  closestWaypointDist = distanceBetweenPositions(vehiclePos, bus->nodes.at(closestWaypointIndex).position);
46  activeWaypointDist = distanceBetweenPositions(vehiclePos, bus->nodes.at(activeWaypointIndex).position);
47  }
48  catch (std::exception error) {
49  closestWaypointDist = 99.0f;
50  activeWaypointDist = 99.0f;
51  }
52  // Then we check if any waypoint is closer
53  float nodeDist = 9999.0f;
54  Snode node;
55  bool clearNodes = false;
56  for (auto iter = bus->nodes.begin(); iter != bus->nodes.end(); ++iter) {
57  node = *iter;
58  nodeDist = distanceBetweenPositions(vehiclePos, node.position);
59  // If this waypoint is closer, this becomes the active waypoint
60  if (nodeDist < closestWaypointDist) {
61  closestWaypointIndex = iter - bus->nodes.begin();
62  }
63  }
64  // If our closest waypoint isn't the currently active one or the one we just came from
66  // if the closestWaypointIndex is smaller then the previous, we reset our navigation to that index
68  //activeWaypointIndex = closestWaypointIndex;
69  }
71  // We somehow skipped a part, but we forward our active waypoint to the closest one
72  // activeWaypointIndex = closestWaypointIndex;
73  //this->sendUpdateToServer(bus->nodes.at(activeWaypointIndex).edgeId, 0.0f, 0, UpdateType::TYPE_NEXT_NODE);
74  //
75  }
76  }
77  // If we are closer to the waypoint then the threshhold, we reached this waypoint and the next becomes active
78  for (auto iter = bus->nodes.begin() + activeWaypointIndex; iter != bus->nodes.end(); ++iter) {
79  node = *iter;
80  const float dist = distanceBetweenPositions(vehiclePos, node.position);
81  // If we reached our next waypoint, we set the next one as active
82  if (dist < cReachedWaypointThreshold) {
83  activeWaypointIndex = (iter - bus->nodes.begin());
84  nextWaypointIndex = (iter - bus->nodes.begin()) + 1;
85  // Check if this was the last waypoint
86  if (nextWaypointIndex >= bus->nodes.size() - 1) {
87  // TODO: Last waypoint reached, finished navigation
91  clearNodes = true;
92  this->sendUpdateToServer(0, 0.0f, 0, UpdateType::TYPE_NAVIGATION_COMPLETED);
95  }
96  }
97  }
98  float distanceTraveled = 0.0f;
99  if (lastVehiclePos.x != 0.0f && lastVehiclePos.y != 0.0f) {
101  }
102  this->updateHeadingState();
103  if (clearNodes) {
104  bus->nodes.clear();
105  }
106  }
107  if (bus->turnByTurnDirty && !bus->nodes.empty()) {
108  this->CreateVB(DXUTGetD3D9Device());
111  bus->turnByTurnDirty = false;
112  }
113  if (elapsedCounter > 0.5f) {
114  this->UpdateVB(DXUTGetD3D9Device());
115  elapsedCounter = 0.0f;
116  }
118  }
119 }
120 
121 void TurnByTurn::Draw(IDirect3DDevice9* pd3dDevice)
122 {
123  logger->AddToCallStack("TurnByTurn::Draw");
124  // problem is this line data is not conducive to sprite drawing!
125  // problem is this would be perfect in a module but modules don't have vertexbuffers!
126  // and you could not simply translate and scale the static buffer since the line should only go from our current location to the next node!
127  if (!m_avRouteMap)
128  return;
129 
130  HRESULT hr;
131  D3DVIEWPORT9 mvp, oldmvp;
132  // 49,271 and 128x128
133  // all of these use displayscaley because the aspect is locked
134  mvp.X = 0;
135  mvp.Y = 213;
136  mvp.Width = 137;
137  mvp.Height = 64;
138  mvp.MinZ = 0.0f; mvp.MaxZ = 1.0f;
139  V(pd3dDevice->GetViewport(&oldmvp));
140  V(pd3dDevice->SetViewport(&mvp));
141 
142  V(pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false));
143  V(pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2));
144  V(pd3dDevice->SetStreamSource(0, m_avRouteMap, 0, sizeof(D3DSCREEN)));
145  V(pd3dDevice->SetFVF(D3DFVF_SCREEN));
146  V(pd3dDevice->DrawPrimitive(D3DPT_LINESTRIP, 0, lineCount));
147 
148  V(pd3dDevice->SetViewport(&oldmvp));
149 }
150 
151 void TurnByTurn::CreateVB(IDirect3DDevice9* pd3dDevice)
152 {
153  logger->AddToCallStack("TurnByTurn::CreateVB");
154 
155  if (!bus)
156  return;
157 
158  HRESULT hr;
159  SAFE_RELEASE(m_avRouteMap);
160  /*V(pd3dDevice->CreateVertexBuffer((bus->nodes.size() + 1) * sizeof(D3DSCREEN),
161  D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, D3DFVF_SCREEN,
162  D3DPOOL_DEFAULT, &m_avRouteMap, nullptr));*/
163 }
164 
165 void TurnByTurn::UpdateVB(IDirect3DDevice9* pd3dDevice)
166 {
167  // As long as the bus isn't initialized yet, we can't really do anything
168  logger->AddToCallStack("TurnByTurn::UpdateVB");
169 
170  if (!bus)
171  return;
172 
173  if (bus->nodes.empty())
174  return;
175 
176  if (!m_avRouteMap)
177  return;
178 
179  HRESULT hr;
180  D3DSCREEN* vtxs;
181  V(m_avRouteMap->Lock(0, 0, reinterpret_cast<void**>(&vtxs), D3DLOCK_DISCARD));
182 
183  // Begin node is always the center of the screen
184  (*vtxs).x = 68.0f; (*vtxs).y = 248.0f; (*vtxs).z = 0.0f; (*vtxs).w = 1.0f;
185  (*vtxs).diffuse = D3DCOLOR_XRGB(255, 255, 255);
186  vtxs++;
187 
188  Snode node;
189  lineCount = 0;
190  // 68,236 is the center of the texture which is 907,352 ... which means
191  for (auto iter = bus->nodes.begin() + nextWaypointIndex; iter != bus->nodes.end(); ++iter)
192  {
193  node = *iter;
194  const D3DXVECTOR2 mapPosition = convertWorldPositionToMapPosition(node.position);
195  (*vtxs).x = 68.0f + mapPosition.x; (*vtxs).y = 248.0f + mapPosition.y; (*vtxs).z = 0.0f; (*vtxs).w = 1.0f;
196  (*vtxs).diffuse = D3DCOLOR_XRGB(255, 255, 0);
197  vtxs++;
198  lineCount++;
199  }
200 
201  V(m_avRouteMap->Unlock());
202 }
203 
204 D3DXVECTOR2 TurnByTurn::convertWorldPositionToMapPosition(const D3DXVECTOR2& pPos) {
205 
206  // Citymap.dds is 2048,2048 and has 3 x 3 sectors
207  // Map starts at tcp.u 519 tcp.v = 1101
208  // this means each sector is 682,666667 pixels at 100%
209  // One grid tile in CityMap.dds = 170,6666666666667 at 100%
210  // position in a sector is on 0.0 to 1.0f
211  // so we multiply position in sector (0.0 - 1.0) with the pixelsize of a sector to get the pixel position on the CityMap.dds
212  // then we have to take zoom into account
213  // center for x = 68.0f;
214  // center for y = 248.0f;
215  // so mag is 1 at 10km scale ... but that is actually 138/2048 or 0.673828125km across, 0.3369140625 from the center to edge
216 
217  D3DXVECTOR2 retPos;
218  retPos.x = (pPos.x - mapStartTcpU) - (vehiclePos.x - mapStartTcpU);
219  retPos.y = (pPos.y - mapStartTcpV) - (vehiclePos.y - mapStartTcpV);
220  retPos.x *= (sectorSize * mapMagnifier);
221  retPos.y *= (sectorSize * mapMagnifier);
222  // somehow we need to offset Y a little bit to make it look good on the map
223  retPos.y -= 3.0f;
224  return retPos;
225 }
226 
228 {
229  SAFE_RELEASE(m_avRouteMap);
230 }
231 
232 void TurnByTurn::sendUpdateToServer(int pEdgeId, float pDistance, size_t pDirection, size_t pType) {
233  // Communication to server
234  // So in the packets you send me I need the edgeId of course (unless you don't want it to say the street name because it isn't changing then sent -1)
235  // distance ...
236  // direction enumeration (like 0 is straight, 1 is bear left, 2 is turn left, 3 is bear right, 4 is turn right, 5 is u-turn) ...
237  // and also what type it is (0=early notice of change, 1=affect change, 2=after change was successful, 3=node closest 5=navigation finished)
238  SClientPacket outpacket;
239  outpacket.type = 25; // TurnByTurn
240  outpacket.f_x = static_cast<float>(pEdgeId); // edgeId
241  outpacket.f_y = pDistance; // distance in meters
242  outpacket.f_z = static_cast<float>(pDirection); // direction enum
243  outpacket.f_w = static_cast<float>(pType); // type
244  networking->SendToServer(&outpacket, sizeof(SClientPacket), true);
245 }
246 
248 {
249  if (bus->nodes.empty())
250  return;
251 
252  char msg[255];
253  float distanceChecked = 0.0f;
254  const float drivingDirection = angleBetweenPositionsDeg(lastVehiclePos, vehiclePos);
255  D3DXVECTOR2 lastPosition;
256  lastPosition = bus->nodes.at(headingChangeEndWaypointIndex).position;
258  size_t iterCounter = 0;
259  for (size_t index = headingChangeEndWaypointIndex; index < bus->nodes.size() - 1; ++index) {
260  // Connections between most nodes look like this
261  // ___ <- A
262  // \ <- B
263  // | <- C
264  // If we only A -> B, we will only get a direction change of 45 degrees
265  // So by default, you want to check A -> C nodes ahead, and see what direction change that gives you (in this case, closer to 90 degrees)
266  // If that is not possible (becase we are at the end of the list) then we take only 1 node ahead
267  bool gotChange = false;
268  float heading = 0.0;
269  float headingDiff = 0.0;
270  float distanceIncludingThisLoop = 0.0;
271  heading = angleBetweenPositionsDeg(lastPosition, bus->nodes.at(index + 1).position);
272  headingDiff = this->getHeadingChange(heading, bus->HeadingTrueDegrees);
273  distanceIncludingThisLoop = distanceBetweenPositions(lastPosition, bus->nodes.at(index + 1).position);
274  if (index + 2 < bus->nodes.size() && abs(headingDiff) > cDirectionChangeThreshold) {
275  heading = angleBetweenPositionsDeg(bus->nodes.at(index + 1).position, bus->nodes.at(index + 2).position);
276  headingDiff = this->getHeadingChange(heading, bus->HeadingTrueDegrees);
277  distanceIncludingThisLoop += distanceBetweenPositions(bus->nodes.at(index + 1).position, bus->nodes.at(index + 2).position);
278  }
279  lastPosition = bus->nodes.at(index + 1).position;
280 
281  if (abs(headingDiff) > cDirectionChangeThreshold) {
282  gotChange = true;
284  headingChangeEndWaypointIndex = index + 1;
285  edgeIdAfterFirstHeadingChange = bus->nodes.at(index + 1).edgeId;
286  firstHeadingChangeDegrees = headingDiff;
287  nextNodeUpdateSent = false;
288  sprintf_s(msg, 255, "Heading diff exceeded threshold! TargetHeading: %f, CurrentHeading: %f, diff: %f, distance: %f, iter: %u, startIndex: %u, endIndex: %u", heading, bus->HeadingTrueDegrees, headingDiff, distanceChecked, iterCounter, headingChangeStartWaypointIndex, headingChangeEndWaypointIndex);
289  this->logger->Log(msg, Logger::Debug);
290  break;
291  }
292 
293  distanceChecked += distanceIncludingThisLoop;
294 
295  if (distanceChecked >= cDistanceToCheckAhead) {
296  break;
297  }
298  iterCounter++;
299  }
300 
301  size_t direction = Direction::STRAIGHT;
302  if (firstHeadingChangeDegrees < -30.0f && firstHeadingChangeDegrees >= -60.0f) {
303  direction = Direction::BEAR_LEFT;
304  }
305  else if (firstHeadingChangeDegrees < -60.0f && firstHeadingChangeDegrees > -130.0f) {
306  direction = Direction::TURN_LEFT;
307  }
308  else if (firstHeadingChangeDegrees > 30.0f && firstHeadingChangeDegrees <= 60.0f) {
309  direction = Direction::BEAR_RIGHT;
310  }
311  else if (firstHeadingChangeDegrees > 60.0f && firstHeadingChangeDegrees < 130.0f) {
312  direction = Direction::TURN_RIGHT;
313  }
314  else if (firstHeadingChangeDegrees > 130.0f || firstHeadingChangeDegrees < -130.0f) {
315  direction = Direction::U_TURN;
316  }
317  firstHeadingChangeDirection = direction;
318 }
319 
320 float TurnByTurn::angleBetweenPositionsDeg(const D3DXVECTOR2& startingPos, const D3DXVECTOR2& targetPos) {
321  const D3DXVECTOR2 directionVector = targetPos - startingPos;
322  D3DXVECTOR2 normalizedDirVector;
323  D3DXVec2Normalize(&normalizedDirVector, &directionVector);
324  return vectorToDegrees(normalizedDirVector);
325 }
326 
327 float TurnByTurn::vectorToDegrees(const D3DXVECTOR2& vec) {
328  const float twoPi = 2.0f * static_cast<float>(M_PI);
329  float radians = atan2f(vec.y, vec.x);
330  if (radians < 0.0f) {
331  return fmodf(twoPi + radians + static_cast<float>(M_PI_2), twoPi) * (180.0f / static_cast<float>(M_PI));
332  }
333  else
334  {
335  return fmodf(radians + static_cast<float>(M_PI_2), twoPi) * (180.0f / static_cast<float>(M_PI));
336  }
337 }
338 
339 float TurnByTurn::distanceBetweenPositions(const D3DXVECTOR2& positionA, const D3DXVECTOR2& positionB) {
340  const D3DXVECTOR2 distanceVec = positionB - positionA;
341  return D3DXVec2Length(&distanceVec);
342 }
343 
344 float TurnByTurn::convertDistanceToMeters(const float dist) {
345  // Based on that coordinates 0.0 to 1.0 = 2000meter
346  return dist * 2000.0f;
347 }
348 
349 
350 float TurnByTurn::getHeadingChange(float pTargetHeading, float pCurrentHeading) {
351  float headingChange = pTargetHeading - pCurrentHeading;
352  return headingChange = customModulo(headingChange + 180.0f, 360.0f) - 180.0f;
353 }
354 
355 /*
356 * Implemented this function since the standard cmath modulo keeps the - sign which is not what we want
357 */
358 float TurnByTurn::customModulo(float a, float n) {
359  return a - floor(a / n) * n;
360 }
361 
363  // We don't check for cues if we are at, or past the heading change
364  const float maxWarnDist = 0.070f;
365  const float minWarnDist = 0.020f;
366  const float maxSpeed = 0.040f;
367  // linear mapping from 0.0 -> 0.040ms speed to 0.020 -> 0.070 distance
368  const float warnDist = ((bus->GroundSpeedKms / maxSpeed) * (maxWarnDist - minWarnDist)) + minWarnDist;
369  if (distanceUntilFirstHeadingChange <= 0.0f) {
370  return;
371  }
372  else if (distanceUntilFirstHeadingChange <= warnDist && !nextNodeUpdateSent) {
373  // We send a cue when we are at less then 40 meters away from heading change and have not sent the next node update yet
374  char msg[255];
375  sprintf_s(msg, 255, "Sending next node update to server Direction: %d, distanceMeters: %f, speed: %f", firstHeadingChangeDirection, distanceUntilFirstHeadingChange, bus->GroundSpeedKms);
376  this->logger->Log(msg, Logger::Debug);
378  nextNodeUpdateSent = true;
379  }
380  else if (distanceUntilFirstHeadingChange <= 0.05f && approachingNodeLastDistanceSent > 0.06f) {
381  // We send a cue when we are at less then 100 meters away from heading change
382  char msg[255];
383  sprintf_s(msg, 255, "Sending approaching next node update to server Direction: %d, distance: %f, edgeId: %d", firstHeadingChangeDirection, distanceUntilFirstHeadingChange, edgeIdAfterFirstHeadingChange);
384  this->logger->Log(msg, Logger::Debug);
385  sendUpdateToServer(edgeIdAfterFirstHeadingChange, 100.0f, firstHeadingChangeDirection, UpdateType::TYPE_APPROACHING_NEXT_NODE);
387  }
388 }
389 
391  char msg[255];
392  if (this->headingChangeStartWaypointIndex != -1 && this->headingChangeStartWaypointIndex < bus->nodes.size()) {
393  const float angleDegreesHeadingChangeStartWaypoint = this->angleBetweenPositionsDeg(this->vehiclePos, bus->nodes.at(headingChangeStartWaypointIndex).position);
394  const float headingChange = this->getHeadingChange(angleDegreesHeadingChangeStartWaypoint, bus->HeadingTrueDegrees);
395  if (headingChange > -90.0f && headingChange < 90.0f) {
396  // Heading change is still ahead of us
397  if (this->headingState != State::APPROACHING_HEADING_CHANGE) {
398  this->headingState = State::APPROACHING_HEADING_CHANGE;
399  sprintf_s(msg, 255, "Changing heading state to approach");
400  this->logger->Log(msg, Logger::Debug);
401  }
402 
404  this->checkForCue();
405  }
406  else {
407  if (this->headingChangeEndWaypointIndex != -1 && this->headingChangeEndWaypointIndex < bus->nodes.size()) {
408  const float angleDegreesHeadingChangeEndWaypoint = this->angleBetweenPositionsDeg(this->vehiclePos, bus->nodes.at(headingChangeEndWaypointIndex).position);
409  const float headingChange = this->getHeadingChange(angleDegreesHeadingChangeEndWaypoint, bus->HeadingTrueDegrees);
410  if (headingChange < -90.0f || headingChange > 90.0) {
411  // If the angle is smaller then -100 or bigger then 100, it's behind us, then we look ahead to next
412  if (this->headingState != State::COMPLETED_HEADING_CHANGE) {
413  sprintf_s(msg, 255, "Changing heading state to completed");
414  this->logger->Log(msg, Logger::Debug);
415  this->headingState = State::COMPLETED_HEADING_CHANGE;
416  this->LookAhead();
417  }
418  }
419  else {
420  if (this->headingState != State::IN_HEADING_CHANGE) {
421  sprintf_s(msg, 255, "Changing heading state to in heading change");
422  this->logger->Log(msg, Logger::Debug);
423  this->headingState = State::IN_HEADING_CHANGE;
424  }
425 
426  }
427  }
428 
429  }
430  }
431  else if (this->headingChangeEndWaypointIndex == -1) {
433  this->LookAhead();
434  }
435 }
size_t closestWaypointIndex
Definition: TurnByTurn.h:47
float getHeadingChange(float targetHeading, float currentHeading)
Definition: TurnByTurn.cpp:350
D3DXVECTOR2 vehiclePos
Definition: TurnByTurn.h:30
const float mapStartTcpU
Definition: TurnByTurn.h:23
float angleBetweenPositionsDeg(const D3DXVECTOR2 &vectorA, const D3DXVECTOR2 &vectorB)
Definition: TurnByTurn.cpp:320
int edgeIdAfterFirstHeadingChange
Definition: TurnByTurn.h:40
size_t nextWaypointIndex
Definition: TurnByTurn.h:49
size_t lineCount
Definition: TurnByTurn.h:50
bool nextNodeUpdateSent
Definition: TurnByTurn.h:41
float HeadingTrueDegrees
Definition: Bus.h:30
Definition: Logger.h:9
void ReleaseResources()
Definition: TurnByTurn.cpp:227
void SendToServer(void *pData, DWORD dwSize, bool bGuaranteed, PacketOrdering order=ORDERING_NONE) const
Definition: Networking.cpp:59
size_t firstHeadingChangeDirection
Definition: TurnByTurn.h:39
float customModulo(float a, float n)
Definition: TurnByTurn.cpp:358
int headingChangeEndWaypointIndex
Definition: TurnByTurn.h:44
float x
Definition: globals.h:243
void Draw(IDirect3DDevice9 *pd3dDevice)
Definition: TurnByTurn.cpp:121
float distanceTraveled
Definition: TurnByTurn.h:32
float distanceBetweenPositions(const D3DXVECTOR2 &vectorA, const D3DXVECTOR2 &vectorB)
Definition: TurnByTurn.cpp:339
float assayProgressU
Definition: Bus.h:387
float approachingNodeLastDistanceSent
Definition: TurnByTurn.h:42
void sendUpdateToServer(int pEdgeId, float pDistance, size_t pDirection, size_t pType)
Definition: TurnByTurn.cpp:232
const float cDirectionChangeThreshold
Definition: TurnByTurn.h:17
int headingState
Definition: TurnByTurn.h:45
Networking * networking
Definition: TurnByTurn.h:28
D3DXVECTOR2 lastVehiclePos
Definition: TurnByTurn.h:31
void updateHeadingState()
Definition: TurnByTurn.cpp:390
Bus * bus
Definition: TurnByTurn.h:26
Definition: Bus.h:16
const float cDistanceToCheckAhead
Definition: TurnByTurn.h:15
float mapMagnifier
Definition: TurnByTurn.h:33
D3DXVECTOR2 convertWorldPositionToMapPosition(const D3DXVECTOR2 &pos)
Definition: TurnByTurn.cpp:204
const float cReachedWaypointThreshold
Definition: TurnByTurn.h:11
void checkForCue()
Definition: TurnByTurn.cpp:362
void LookAhead()
Definition: TurnByTurn.cpp:247
size_t activeWaypointIndex
Definition: TurnByTurn.h:48
float MapScaleInnerRingKm
Definition: Bus.h:381
const float sectorSize
Definition: TurnByTurn.h:22
float convertDistanceToMeters(float dist)
Definition: TurnByTurn.cpp:344
float assayProgressV
Definition: Bus.h:387
void UpdateVB(IDirect3DDevice9 *pd3dDevice)
Definition: TurnByTurn.cpp:165
int headingChangeStartWaypointIndex
Definition: TurnByTurn.h:43
float vectorToDegrees(const D3DXVECTOR2 &vec)
Definition: TurnByTurn.cpp:327
TurnByTurn(Bus *pBus, Logger *pLoggger, Networking *pNetworking)
Definition: TurnByTurn.cpp:7
float firstHeadingChangeDegrees
Definition: TurnByTurn.h:38
void Log(const char *msg, Level level=Info, int errorCode=0)
Definition: Logger.cpp:11
LPDIRECT3DVERTEXBUFFER9 m_avRouteMap
Definition: TurnByTurn.h:29
#define D3DFVF_SCREEN
Definition: globals.h:109
bool turnByTurnDirty
Definition: Bus.h:398
void CreateVB(IDirect3DDevice9 *pd3dDevice)
Definition: TurnByTurn.cpp:151
float distanceUntilFirstHeadingChange
Definition: TurnByTurn.h:36
std::vector< Snode > nodes
Definition: Bus.h:397
float GroundSpeedKms
Definition: Bus.h:156
void Update(bool pIsGrndVehicle, float pElasedTime)
Definition: TurnByTurn.cpp:18
void AddToCallStack(const char *msg)
Definition: Logger.cpp:86
const float mapStartTcpV
Definition: TurnByTurn.h:24
VECTOR2SHORT tcp
Definition: Bus.h:236
Logger * logger
Definition: TurnByTurn.h:27
float elapsedCounter
Definition: TurnByTurn.h:34