Skip to content

Commit bd89004

Browse files
committed
- cell iterator cache added
1 parent 635ee57 commit bd89004

5 files changed

Lines changed: 134 additions & 68 deletions

File tree

DriverLevelTool/driver_routines/regions.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@ typedef void (*OnRegionFreed_t)(CBaseLevelRegion* region);
2121
struct SPOOL_CONTEXT
2222
{
2323
IVirtualStream* dataStream;
24-
2524
OUT_CITYLUMP_INFO* lumpInfo;
2625
};
2726

27+
struct CELL_ITERATOR_CACHE
28+
{
29+
ubyte computedValues[2048] = { 0 };
30+
};
31+
2832
class CBaseLevelRegion
2933
{
3034
friend class CBaseLevelMap;

DriverLevelTool/driver_routines/regions_d1.cpp

Lines changed: 65 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ bool CDriver1LevelMap::GetRoadInfo(ROUTE_DATA& outData, const VECTOR_NOPAD& posi
430430

431431
if (region && region->m_roadMap)
432432
{
433-
uint value = *(uint*)(loc_x + loc_z * double_region_size + region->m_roadMap);
433+
uint value = region->m_roadMap[loc_x + loc_z * double_region_size];
434434

435435
outData.height = *(short*)&value;
436436
outData.type = value >> 16 & 0x3ff;
@@ -615,17 +615,12 @@ int CDriver1LevelMap::FindSurface(const VECTOR_NOPAD& position, VECTOR_NOPAD& ou
615615
CELL_OBJECT* CDriver1LevelMap::GetFirstCop(CELL_ITERATOR_D1* iterator, const XZPAIR& cell) const
616616
{
617617
// lookup region
618-
const int region_x = cell.x / m_mapInfo.region_size;
619-
const int region_z = cell.z / m_mapInfo.region_size;
620-
621-
int regionIdx = region_x + region_z * m_regions_across;
622-
623-
CDriver1LevelRegion& region = m_regions[regionIdx];
618+
CDriver1LevelRegion* region = (CDriver1LevelRegion*)GetRegion(cell);
624619

625-
iterator->region = &region;
620+
iterator->region = region;
626621

627622
// don't do anything on empty or non-spooled regions
628-
if (!region.m_cells)
623+
if (!region->m_cells)
629624
return nullptr;
630625

631626
// get cell index on the region
@@ -635,17 +630,35 @@ CELL_OBJECT* CDriver1LevelMap::GetFirstCop(CELL_ITERATOR_D1* iterator, const XZP
635630
// FIXME: might be incorrect
636631
int cell_index = region_cell_x + region_cell_z * m_mapInfo.region_size;
637632

638-
ushort cell_ptr = region.m_cellPointers[cell_index];
633+
ushort cell_ptr = region->m_cellPointers[cell_index];
639634

640635
if (cell_ptr == 0xFFFF)
641636
return nullptr;
642637

643638
// get the packed cell data start and near cell
644-
CELL_DATA_D1& pcd = region.m_cells[cell_ptr];
639+
CELL_DATA_D1* pcd = &region->m_cells[cell_ptr];
645640

646-
CELL_OBJECT* pco = region.GetCellObject(pcd.num & 0x3fff);
641+
iterator->pcd = pcd;
642+
643+
CELL_OBJECT* pco = region->GetCellObject(pcd->num & 0x3fff);
644+
645+
if (iterator->cache)
646+
{
647+
CELL_ITERATOR_CACHE* cache = iterator->cache;
648+
ushort num = pcd->num;
649+
uint value = 1 << (num & 7) & 0xffff;
650+
651+
if ((cache->computedValues[(num & 0x3fff) >> 3] & value))
652+
{
653+
pco = GetNextCop(iterator);
654+
iterator->pco = pco;
655+
656+
return pco;
657+
}
658+
659+
cache->computedValues[(num & 0x3fff) >> 3] |= value;
660+
}
647661

648-
iterator->pcd = &pcd;
649662
iterator->pco = pco;
650663

651664
return pco;
@@ -656,22 +669,47 @@ CELL_OBJECT* CDriver1LevelMap::GetFirstCop(CELL_ITERATOR_D1* iterator, const XZP
656669
//-------------------------------------------------------------
657670
CELL_OBJECT* CDriver1LevelMap::GetNextCop(CELL_ITERATOR_D1* iterator) const
658671
{
659-
ushort cell_ptr = iterator->pcd->next_ptr;
672+
CELL_OBJECT* pco = nullptr;
660673

661-
if(cell_ptr != 0xFFFF)
674+
do
662675
{
663676
CDriver1LevelRegion* region = iterator->region;
664-
cell_ptr -= m_cell_slots_add[region->m_regionBarrelNumber];
665-
666-
// get the packed cell data start and near cell
667-
CELL_DATA_D1& cell = region->m_cells[cell_ptr];
668-
iterator->pcd = &cell;
669-
670-
CELL_OBJECT* pco = region->GetCellObject(cell.num & 0x3fff);
671-
iterator->pco = pco;
672-
673-
return pco;
674-
}
675677

676-
return nullptr;
678+
CELL_DATA_D1* pcd = iterator->pcd;
679+
680+
do
681+
{
682+
ushort cell_ptr = pcd->next_ptr;
683+
684+
if (cell_ptr == 0xffff)
685+
return nullptr;
686+
687+
// get the packed cell data start and near cell
688+
pcd = &region->m_cells[cell_ptr - m_cell_slots_add[region->m_regionBarrelNumber]];
689+
690+
iterator->pcd = pcd;
691+
692+
pco = region->GetCellObject(pcd->num & 0x3fff);
693+
iterator->pco = pco;
694+
} while (pco->pos.vx == -1 && pco->pos.vy == -1 && pco->pos.vz == -1 && pco->type == 0xffff);
695+
696+
if (!iterator->cache)
697+
break;
698+
699+
ushort num = pcd->num;
700+
701+
CELL_ITERATOR_CACHE* cache = iterator->cache;
702+
703+
uint value = 1 << (num & 7) & 0xffff;
704+
705+
if ((cache->computedValues[(num & 0x3fff) >> 3] & value) == 0)
706+
{
707+
cache->computedValues[(num & 0x3fff) >> 3] |= value;
708+
break;
709+
}
710+
} while (true);
711+
712+
713+
714+
return pco;
677715
}

DriverLevelTool/driver_routines/regions_d1.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class CDriver1LevelMap;
1212

1313
struct CELL_ITERATOR_D1
1414
{
15+
CELL_ITERATOR_CACHE* cache{ nullptr };
1516
CDriver1LevelRegion* region;
1617
CELL_DATA_D1* pcd;
1718
CELL_OBJECT* pco;

DriverLevelTool/driver_routines/regions_d2.cpp

Lines changed: 62 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,6 @@ int CDriver2LevelRegion::RoadInCell(VECTOR_NOPAD& position) const
206206
cellPos.x = position.vx - 512;
207207
cellPos.y = position.vz - 512;
208208

209-
sdPlane* planeData = (sdPlane*)((char*)buffer + buffer[1]);
210-
short* bspData = (short*)((char*)buffer + buffer[2]);
211-
sdNode* nodeData = (sdNode*)((char*)buffer + buffer[3]);
212-
213209
check = &buffer[(cellPos.x >> 10 & 63) +
214210
(cellPos.y >> 10 & 63) * 64 + 4];
215211

@@ -227,7 +223,7 @@ int CDriver2LevelRegion::RoadInCell(VECTOR_NOPAD& position) const
227223
moreLevels = (*check & 0x8000) != 0;
228224

229225
if (moreLevels)
230-
check = &bspData[(*check & 0x1fff) + 1];
226+
check = &m_bspData[(*check & 0x1fff) + 1];
231227

232228
do
233229
{
@@ -238,11 +234,11 @@ int CDriver2LevelRegion::RoadInCell(VECTOR_NOPAD& position) const
238234
// basically it determines surface bounds
239235
if (*check & 0x4000)
240236
{
241-
sdNode* search = &nodeData[*check & 0x1fff]; // 0x3fff in final
237+
sdNode* search = &m_nodeData[*check & 0x1fff]; // 0x3fff in final
242238

243239
while (search->node < 0)
244240
{
245-
plane = FindRoadInBSP(search + 1, planeData);
241+
plane = FindRoadInBSP(search + 1, m_planeData);
246242

247243
if (plane != nullptr)
248244
break;
@@ -255,7 +251,7 @@ int CDriver2LevelRegion::RoadInCell(VECTOR_NOPAD& position) const
255251
}
256252
else
257253
{
258-
plane = &planeData[*check];
254+
plane = &m_planeData[*check];
259255

260256
if (plane->surfaceType >= 32)
261257
break;
@@ -271,7 +267,7 @@ int CDriver2LevelRegion::RoadInCell(VECTOR_NOPAD& position) const
271267
}
272268
else
273269
{
274-
plane = &planeData[*check];
270+
plane = &m_planeData[*check];
275271
}
276272
}
277273
else
@@ -281,7 +277,7 @@ int CDriver2LevelRegion::RoadInCell(VECTOR_NOPAD& position) const
281277
moreLevels = (*check & 0x6000) == 0x2000;
282278

283279
if (moreLevels)
284-
check = &bspData[(*check & 0x1fff) + 1];
280+
check = &m_bspData[(*check & 0x1fff) + 1];
285281

286282
do
287283
{
@@ -290,14 +286,14 @@ int CDriver2LevelRegion::RoadInCell(VECTOR_NOPAD& position) const
290286

291287
if (*check & 0x4000)
292288
{
293-
plane = FindRoadInBSP(&nodeData[*check & 0x3fff], planeData);
289+
plane = FindRoadInBSP(&m_nodeData[*check & 0x3fff], m_planeData);
294290

295291
if (plane != nullptr)
296292
break;
297293
}
298294
else
299295
{
300-
plane = &planeData[*check];
296+
plane = &m_planeData[*check];
301297

302298
if (plane->surfaceType >= 32)
303299
break;
@@ -308,7 +304,7 @@ int CDriver2LevelRegion::RoadInCell(VECTOR_NOPAD& position) const
308304
}
309305
else if (!(*check & 0xE000))
310306
{
311-
plane = &planeData[*check];
307+
plane = &m_planeData[*check];
312308
}
313309
else
314310
plane = nullptr;
@@ -903,17 +899,12 @@ int CDriver2LevelMap::GetNumJunctions() const
903899
PACKED_CELL_OBJECT* CDriver2LevelMap::GetFirstPackedCop(CELL_ITERATOR_D2* iterator, const XZPAIR& cell) const
904900
{
905901
// lookup region
906-
const int region_x = cell.x / m_mapInfo.region_size;
907-
const int region_z = cell.z / m_mapInfo.region_size;
908-
909-
int regionIdx = region_x + region_z * m_regions_across;
910-
911-
CDriver2LevelRegion& region = m_regions[regionIdx];
902+
CDriver2LevelRegion* region = (CDriver2LevelRegion*)GetRegion(cell);
912903

913-
iterator->region = &region;
904+
iterator->region = region;
914905

915906
// don't do anything on empty or non-spooled regions
916-
if (!region.m_cells)
907+
if (!region->m_cells)
917908
return nullptr;
918909

919910
// get cell index on the region
@@ -923,7 +914,7 @@ PACKED_CELL_OBJECT* CDriver2LevelMap::GetFirstPackedCop(CELL_ITERATOR_D2* iterat
923914
// FIXME: might be incorrect
924915
int cell_index = region_cell_x + region_cell_z * m_mapInfo.region_size;
925916

926-
ushort cell_ptr = region.m_cellPointers[cell_index];
917+
ushort cell_ptr = region->m_cellPointers[cell_index];
927918

928919
if (cell_ptr == 0xFFFF)
929920
return nullptr;
@@ -933,7 +924,7 @@ PACKED_CELL_OBJECT* CDriver2LevelMap::GetFirstPackedCop(CELL_ITERATOR_D2* iterat
933924
iterator->nearCell.z = (cell.z - (m_mapInfo.cells_down / 2)) * m_mapInfo.cell_size;
934925

935926
// get the packed cell data start and near cell
936-
CELL_DATA* celld = &region.m_cells[cell_ptr];
927+
CELL_DATA* celld = &region->m_cells[cell_ptr];
937928

938929
/*
939930
Data looks like this:
@@ -954,13 +945,29 @@ PACKED_CELL_OBJECT* CDriver2LevelMap::GetFirstPackedCop(CELL_ITERATOR_D2* iterat
954945
celld++; // get to the start
955946
}
956947

957-
PACKED_CELL_OBJECT* ppco = region.GetPackedCellObject(celld->num & 0x3fff);
958-
iterator->co = region.GetCellObject(celld->num & 0x3fff);
948+
PACKED_CELL_OBJECT* ppco = region->GetPackedCellObject(celld->num & 0x3fff);
949+
iterator->co = region->GetCellObject(celld->num & 0x3fff);
959950

960951
iterator->pcd = celld;
961952

962953
if (ppco->value == 0xffff && (ppco->pos.vy & 1))
963954
ppco = GetNextPackedCop(iterator);
955+
else if (iterator->cache)
956+
{
957+
CELL_ITERATOR_CACHE* cache = iterator->cache;
958+
ushort num = celld->num;
959+
uint value = 1 << (num & 7) & 0xffff;
960+
961+
if ((cache->computedValues[(num & 0x3fff) >> 3] & value))
962+
{
963+
ppco = GetNextPackedCop(iterator);
964+
iterator->ppco = ppco;
965+
966+
return ppco;
967+
}
968+
969+
cache->computedValues[(num & 0x3fff) >> 3] |= value;
970+
}
964971

965972
iterator->ppco = ppco;
966973

@@ -972,31 +979,46 @@ PACKED_CELL_OBJECT* CDriver2LevelMap::GetFirstPackedCop(CELL_ITERATOR_D2* iterat
972979
//-------------------------------------------------------------
973980
PACKED_CELL_OBJECT* CDriver2LevelMap::GetNextPackedCop(CELL_ITERATOR_D2* iterator) const
974981
{
975-
ushort num;
976982
PACKED_CELL_OBJECT* ppco;
977983
CELL_OBJECT* co;
978984
CDriver2LevelRegion* reg = iterator->region;
985+
CELL_DATA* celld = iterator->pcd;
979986

980-
do {
981-
CELL_DATA* celld = iterator->pcd;
987+
do
988+
{
989+
do {
990+
if (celld->num & 0x8000) // end of the cell objects?
991+
return nullptr;
982992

983-
if (celld->num & 0x8000) // end of the cell objects?
984-
return nullptr;
993+
celld++;
985994

986-
celld++;
995+
if (celld->num & 0x4000) // if we got new list
996+
{
997+
iterator->listType = celld->num;
998+
celld++; // get to the start
999+
}
9871000

988-
if (celld->num & 0x4000) // if we got new list
989-
{
990-
iterator->listType = celld->num;
991-
celld++; // get to the start
992-
}
1001+
iterator->pcd = celld;
9931002

994-
iterator->pcd = celld;
1003+
ppco = reg->GetPackedCellObject(celld->num & 0x3fff);
1004+
co = reg->GetCellObject(celld->num & 0x3fff);
1005+
} while (ppco->value == 0xffff && (ppco->pos.vy & 1));
9951006

996-
ppco = reg->GetPackedCellObject(celld->num & 0x3fff);
997-
co = reg->GetCellObject(celld->num & 0x3fff);
1007+
if (!iterator->cache)
1008+
break;
9981009

999-
} while (ppco->value == 0xffff && (ppco->pos.vy & 1));
1010+
ushort num = celld->num;
1011+
1012+
CELL_ITERATOR_CACHE* cache = iterator->cache;
1013+
1014+
uint value = 1 << (num & 7) & 0xffff;
1015+
1016+
if ((cache->computedValues[(num & 0x3fff) >> 3] & value) == 0)
1017+
{
1018+
cache->computedValues[(num & 0x3fff) >> 3] |= value;
1019+
break;
1020+
}
1021+
} while (true);
10001022

10011023
iterator->ppco = ppco;
10021024
iterator->co = co;

DriverLevelTool/driver_routines/regions_d2.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class CDriver2LevelMap;
5959

6060
struct CELL_ITERATOR_D2
6161
{
62+
CELL_ITERATOR_CACHE* cache{ nullptr };
6263
CDriver2LevelRegion* region;
6364
CELL_DATA* pcd;
6465
PACKED_CELL_OBJECT* ppco;

0 commit comments

Comments
 (0)