Skip to content

Commit ee6cb84

Browse files
committed
- added "Display roads" feature
1 parent f4244a5 commit ee6cb84

5 files changed

Lines changed: 380 additions & 20 deletions

File tree

DriverLevelTool/driver_routines/d2_types.h

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -336,31 +336,20 @@ struct sdHeightmapHeader
336336

337337
struct DRIVER2_CURVE
338338
{
339-
int Midx;
340-
int Midz;
341-
short start;
342-
short end;
339+
int Midx, Midz;
340+
short start, end;
343341
short ConnectIdx[4];
344-
short gradient;
345-
short height;
346-
char NumLanes;
347-
char LaneDirs;
348-
char inside;
349-
char AILanes;
342+
short gradient, height;
343+
int8 NumLanes, LaneDirs, inside, AILanes;
350344
};
351345

352346
struct DRIVER2_STRAIGHT
353347
{
354-
int Midx;
355-
int Midz;
348+
int Midx, Midz;
356349
ushort length;
357-
short bing;
358-
short angle;
350+
short bing, angle;
359351
short ConnectIdx[4];
360-
char NumLanes;
361-
char LaneDirs;
362-
char AILanes;
363-
char packing;
352+
int8 NumLanes, LaneDirs, AILanes, packing;
364353
};
365354

366355
struct OLD_DRIVER2_JUNCTION

DriverLevelTool/driver_routines/regions_d2.cpp

Lines changed: 254 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
#include <malloc.h>
1212
#include <string.h>
1313

14+
#define IS_STRAIGHT_SURFACE(surfid) (((surfid) > -1) && ((surfid) & 0xFFFFE000) == 0 && ((surfid) & 0x1FFF) < m_numStraights)
15+
#define IS_CURVED_SURFACE(surfid) (((surfid) > -1) && ((surfid) & 0xFFFFE000) == 0x4000 && ((surfid) & 0x1FFF) < m_numCurves)
16+
#define IS_JUNCTION_SURFACE(surfid) (((surfid) > -1) && ((surfid) & 0xFFFFE000) == 0x2000 && ((surfid) & 0x1FFF) < m_numJunctions)
17+
1418
sdPlane g_defaultPlane = { 0, 0, 0, 0, 2048 };
1519
sdPlane g_seaPlane = { 9, 0, 16384, 0, 2048 };
1620

@@ -71,6 +75,29 @@ short* SdGetBSP(sdNode* node, XZPAIR* pos)
7175
return (short*)node;
7276
}
7377

78+
sdPlane* FindRoadInBSP(sdNode* node, sdPlane* base)
79+
{
80+
sdPlane* plane;
81+
82+
while (true)
83+
{
84+
if (*(int*)node > -1)
85+
{
86+
base += *(int*)node;
87+
return (base->surfaceType < 32) ? nullptr : base;
88+
}
89+
90+
plane = FindRoadInBSP(node + 1, base);
91+
92+
if (plane != nullptr)
93+
break;
94+
95+
node += node->offset;
96+
}
97+
98+
return plane;
99+
}
100+
74101
// walk the heightmap to get a cPosition
75102
sdPlane* CDriver2LevelRegion::SdGetCell(const VECTOR_NOPAD& cPosition, int& sdLevel, sdBspCallback bspWalker) const
76103
{
@@ -162,6 +189,139 @@ sdPlane* CDriver2LevelRegion::SdGetCell(const VECTOR_NOPAD& cPosition, int& sdLe
162189
return plane;
163190
}
164191

192+
// walk heightmap for nearest road
193+
int CDriver2LevelRegion::RoadInCell(VECTOR_NOPAD& position) const
194+
{
195+
int moreLevels;
196+
sdPlane* plane;
197+
short* check;
198+
short* buffer;
199+
200+
XYPAIR cellPos;
201+
202+
cellPos.x = position.vx - 512;
203+
cellPos.y = position.vz - 512;
204+
205+
sdPlane* planeData = (sdPlane*)((char*)buffer + buffer[1]);
206+
short* bspData = (short*)((char*)buffer + buffer[2]);
207+
sdNode* nodeData = (sdNode*)((char*)buffer + buffer[3]);
208+
209+
check = &buffer[(cellPos.x >> 10 & 63) +
210+
(cellPos.y >> 10 & 63) * 64 + 4];
211+
212+
if (*check == -1)
213+
return -1;
214+
215+
if (m_owner->m_format == LEV_FORMAT_DRIVER2_ALPHA16)
216+
{
217+
// FIXME: check if this is redundant!
218+
if (*check & 0xE000)
219+
{
220+
if (*check & 0x2000)
221+
{
222+
// check surface has overlapping planes flag (aka multiple levels)
223+
moreLevels = (*check & 0x8000) != 0;
224+
225+
if (moreLevels)
226+
check = &bspData[(*check & 0x1fff) + 1];
227+
228+
do
229+
{
230+
if (moreLevels && check[-1] == -0x8000)
231+
moreLevels = 0;
232+
233+
// check if it's has BSP properties
234+
// basically it determines surface bounds
235+
if (*check & 0x4000)
236+
{
237+
sdNode* search = &nodeData[*check & 0x1fff]; // 0x3fff in final
238+
239+
while (search->node < 0)
240+
{
241+
plane = FindRoadInBSP(search + 1, planeData);
242+
243+
if (plane != nullptr)
244+
break;
245+
246+
search += search->offset;
247+
}
248+
249+
if (plane != nullptr)
250+
break;
251+
}
252+
else
253+
{
254+
plane = &planeData[*check];
255+
256+
if (plane->surfaceType >= 32)
257+
break;
258+
}
259+
260+
check += 2;
261+
} while (true);
262+
}
263+
else
264+
{
265+
plane = nullptr;
266+
}
267+
}
268+
else
269+
{
270+
plane = &planeData[*check];
271+
}
272+
}
273+
else
274+
{
275+
if (*check & 0x8000)
276+
{
277+
moreLevels = (*check & 0x6000) == 0x2000;
278+
279+
if (moreLevels)
280+
check = &bspData[(*check & 0x1fff) + 1];
281+
282+
do
283+
{
284+
if (moreLevels && check[-1] == 0x8000)
285+
moreLevels = 0;
286+
287+
if (*check & 0x4000)
288+
{
289+
plane = FindRoadInBSP(&nodeData[*check & 0x3fff], planeData);
290+
291+
if (plane != nullptr)
292+
break;
293+
}
294+
else
295+
{
296+
plane = &planeData[*check];
297+
298+
if (plane->surfaceType >= 32)
299+
break;
300+
}
301+
302+
check += 2;
303+
} while (true);
304+
}
305+
else if (!(*check & 0xE000))
306+
{
307+
plane = &planeData[*check];
308+
}
309+
else
310+
plane = nullptr;
311+
}
312+
313+
if (plane == nullptr)
314+
return -1;
315+
316+
if (plane->surfaceType >= 32)
317+
{
318+
position.vy = SdHeightOnPlane(position, plane, ((CDriver2LevelMap*)m_owner)->m_curves) + 256;
319+
return plane->surfaceType - 32;
320+
}
321+
322+
return -1;
323+
}
324+
165325
void CDriver2LevelRegion::FreeAll()
166326
{
167327
if (!m_loaded)
@@ -289,7 +449,7 @@ void CDriver2LevelRegion::ReadHeightmapData(const SPOOL_CONTEXT& ctx)
289449
}
290450
else
291451
{
292-
MsgError("Incorrect format or read error\n");
452+
MsgError("Incorrect road map format or read error\n");
293453
}
294454
}
295455

@@ -528,6 +688,99 @@ int CDriver2LevelMap::MapHeight(const VECTOR_NOPAD& position) const
528688
return 0;
529689
}
530690

691+
int CDriver2LevelMap::GetRoadIndex(VECTOR_NOPAD& position) const
692+
{
693+
VECTOR_NOPAD cellPos;
694+
XZPAIR cell;
695+
int level = 0;
696+
697+
cellPos.vx = position.vx - 512; // FIXME: is that a quarter of a cell?
698+
cellPos.vy = position.vy;
699+
cellPos.vz = position.vz - 512;
700+
701+
WorldPositionToCellXZ(cell, cellPos);
702+
CDriver2LevelRegion* region = (CDriver2LevelRegion*)GetRegion(cell);
703+
704+
return region->RoadInCell(position);
705+
}
706+
707+
// [A] custom function for working with roads in very optimized way
708+
bool CDriver2LevelMap::GetSurfaceRoadInfo(DRIVER2_ROAD_INFO& outRoadInfo, int surfId) const
709+
{
710+
DRIVER2_CURVE* curve;
711+
DRIVER2_STRAIGHT* straight;
712+
DRIVER2_JUNCTION* junction;
713+
714+
outRoadInfo.surfId = surfId;
715+
716+
if (IS_CURVED_SURFACE(surfId))
717+
{
718+
outRoadInfo.curve = curve = GetCurve(surfId);
719+
outRoadInfo.ConnectIdx = &curve->ConnectIdx;
720+
outRoadInfo.NumLanes = curve->NumLanes;
721+
outRoadInfo.LaneDirs = curve->LaneDirs;
722+
outRoadInfo.AILanes = curve->AILanes;
723+
return true;
724+
}
725+
else if (IS_STRAIGHT_SURFACE(surfId))
726+
{
727+
outRoadInfo.straight = straight = GetStraight(surfId);
728+
outRoadInfo.ConnectIdx = &straight->ConnectIdx;
729+
outRoadInfo.NumLanes = straight->NumLanes;
730+
outRoadInfo.LaneDirs = straight->LaneDirs;
731+
outRoadInfo.AILanes = straight->AILanes;
732+
return true;
733+
}
734+
else if (IS_JUNCTION_SURFACE(surfId))
735+
{
736+
outRoadInfo.junction = junction = GetJunction(surfId);
737+
outRoadInfo.ConnectIdx = &junction->ExitIdx;
738+
outRoadInfo.flags = junction->flags;
739+
return true;
740+
}
741+
742+
return false;
743+
}
744+
745+
DRIVER2_STRAIGHT* CDriver2LevelMap::GetStraight(int index) const
746+
{
747+
if(IS_STRAIGHT_SURFACE(index))
748+
return &m_straights[index & 0x1fff];
749+
750+
return nullptr;
751+
}
752+
753+
DRIVER2_CURVE* CDriver2LevelMap::GetCurve(int index) const
754+
{
755+
if (IS_CURVED_SURFACE(index))
756+
return &m_curves[index & 0x1fff];
757+
758+
return nullptr;
759+
}
760+
761+
DRIVER2_JUNCTION* CDriver2LevelMap::GetJunction(int index) const
762+
{
763+
if (IS_JUNCTION_SURFACE(index))
764+
return &m_junctions[index & 0x1fff];
765+
766+
return nullptr;
767+
}
768+
769+
int CDriver2LevelMap::GetNumStraights() const
770+
{
771+
return m_numStraights;
772+
}
773+
774+
int CDriver2LevelMap::GetNumCurves() const
775+
{
776+
return m_numCurves;
777+
}
778+
779+
int CDriver2LevelMap::GetNumJunctions() const
780+
{
781+
return m_numJunctions;
782+
}
783+
531784
//-------------------------------------------------------------
532785
// returns first cell object of cell
533786
//-------------------------------------------------------------

0 commit comments

Comments
 (0)