mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2025-01-10 07:42:56 +08:00
Replaced world grid with quadtrees, improved loading speed of cutscenes
This commit is contained in:
parent
d59663d87e
commit
a5259c17fe
@ -625,6 +625,22 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void GetVisibleChildren(ref Vector3 p, List<MapDataStoreNode> items)
|
||||||
|
{
|
||||||
|
if (Children == null) return;
|
||||||
|
for (int i = 0; i < Children.Length; i++)
|
||||||
|
{
|
||||||
|
var c = Children[i];
|
||||||
|
if (c == null) continue;
|
||||||
|
var cmin = c.streamingExtentsMin;
|
||||||
|
var cmax = c.streamingExtentsMax;
|
||||||
|
if ((p.X >= cmin.X) && (p.X <= cmax.X) && (p.Y >= cmin.Y) && (p.Y <= cmax.Y))
|
||||||
|
{
|
||||||
|
items.Add(c);
|
||||||
|
c.GetVisibleChildren(ref p, items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
@ -101,7 +101,7 @@ namespace CodeWalker.World
|
|||||||
Yld = gfc.GetFileUncached<YldFile>(clothFile);
|
Yld = gfc.GetFileUncached<YldFile>(clothFile);
|
||||||
while ((Yld != null) && (!Yld.Loaded))
|
while ((Yld != null) && (!Yld.Loaded))
|
||||||
{
|
{
|
||||||
Thread.Sleep(20);//kinda hacky
|
Thread.Sleep(1);//kinda hacky
|
||||||
gfc.TryLoadEnqueue(Yld);
|
gfc.TryLoadEnqueue(Yld);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,22 +110,22 @@ namespace CodeWalker.World
|
|||||||
|
|
||||||
while ((Ydd != null) && (!Ydd.Loaded))
|
while ((Ydd != null) && (!Ydd.Loaded))
|
||||||
{
|
{
|
||||||
Thread.Sleep(20);//kinda hacky
|
Thread.Sleep(1);//kinda hacky
|
||||||
Ydd = gfc.GetYdd(pedhash);
|
Ydd = gfc.GetYdd(pedhash);
|
||||||
}
|
}
|
||||||
while ((Ytd != null) && (!Ytd.Loaded))
|
while ((Ytd != null) && (!Ytd.Loaded))
|
||||||
{
|
{
|
||||||
Thread.Sleep(20);//kinda hacky
|
Thread.Sleep(1);//kinda hacky
|
||||||
Ytd = gfc.GetYtd(pedhash);
|
Ytd = gfc.GetYtd(pedhash);
|
||||||
}
|
}
|
||||||
while ((Ycd != null) && (!Ycd.Loaded))
|
while ((Ycd != null) && (!Ycd.Loaded))
|
||||||
{
|
{
|
||||||
Thread.Sleep(20);//kinda hacky
|
Thread.Sleep(1);//kinda hacky
|
||||||
Ycd = gfc.GetYcd(ycdhash);
|
Ycd = gfc.GetYcd(ycdhash);
|
||||||
}
|
}
|
||||||
while ((Yft != null) && (!Yft.Loaded))
|
while ((Yft != null) && (!Yft.Loaded))
|
||||||
{
|
{
|
||||||
Thread.Sleep(20);//kinda hacky
|
Thread.Sleep(1);//kinda hacky
|
||||||
Yft = gfc.GetYft(pedhash);
|
Yft = gfc.GetYft(pedhash);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ namespace CodeWalker.World
|
|||||||
var ydd = gfc.GetFileUncached<YddFile>(file);
|
var ydd = gfc.GetFileUncached<YddFile>(file);
|
||||||
while ((ydd != null) && (!ydd.Loaded))
|
while ((ydd != null) && (!ydd.Loaded))
|
||||||
{
|
{
|
||||||
Thread.Sleep(20);//kinda hacky
|
Thread.Sleep(1);//kinda hacky
|
||||||
gfc.TryLoadEnqueue(ydd);
|
gfc.TryLoadEnqueue(ydd);
|
||||||
}
|
}
|
||||||
if (ydd?.Drawables?.Length > 0)
|
if (ydd?.Drawables?.Length > 0)
|
||||||
@ -193,7 +193,7 @@ namespace CodeWalker.World
|
|||||||
var ytd = gfc.GetFileUncached<YtdFile>(file);
|
var ytd = gfc.GetFileUncached<YtdFile>(file);
|
||||||
while ((ytd != null) && (!ytd.Loaded))
|
while ((ytd != null) && (!ytd.Loaded))
|
||||||
{
|
{
|
||||||
Thread.Sleep(20);//kinda hacky
|
Thread.Sleep(1);//kinda hacky
|
||||||
gfc.TryLoadEnqueue(ytd);
|
gfc.TryLoadEnqueue(ytd);
|
||||||
}
|
}
|
||||||
if (ytd?.TextureDict?.Textures?.data_items.Length > 0)
|
if (ytd?.TextureDict?.Textures?.data_items.Length > 0)
|
||||||
@ -216,7 +216,7 @@ namespace CodeWalker.World
|
|||||||
var yld = gfc.GetFileUncached<YldFile>(file);
|
var yld = gfc.GetFileUncached<YldFile>(file);
|
||||||
while ((yld != null) && (!yld.Loaded))
|
while ((yld != null) && (!yld.Loaded))
|
||||||
{
|
{
|
||||||
Thread.Sleep(20);//kinda hacky
|
Thread.Sleep(1);//kinda hacky
|
||||||
gfc.TryLoadEnqueue(yld);
|
gfc.TryLoadEnqueue(yld);
|
||||||
}
|
}
|
||||||
if (yld?.ClothDictionary?.Clothes?.data_items?.Length > 0)
|
if (yld?.ClothDictionary?.Clothes?.data_items?.Length > 0)
|
||||||
|
@ -18,8 +18,12 @@ namespace CodeWalker.World
|
|||||||
private GameFileCache GameFileCache = null;
|
private GameFileCache GameFileCache = null;
|
||||||
|
|
||||||
|
|
||||||
public SpaceGrid Grid;
|
|
||||||
private Dictionary<SpaceBoundsKey, BoundsStoreItem> visibleBoundsDict = new Dictionary<SpaceBoundsKey, BoundsStoreItem>();
|
|
||||||
|
public SpaceMapDataStore MapDataStore;
|
||||||
|
public SpaceBoundsStore BoundsStore;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private Dictionary<MetaHash, MetaHash> interiorLookup = new Dictionary<MetaHash, MetaHash>();
|
private Dictionary<MetaHash, MetaHash> interiorLookup = new Dictionary<MetaHash, MetaHash>();
|
||||||
private Dictionary<MetaHash, YmfInterior> interiorManifest = new Dictionary<MetaHash, YmfInterior>();
|
private Dictionary<MetaHash, YmfInterior> interiorManifest = new Dictionary<MetaHash, YmfInterior>();
|
||||||
@ -58,9 +62,14 @@ namespace CodeWalker.World
|
|||||||
InitCacheData();
|
InitCacheData();
|
||||||
|
|
||||||
|
|
||||||
updateStatus("Building world grid...");
|
updateStatus("Building map data store...");
|
||||||
|
|
||||||
InitMapGrid();
|
InitMapDataStore();
|
||||||
|
|
||||||
|
|
||||||
|
updateStatus("Building bounds store...");
|
||||||
|
|
||||||
|
InitBoundsStore();
|
||||||
|
|
||||||
|
|
||||||
updateStatus("Loading paths...");
|
updateStatus("Loading paths...");
|
||||||
@ -313,101 +322,46 @@ namespace CodeWalker.World
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitMapGrid()
|
private void InitMapDataStore()
|
||||||
{
|
{
|
||||||
|
|
||||||
Grid = new SpaceGrid();
|
MapDataStore = new SpaceMapDataStore();
|
||||||
|
|
||||||
//List<MapDataStoreNode> containers = new List<MapDataStoreNode>();
|
List<MapDataStoreNode> rootnodes = new List<MapDataStoreNode>();
|
||||||
//List<MapDataStoreNode> critnodes = new List<MapDataStoreNode>();
|
List<MapDataStoreNode> lodnodes = new List<MapDataStoreNode>();
|
||||||
//List<MapDataStoreNode> hdnodes = new List<MapDataStoreNode>();
|
List<MapDataStoreNode> orphnodes = new List<MapDataStoreNode>();
|
||||||
//List<MapDataStoreNode> lodnodes = new List<MapDataStoreNode>();
|
|
||||||
//List<MapDataStoreNode> strmnodes = new List<MapDataStoreNode>();
|
|
||||||
//List<MapDataStoreNode> intnodes = new List<MapDataStoreNode>();
|
|
||||||
//List<MapDataStoreNode> occlnodes = new List<MapDataStoreNode>();
|
|
||||||
//List<MapDataStoreNode> grassnodes = new List<MapDataStoreNode>();
|
|
||||||
//List<MapDataStoreNode> lodlightsnodes = new List<MapDataStoreNode>();
|
|
||||||
|
|
||||||
foreach (var node in nodedict.Values)
|
foreach (var node in nodedict.Values)
|
||||||
{
|
{
|
||||||
bool addtogrid = false;
|
if (node.ParentName == 0)
|
||||||
byte t = (byte)(node.ContentFlags & 0xFF);
|
|
||||||
switch (node.ContentFlags)// t)
|
|
||||||
{
|
{
|
||||||
case 0: //for mods/unused stuff? could be interesting.
|
rootnodes.Add(node);
|
||||||
addtogrid = true;
|
if (((node.ContentFlags & 2) > 0) || ((node.ContentFlags & 4) > 0) || ((node.ContentFlags & 16) > 0))
|
||||||
break;
|
|
||||||
case 16://"container" node?
|
|
||||||
//containers.Add(node);
|
|
||||||
break;
|
|
||||||
case 18:
|
|
||||||
case 82: //HD nodes
|
|
||||||
//hdnodes.Add(node);
|
|
||||||
addtogrid = true;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
case 65: //Stream nodes
|
|
||||||
//strmnodes.Add(node);
|
|
||||||
addtogrid = true;
|
|
||||||
break;
|
|
||||||
case 513:
|
|
||||||
case 577: //critical nodes
|
|
||||||
//critnodes.Add(node);
|
|
||||||
addtogrid = true;
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
case 73: //interior nodes
|
|
||||||
//intnodes.Add(node);
|
|
||||||
addtogrid = true;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
case 4:
|
|
||||||
case 20:
|
|
||||||
case 66:
|
|
||||||
case 514: //LOD nodes
|
|
||||||
//lodnodes.Add(node);
|
|
||||||
addtogrid = true;
|
|
||||||
break;
|
|
||||||
case 128:
|
|
||||||
case 256: //LOD lights nodes
|
|
||||||
//lodlightsnodes.Add(node);
|
|
||||||
addtogrid = true;
|
|
||||||
break;
|
|
||||||
case 32: //occlusion nodes
|
|
||||||
//occlnodes.Add(node);
|
|
||||||
addtogrid = true;
|
|
||||||
break;
|
|
||||||
case 1088: //grass nodes
|
|
||||||
//grassnodes.Add(node);
|
|
||||||
addtogrid = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
addtogrid = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (addtogrid)
|
|
||||||
{
|
{
|
||||||
Grid.AddNode(node);
|
lodnodes.Add(node);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
foreach (var item in boundsdict.Values)
|
|
||||||
{
|
{
|
||||||
Grid.AddBounds(item);
|
orphnodes.Add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var intprx in interiorProxies.Values)
|
|
||||||
|
MapDataStore.Init(rootnodes);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitBoundsStore()
|
||||||
{
|
{
|
||||||
Grid.AddInterior(intprx);
|
|
||||||
}
|
BoundsStore = new SpaceBoundsStore();
|
||||||
|
|
||||||
|
BoundsStore.Init(boundsdict.Values.ToList());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void InitNodeGrid()
|
private void InitNodeGrid()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -786,7 +740,7 @@ namespace CodeWalker.World
|
|||||||
public void Update(float elapsed)
|
public void Update(float elapsed)
|
||||||
{
|
{
|
||||||
if (!Inited) return;
|
if (!Inited) return;
|
||||||
if (Grid == null) return;
|
if (BoundsStore == null) return;
|
||||||
|
|
||||||
if (elapsed > 0.1f) elapsed = 0.1f;
|
if (elapsed > 0.1f) elapsed = 0.1f;
|
||||||
|
|
||||||
@ -1044,19 +998,12 @@ namespace CodeWalker.World
|
|||||||
public void GetVisibleYmaps(Camera cam, int hour, MetaHash weather, Dictionary<MetaHash, YmapFile> ymaps)
|
public void GetVisibleYmaps(Camera cam, int hour, MetaHash weather, Dictionary<MetaHash, YmapFile> ymaps)
|
||||||
{
|
{
|
||||||
if (!Inited) return;
|
if (!Inited) return;
|
||||||
if (Grid == null) return;
|
if (MapDataStore == null) return;
|
||||||
|
var items = MapDataStore.GetItems(ref cam.Position);
|
||||||
|
for (int i = 0; i < items.Count; i++)
|
||||||
ymaps.Clear();
|
|
||||||
|
|
||||||
//var pos = Grid.GetCellPos(cam.Position);
|
|
||||||
var cell = Grid.GetCell(cam.Position);
|
|
||||||
if (cell.NodesList != null)
|
|
||||||
{
|
{
|
||||||
for (int n = 0; n < cell.NodesList.Count; n++)
|
var item = items[i];
|
||||||
{
|
var hash = item.Name;
|
||||||
var node = cell.NodesList[n];
|
|
||||||
var hash = node.Name;
|
|
||||||
if (!ymaps.ContainsKey(hash))
|
if (!ymaps.ContainsKey(hash))
|
||||||
{
|
{
|
||||||
var ymap = (hash > 0) ? GameFileCache.GetYmap(hash) : null;
|
var ymap = (hash > 0) ? GameFileCache.GetYmap(hash) : null;
|
||||||
@ -1073,86 +1020,17 @@ namespace CodeWalker.World
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//int gridrange = 0;
|
|
||||||
|
|
||||||
//var pos = Grid.GetCellPos(cam.Position);
|
|
||||||
//int minx = Math.Min(Math.Max(pos.X - gridrange, 0), SpaceGrid.LastCell);
|
|
||||||
//int maxx = Math.Min(Math.Max(pos.X + gridrange, 0), SpaceGrid.LastCell);
|
|
||||||
//int miny = Math.Min(Math.Max(pos.Y - gridrange, 0), SpaceGrid.LastCell);
|
|
||||||
//int maxy = Math.Min(Math.Max(pos.Y + gridrange, 0), SpaceGrid.LastCell);
|
|
||||||
|
|
||||||
//for (int x = minx; x <= maxx; x++)
|
|
||||||
//{
|
|
||||||
// for (int y = miny; y <= maxy; y++)
|
|
||||||
// {
|
|
||||||
// var cell = Grid.GetCell(new Vector2I(x, y));
|
|
||||||
// if (cell.NodesList != null)
|
|
||||||
// {
|
|
||||||
// for (int n = 0; n < cell.NodesList.Count; n++)
|
|
||||||
// {
|
|
||||||
// var node = cell.NodesList[n];
|
|
||||||
// var hash = node.Name;
|
|
||||||
// if (!ymaps.ContainsKey(hash))
|
|
||||||
// {
|
|
||||||
// var ymap = (hash > 0) ? GameFileCache.GetYmap(hash) : null;
|
|
||||||
// if ((ymap != null) && (ymap.Loaded))
|
|
||||||
// {
|
|
||||||
// ymaps[hash] = ymap;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void GetVisibleBounds(Camera cam, int gridrange, bool[] layers, List<BoundsStoreItem> boundslist)
|
public void GetVisibleBounds(Camera cam, int gridrange, bool[] layers, List<BoundsStoreItem> boundslist)
|
||||||
{
|
{
|
||||||
if (!Inited) return;
|
if (!Inited) return;
|
||||||
if (Grid == null) return;
|
|
||||||
|
|
||||||
visibleBoundsDict.Clear();
|
|
||||||
|
|
||||||
var pos = Grid.GetCellPos(cam.Position);
|
|
||||||
int minx = Math.Min(Math.Max(pos.X - gridrange, 0), SpaceGrid.LastCell);
|
|
||||||
int maxx = Math.Min(Math.Max(pos.X + gridrange, 0), SpaceGrid.LastCell);
|
|
||||||
int miny = Math.Min(Math.Max(pos.Y - gridrange, 0), SpaceGrid.LastCell);
|
|
||||||
int maxy = Math.Min(Math.Max(pos.Y + gridrange, 0), SpaceGrid.LastCell);
|
|
||||||
|
|
||||||
for (int x = minx; x <= maxx; x++)
|
|
||||||
{
|
|
||||||
for (int y = miny; y <= maxy; y++)
|
|
||||||
{
|
|
||||||
var cell = Grid.GetCell(new Vector2I(x, y));
|
|
||||||
if (cell.BoundsList != null)
|
|
||||||
{
|
|
||||||
foreach (var item in cell.BoundsList)
|
|
||||||
{
|
|
||||||
uint l = item.Layer;
|
|
||||||
if (l < 3)
|
|
||||||
{
|
|
||||||
if (!layers[l]) continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ }
|
|
||||||
|
|
||||||
visibleBoundsDict[new SpaceBoundsKey(item.Name, item.Min)] = item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//var cell = grid.GetCell(cam.Position);
|
|
||||||
//if (cell.BoundsList != null)
|
|
||||||
//{
|
|
||||||
// boundslist.AddRange(cell.BoundsList);
|
|
||||||
//}
|
|
||||||
|
|
||||||
boundslist.AddRange(visibleBoundsDict.Values);
|
|
||||||
|
|
||||||
|
if (BoundsStore == null) return;
|
||||||
|
float dist = 50.0f * gridrange;
|
||||||
|
var pos = cam.Position;
|
||||||
|
var min = pos - dist;
|
||||||
|
var max = pos + dist;
|
||||||
|
var items = BoundsStore.GetItems(ref min, ref max);
|
||||||
|
boundslist.AddRange(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1174,7 +1052,7 @@ namespace CodeWalker.World
|
|||||||
public void GetVisibleYnvs(Camera cam, int gridrange, List<YnvFile> ynvs)
|
public void GetVisibleYnvs(Camera cam, int gridrange, List<YnvFile> ynvs)
|
||||||
{
|
{
|
||||||
if (!Inited) return;
|
if (!Inited) return;
|
||||||
if (Grid == null) return;
|
if (NavGrid == null) return;
|
||||||
|
|
||||||
|
|
||||||
ynvs.Clear();
|
ynvs.Clear();
|
||||||
@ -1213,18 +1091,11 @@ namespace CodeWalker.World
|
|||||||
int polytestcount = 0;
|
int polytestcount = 0;
|
||||||
int nodetestcount = 0;
|
int nodetestcount = 0;
|
||||||
bool testcomplete = true;
|
bool testcomplete = true;
|
||||||
var cellpos = Grid.GetCellPos(ray.Position);
|
|
||||||
var cell = Grid.GetCell(cellpos);
|
|
||||||
var startz = ray.Position.Z;
|
|
||||||
var maxcells = 5;
|
|
||||||
var cellcount = 0;
|
|
||||||
var box = new BoundingBox();
|
var box = new BoundingBox();
|
||||||
var tsph = new BoundingSphere();
|
var tsph = new BoundingSphere();
|
||||||
var rayt = new Ray();
|
var rayt = new Ray();
|
||||||
var rp = ray.Position;
|
var rp = ray.Position;
|
||||||
var rd = ray.Direction;
|
var rd = ray.Direction;
|
||||||
float dirx = (rd.X < 0) ? -1 : (rd.X > 0) ? 1 : 0;
|
|
||||||
float diry = (rd.Y < 0) ? -1 : (rd.Y > 0) ? 1 : 0;
|
|
||||||
var boxhitdist = float.MaxValue;
|
var boxhitdist = float.MaxValue;
|
||||||
var itemhitdist = float.MaxValue;
|
var itemhitdist = float.MaxValue;
|
||||||
Vector3 p1, p2, p3, p4, a1, a2, a3;
|
Vector3 p1, p2, p3, p4, a1, a2, a3;
|
||||||
@ -1235,11 +1106,11 @@ namespace CodeWalker.World
|
|||||||
BoundMaterial_s hitmat = new BoundMaterial_s();
|
BoundMaterial_s hitmat = new BoundMaterial_s();
|
||||||
Vector3 hitnorm = Vector3.Zero;
|
Vector3 hitnorm = Vector3.Zero;
|
||||||
Vector3 hitpos = Vector3.Zero;
|
Vector3 hitpos = Vector3.Zero;
|
||||||
while (cell != null)
|
|
||||||
{
|
if (BoundsStore == null) return res;
|
||||||
if (cell.BoundsList != null)
|
var boundslist = BoundsStore.GetItems(ref ray);
|
||||||
{
|
|
||||||
foreach (var bound in cell.BoundsList)
|
foreach (var bound in boundslist)
|
||||||
{
|
{
|
||||||
uint l = bound.Layer;
|
uint l = bound.Layer;
|
||||||
if ((layers != null) && (l < 3))
|
if ((layers != null) && (l < 3))
|
||||||
@ -1447,39 +1318,6 @@ namespace CodeWalker.World
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//walk the line to the next cell...
|
|
||||||
|
|
||||||
cellcount++;
|
|
||||||
if (cellcount >= maxcells) break;
|
|
||||||
if ((dirx == 0) && (diry == 0)) break; //vertical ray
|
|
||||||
|
|
||||||
Vector3 cellwp = Grid.GetWorldPos(cellpos);
|
|
||||||
float compx = (dirx < 0) ? cellwp.X : cellwp.X + SpaceGrid.CellSize;
|
|
||||||
float compy = (diry < 0) ? cellwp.Y : cellwp.Y + SpaceGrid.CellSize;
|
|
||||||
float deltx = Math.Abs(compx - rp.X);
|
|
||||||
float delty = Math.Abs(compy - rp.Y);
|
|
||||||
float nextd = 0;
|
|
||||||
if (deltx < delty)
|
|
||||||
{
|
|
||||||
cellpos.X += (int)dirx;
|
|
||||||
nextd = (rd.X != 0) ? (deltx / rd.X) : 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cellpos.Y += (int)diry;
|
|
||||||
nextd = (rd.Y != 0) ? (delty / rd.Y) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
cell = Grid.GetCell(cellpos);
|
|
||||||
|
|
||||||
if (nextd > itemhitdist)
|
|
||||||
{ break; } //next cell is further away than current hit.. no need to continue
|
|
||||||
if (nextd > maxdist)
|
|
||||||
{ break; } //next cell is out of the testing range.. stop now
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hit)
|
if (hit)
|
||||||
{
|
{
|
||||||
@ -1508,9 +1346,6 @@ namespace CodeWalker.World
|
|||||||
bool testcomplete = true;
|
bool testcomplete = true;
|
||||||
Vector3 sphmin = sph.Center - sph.Radius;
|
Vector3 sphmin = sph.Center - sph.Radius;
|
||||||
Vector3 sphmax = sph.Center + sph.Radius;
|
Vector3 sphmax = sph.Center + sph.Radius;
|
||||||
var cellmin = Grid.GetCellPos(sphmin);
|
|
||||||
var cellmax = Grid.GetCellPos(sphmax);
|
|
||||||
var cellcount = 0;
|
|
||||||
var box = new BoundingBox();
|
var box = new BoundingBox();
|
||||||
var tsph = new BoundingSphere();
|
var tsph = new BoundingSphere();
|
||||||
var spht = new BoundingSphere();
|
var spht = new BoundingSphere();
|
||||||
@ -1525,15 +1360,13 @@ namespace CodeWalker.World
|
|||||||
BoundPolygon hitpoly = null;
|
BoundPolygon hitpoly = null;
|
||||||
Vector3 hitnorm = Vector3.Zero;
|
Vector3 hitnorm = Vector3.Zero;
|
||||||
Vector3 hitpos = Vector3.Zero;
|
Vector3 hitpos = Vector3.Zero;
|
||||||
for (int x = cellmin.X; x <= cellmax.X; x++)
|
|
||||||
{
|
|
||||||
for (int y = cellmin.Y; y <= cellmax.Y; y++)
|
|
||||||
{
|
|
||||||
var cell = Grid.GetCell(new Vector2I(x, y));
|
|
||||||
if (cell == null) continue;
|
|
||||||
if (cell.BoundsList == null) continue;
|
|
||||||
|
|
||||||
foreach (var bound in cell.BoundsList)
|
|
||||||
|
if (BoundsStore == null) return res;
|
||||||
|
var boundslist = BoundsStore.GetItems(ref sphmin, ref sphmax);
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var bound in boundslist)
|
||||||
{
|
{
|
||||||
box.Minimum = bound.Min;
|
box.Minimum = bound.Min;
|
||||||
box.Maximum = bound.Max;
|
box.Maximum = bound.Max;
|
||||||
@ -1722,9 +1555,6 @@ namespace CodeWalker.World
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cellcount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (hit)
|
//if (hit)
|
||||||
//{
|
//{
|
||||||
@ -1745,205 +1575,8 @@ namespace CodeWalker.World
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SpaceGrid
|
|
||||||
{
|
|
||||||
public const int CellCount = 500; //cells along a side, total cell count is this squared
|
|
||||||
public const int LastCell = CellCount - 1; //the last cell index in the array
|
|
||||||
public const float WorldSize = 10000.0f; //max world grid size +/- 10000 units
|
|
||||||
public const float CellSize = 2.0f * WorldSize / (float)CellCount;//40.0f; //size of a cell
|
|
||||||
public const float CellSizeInv = 1.0f / CellSize; //inverse of the cell size.
|
|
||||||
public const float CellSizeHalf = CellSize * 0.5f; //half the cell size
|
|
||||||
|
|
||||||
public int TotalBoundsCount = 0; //total number of bounds in this grid
|
|
||||||
public int TotalBoundsRefCount = 0; //total number of bounds placements in cells
|
|
||||||
private int MaxBoundsInCell = 0; //biggest number of bounds added to a single cell
|
|
||||||
private SpaceGridCell DensestBoundsCell = null;
|
|
||||||
|
|
||||||
public int TotalNodeCount = 0; //total map nodes in grid
|
|
||||||
public int TotalNodeRefCount = 0; //total number of map node placements in cells
|
|
||||||
public int MaxNodesInCell = 0; //biggest number of nodes added to a single cell
|
|
||||||
private SpaceGridCell DensestNodeCell = null;
|
|
||||||
|
|
||||||
public int TotalInteriorCount = 0;
|
|
||||||
public int TotalInteriorRefCount = 0;
|
|
||||||
public int MaxInteriorsInCell = 0;
|
|
||||||
private SpaceGridCell DensestInteriorCell = null;
|
|
||||||
|
|
||||||
public SpaceGridCell[,] Cells { get; set; } = new SpaceGridCell[CellCount, CellCount];
|
|
||||||
|
|
||||||
|
|
||||||
public Vector3 GetWorldPos(Vector2I p)
|
|
||||||
{
|
|
||||||
Vector3 ind = new Vector3(p.X, p.Y, 0.0f);
|
|
||||||
return (ind * CellSize) - new Vector3(WorldSize, WorldSize, 0);
|
|
||||||
}
|
|
||||||
public Vector2I GetCellPos(Vector3 p)
|
|
||||||
{
|
|
||||||
Vector3 ind = (p + WorldSize) * CellSizeInv;
|
|
||||||
int x = (int)ind.X;
|
|
||||||
int y = (int)ind.Y;
|
|
||||||
x = (x < 0) ? 0 : (x > LastCell) ? LastCell : x;
|
|
||||||
y = (y < 0) ? 0 : (y > LastCell) ? LastCell : y;
|
|
||||||
return new Vector2I(x, y);
|
|
||||||
}
|
|
||||||
public SpaceGridCell GetCell(Vector2I g)
|
|
||||||
{
|
|
||||||
if ((g.X < 0) || (g.Y < 0) || (g.X >= CellCount) || (g.Y >= CellCount))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
var cell = Cells[g.X, g.Y];
|
|
||||||
if (cell == null)
|
|
||||||
{
|
|
||||||
cell = new SpaceGridCell();
|
|
||||||
Cells[g.X, g.Y] = cell;
|
|
||||||
}
|
|
||||||
return cell;
|
|
||||||
}
|
|
||||||
public SpaceGridCell GetCell(Vector3 p)
|
|
||||||
{
|
|
||||||
return GetCell(GetCellPos(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddBounds(BoundsStoreItem item)
|
|
||||||
{
|
|
||||||
Vector2I min = GetCellPos(item.Min);
|
|
||||||
Vector2I max = GetCellPos(item.Max);
|
|
||||||
|
|
||||||
int cellcount = 0;
|
|
||||||
for (int x = min.X; x <= max.X; x++)
|
|
||||||
{
|
|
||||||
for (int y = min.Y; y <= max.Y; y++)
|
|
||||||
{
|
|
||||||
var cell = GetCell(new Vector2I(x, y));
|
|
||||||
cell.AddBounds(item);
|
|
||||||
TotalBoundsRefCount++;
|
|
||||||
if (cell.BoundsList.Count > MaxBoundsInCell)
|
|
||||||
{
|
|
||||||
MaxBoundsInCell = cell.BoundsList.Count;
|
|
||||||
DensestBoundsCell = cell;
|
|
||||||
}
|
|
||||||
cellcount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cellcount == 0)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
TotalBoundsCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddNode(MapDataStoreNode node)
|
|
||||||
{
|
|
||||||
bool useouter = true;// false;
|
|
||||||
//switch (node.Unk01)
|
|
||||||
//{
|
|
||||||
// case 2:
|
|
||||||
// case 4:
|
|
||||||
// case 20:
|
|
||||||
// case 66:
|
|
||||||
// case 514://lods
|
|
||||||
// useouter = true;
|
|
||||||
// break;
|
|
||||||
// case 128:
|
|
||||||
// case 256://lodlights
|
|
||||||
// useouter = true;
|
|
||||||
// break;
|
|
||||||
// case 18:
|
|
||||||
// case 82://HD nodes
|
|
||||||
// useouter = true;
|
|
||||||
// break;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//Vector2I min = GetCellPos(node.OuterBBMin);
|
|
||||||
//Vector2I max = GetCellPos(node.OuterBBMax);
|
|
||||||
Vector2I min = GetCellPos(useouter ? node.streamingExtentsMin : node.entitiesExtentsMin);
|
|
||||||
Vector2I max = GetCellPos(useouter ? node.streamingExtentsMax : node.entitiesExtentsMax);
|
|
||||||
|
|
||||||
for (int x = min.X; x <= max.X; x++)
|
|
||||||
{
|
|
||||||
for (int y = min.Y; y <= max.Y; y++)
|
|
||||||
{
|
|
||||||
var cell = GetCell(new Vector2I(x, y));
|
|
||||||
cell.AddNode(node);
|
|
||||||
TotalNodeRefCount++;
|
|
||||||
if (cell.NodesList.Count > MaxNodesInCell)
|
|
||||||
{
|
|
||||||
MaxNodesInCell = cell.NodesList.Count;
|
|
||||||
DensestNodeCell = cell;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TotalNodeCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddInterior(CInteriorProxy intprx)
|
|
||||||
{
|
|
||||||
Vector2I min = GetCellPos(intprx.BBMin);
|
|
||||||
Vector2I max = GetCellPos(intprx.BBMax);
|
|
||||||
|
|
||||||
int cellcount = 0;
|
|
||||||
for (int x = min.X; x <= max.X; x++)
|
|
||||||
{
|
|
||||||
for (int y = min.Y; y <= max.Y; y++)
|
|
||||||
{
|
|
||||||
var cell = GetCell(new Vector2I(x, y));
|
|
||||||
cell.AddInterior(intprx);
|
|
||||||
TotalInteriorRefCount++;
|
|
||||||
if (cell.InteriorList.Count > MaxInteriorsInCell)
|
|
||||||
{
|
|
||||||
MaxInteriorsInCell = cell.InteriorList.Count;
|
|
||||||
DensestInteriorCell = cell;
|
|
||||||
}
|
|
||||||
cellcount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cellcount == 0)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
TotalInteriorCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public class SpaceGridCell
|
|
||||||
{
|
|
||||||
public List<MapDataStoreNode> NodesList;
|
|
||||||
public List<BoundsStoreItem> BoundsList;
|
|
||||||
public List<CInteriorProxy> InteriorList;
|
|
||||||
|
|
||||||
public void AddNode(MapDataStoreNode node)
|
|
||||||
{
|
|
||||||
if (NodesList == null)
|
|
||||||
{
|
|
||||||
NodesList = new List<MapDataStoreNode>();
|
|
||||||
}
|
|
||||||
NodesList.Add(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddBounds(BoundsStoreItem item)
|
|
||||||
{
|
|
||||||
if (BoundsList == null)
|
|
||||||
{
|
|
||||||
BoundsList = new List<BoundsStoreItem>(5);
|
|
||||||
}
|
|
||||||
BoundsList.Add(item);
|
|
||||||
}
|
|
||||||
public void RemoveBounds(BoundsStoreItem item)
|
|
||||||
{
|
|
||||||
if (BoundsList != null)
|
|
||||||
{
|
|
||||||
BoundsList.Remove(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddInterior(CInteriorProxy intprx)
|
|
||||||
{
|
|
||||||
if (InteriorList == null)
|
|
||||||
{
|
|
||||||
InteriorList = new List<CInteriorProxy>(5);
|
|
||||||
}
|
|
||||||
InteriorList.Add(intprx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public struct SpaceBoundsKey
|
public struct SpaceBoundsKey
|
||||||
{
|
{
|
||||||
public MetaHash Name { get; set; }
|
public MetaHash Name { get; set; }
|
||||||
@ -1956,6 +1589,317 @@ namespace CodeWalker.World
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class SpaceMapDataStore
|
||||||
|
{
|
||||||
|
public SpaceMapDataStoreNode RootNode;
|
||||||
|
public int SplitThreshold = 10;
|
||||||
|
|
||||||
|
public List<MapDataStoreNode> VisibleItems = new List<MapDataStoreNode>();
|
||||||
|
|
||||||
|
public void Init(List<MapDataStoreNode> rootnodes)
|
||||||
|
{
|
||||||
|
RootNode = new SpaceMapDataStoreNode();
|
||||||
|
RootNode.Owner = this;
|
||||||
|
foreach (var item in rootnodes)
|
||||||
|
{
|
||||||
|
RootNode.Add(item);
|
||||||
|
}
|
||||||
|
RootNode.TrySplit(SplitThreshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MapDataStoreNode> GetItems(ref Vector3 p)
|
||||||
|
{
|
||||||
|
VisibleItems.Clear();
|
||||||
|
|
||||||
|
if (RootNode != null)
|
||||||
|
{
|
||||||
|
RootNode.GetItems(ref p, VisibleItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
return VisibleItems;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class SpaceMapDataStoreNode
|
||||||
|
{
|
||||||
|
public SpaceMapDataStore Owner = null;
|
||||||
|
public SpaceMapDataStoreNode[] Children = null;
|
||||||
|
public List<MapDataStoreNode> Items = null;
|
||||||
|
public Vector3 BBMin = new Vector3(float.MaxValue);
|
||||||
|
public Vector3 BBMax = new Vector3(float.MinValue);
|
||||||
|
public int Depth = 0;
|
||||||
|
|
||||||
|
public void Add(MapDataStoreNode item)
|
||||||
|
{
|
||||||
|
if (Items == null)
|
||||||
|
{
|
||||||
|
Items = new List<MapDataStoreNode>();
|
||||||
|
}
|
||||||
|
BBMin = Vector3.Min(BBMin, item.streamingExtentsMin);
|
||||||
|
BBMax = Vector3.Max(BBMax, item.streamingExtentsMax);
|
||||||
|
Items.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TrySplit(int threshold)
|
||||||
|
{
|
||||||
|
if ((Items == null) || (Items.Count <= threshold))
|
||||||
|
{ return; }
|
||||||
|
|
||||||
|
Children = new SpaceMapDataStoreNode[4];
|
||||||
|
|
||||||
|
var newItems = new List<MapDataStoreNode>();
|
||||||
|
|
||||||
|
var ncen = (BBMax + BBMin) * 0.5f;
|
||||||
|
var next = (BBMax - BBMin) * 0.5f;
|
||||||
|
var nsiz = Math.Max(next.X, next.Y);
|
||||||
|
var nsizh = nsiz * 0.5f;
|
||||||
|
|
||||||
|
foreach (var item in Items)
|
||||||
|
{
|
||||||
|
var imin = item.streamingExtentsMin;
|
||||||
|
var imax = item.streamingExtentsMax;
|
||||||
|
var icen = (imax + imin) * 0.5f;
|
||||||
|
var iext = (imax - imin) * 0.5f;
|
||||||
|
var isiz = Math.Max(iext.X, iext.Y);
|
||||||
|
|
||||||
|
if (isiz >= nsizh)
|
||||||
|
{
|
||||||
|
newItems.Add(item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var cind = ((icen.X > ncen.X) ? 1 : 0) + ((icen.Y > ncen.Y) ? 2 : 0);
|
||||||
|
var c = Children[cind];
|
||||||
|
if (c == null)
|
||||||
|
{
|
||||||
|
c = new SpaceMapDataStoreNode();
|
||||||
|
c.Owner = Owner;
|
||||||
|
c.Depth = Depth + 1;
|
||||||
|
Children[cind] = c;
|
||||||
|
}
|
||||||
|
c.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
var c = Children[i];
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
c.TrySplit(threshold);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Items = newItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetItems(ref Vector3 p, List<MapDataStoreNode> items)
|
||||||
|
{
|
||||||
|
if ((p.X >= BBMin.X) && (p.X <= BBMax.X) && (p.Y >= BBMin.Y) && (p.Y <= BBMax.Y))
|
||||||
|
{
|
||||||
|
if (Items != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Items.Count; i++)
|
||||||
|
{
|
||||||
|
var item = Items[i];
|
||||||
|
var imin = item.streamingExtentsMin;
|
||||||
|
var imax = item.streamingExtentsMax;
|
||||||
|
if ((p.X >= imin.X) && (p.X <= imax.X) && (p.Y >= imin.Y) && (p.Y <= imax.Y))
|
||||||
|
{
|
||||||
|
items.Add(item);
|
||||||
|
item.GetVisibleChildren(ref p, items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Children != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
var c = Children[i];
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
c.GetItems(ref p, items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class SpaceBoundsStore
|
||||||
|
{
|
||||||
|
public SpaceBoundsStoreNode RootNode;
|
||||||
|
public int SplitThreshold = 10;
|
||||||
|
|
||||||
|
public List<BoundsStoreItem> VisibleItems = new List<BoundsStoreItem>();
|
||||||
|
|
||||||
|
public void Init(List<BoundsStoreItem> items)
|
||||||
|
{
|
||||||
|
RootNode = new SpaceBoundsStoreNode();
|
||||||
|
RootNode.Owner = this;
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
RootNode.Add(item);
|
||||||
|
}
|
||||||
|
RootNode.TrySplit(SplitThreshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BoundsStoreItem> GetItems(ref Vector3 min, ref Vector3 max)
|
||||||
|
{
|
||||||
|
VisibleItems.Clear();
|
||||||
|
|
||||||
|
if (RootNode != null)
|
||||||
|
{
|
||||||
|
RootNode.GetItems(ref min, ref max, VisibleItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
return VisibleItems;
|
||||||
|
}
|
||||||
|
public List<BoundsStoreItem> GetItems(ref Ray ray)
|
||||||
|
{
|
||||||
|
VisibleItems.Clear();
|
||||||
|
|
||||||
|
if (RootNode != null)
|
||||||
|
{
|
||||||
|
RootNode.GetItems(ref ray, VisibleItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
return VisibleItems;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class SpaceBoundsStoreNode
|
||||||
|
{
|
||||||
|
public SpaceBoundsStore Owner = null;
|
||||||
|
public SpaceBoundsStoreNode[] Children = null;
|
||||||
|
public List<BoundsStoreItem> Items = null;
|
||||||
|
public Vector3 BBMin = new Vector3(float.MaxValue);
|
||||||
|
public Vector3 BBMax = new Vector3(float.MinValue);
|
||||||
|
public int Depth = 0;
|
||||||
|
|
||||||
|
public void Add(BoundsStoreItem item)
|
||||||
|
{
|
||||||
|
if (Items == null)
|
||||||
|
{
|
||||||
|
Items = new List<BoundsStoreItem>();
|
||||||
|
}
|
||||||
|
BBMin = Vector3.Min(BBMin, item.Min);
|
||||||
|
BBMax = Vector3.Max(BBMax, item.Max);
|
||||||
|
Items.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TrySplit(int threshold)
|
||||||
|
{
|
||||||
|
if ((Items == null) || (Items.Count <= threshold))
|
||||||
|
{ return; }
|
||||||
|
|
||||||
|
Children = new SpaceBoundsStoreNode[4];
|
||||||
|
|
||||||
|
var newItems = new List<BoundsStoreItem>();
|
||||||
|
|
||||||
|
var ncen = (BBMax + BBMin) * 0.5f;
|
||||||
|
var next = (BBMax - BBMin) * 0.5f;
|
||||||
|
var nsiz = Math.Max(next.X, next.Y);
|
||||||
|
var nsizh = nsiz * 0.5f;
|
||||||
|
|
||||||
|
foreach (var item in Items)
|
||||||
|
{
|
||||||
|
var imin = item.Min;
|
||||||
|
var imax = item.Max;
|
||||||
|
var icen = (imax + imin) * 0.5f;
|
||||||
|
var iext = (imax - imin) * 0.5f;
|
||||||
|
var isiz = Math.Max(iext.X, iext.Y);
|
||||||
|
|
||||||
|
if (isiz >= nsizh)
|
||||||
|
{
|
||||||
|
newItems.Add(item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var cind = ((icen.X > ncen.X) ? 1 : 0) + ((icen.Y > ncen.Y) ? 2 : 0);
|
||||||
|
var c = Children[cind];
|
||||||
|
if (c == null)
|
||||||
|
{
|
||||||
|
c = new SpaceBoundsStoreNode();
|
||||||
|
c.Owner = Owner;
|
||||||
|
c.Depth = Depth + 1;
|
||||||
|
Children[cind] = c;
|
||||||
|
}
|
||||||
|
c.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
var c = Children[i];
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
c.TrySplit(threshold);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Items = newItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetItems(ref Vector3 min, ref Vector3 max, List<BoundsStoreItem> items)
|
||||||
|
{
|
||||||
|
if ((max.X >= BBMin.X) && (min.X <= BBMax.X) && (max.Y >= BBMin.Y) && (min.Y <= BBMax.Y))
|
||||||
|
{
|
||||||
|
if (Items != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Items.Count; i++)
|
||||||
|
{
|
||||||
|
var item = Items[i];
|
||||||
|
if ((max.X >= item.Min.X) && (min.X <= item.Max.X) && (max.Y >= item.Min.Y) && (min.Y <= item.Max.Y))
|
||||||
|
{
|
||||||
|
items.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Children != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
var c = Children[i];
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
c.GetItems(ref min, ref max, items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void GetItems(ref Ray ray, List<BoundsStoreItem> items)
|
||||||
|
{
|
||||||
|
var box = new BoundingBox(BBMin, BBMax);
|
||||||
|
if (ray.Intersects(ref box))
|
||||||
|
{
|
||||||
|
if (Items != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Items.Count; i++)
|
||||||
|
{
|
||||||
|
var item = Items[i];
|
||||||
|
box = new BoundingBox(item.Min, item.Max);
|
||||||
|
if (ray.Intersects(box))
|
||||||
|
{
|
||||||
|
items.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Children != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
var c = Children[i];
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
c.GetItems(ref ray, items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public class SpaceNodeGrid
|
public class SpaceNodeGrid
|
||||||
{
|
{
|
||||||
|
@ -51,7 +51,7 @@ namespace CodeWalker.World
|
|||||||
Yft = gfc.GetYft(ModelHash);
|
Yft = gfc.GetYft(ModelHash);
|
||||||
while ((Yft != null) && (!Yft.Loaded))
|
while ((Yft != null) && (!Yft.Loaded))
|
||||||
{
|
{
|
||||||
Thread.Sleep(20);//kinda hacky
|
Thread.Sleep(1);//kinda hacky
|
||||||
Yft = gfc.GetYft(ModelHash);
|
Yft = gfc.GetYft(ModelHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ namespace CodeWalker.World
|
|||||||
ConvRoofDict = gfc.GetYcd(ycdhash);
|
ConvRoofDict = gfc.GetYcd(ycdhash);
|
||||||
while ((ConvRoofDict != null) && (!ConvRoofDict.Loaded))
|
while ((ConvRoofDict != null) && (!ConvRoofDict.Loaded))
|
||||||
{
|
{
|
||||||
Thread.Sleep(20);//kinda hacky
|
Thread.Sleep(1);//kinda hacky
|
||||||
ConvRoofDict = gfc.GetYcd(ycdhash);
|
ConvRoofDict = gfc.GetYcd(ycdhash);
|
||||||
}
|
}
|
||||||
ClipMapEntry cme = null;
|
ClipMapEntry cme = null;
|
||||||
|
@ -46,7 +46,7 @@ namespace CodeWalker.World
|
|||||||
|
|
||||||
while ((Ydr != null) && (!Ydr.Loaded))
|
while ((Ydr != null) && (!Ydr.Loaded))
|
||||||
{
|
{
|
||||||
Thread.Sleep(20);//kinda hacky
|
Thread.Sleep(1);//kinda hacky
|
||||||
Ydr = gfc.GetYdr(useHash);
|
Ydr = gfc.GetYdr(useHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -800,7 +800,7 @@ namespace CodeWalker.Forms
|
|||||||
var ycd = gameFileCache.GetYcd(ycdhash);
|
var ycd = gameFileCache.GetYcd(ycdhash);
|
||||||
while ((ycd != null) && (!ycd.Loaded))
|
while ((ycd != null) && (!ycd.Loaded))
|
||||||
{
|
{
|
||||||
Thread.Sleep(20);//kinda hacky
|
Thread.Sleep(1);//kinda hacky
|
||||||
ycd = gameFileCache.GetYcd(ycdhash);
|
ycd = gameFileCache.GetYcd(ycdhash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -826,7 +826,7 @@ namespace CodeWalker.Peds
|
|||||||
var ycd = GameFileCache.GetYcd(ycdhash);
|
var ycd = GameFileCache.GetYcd(ycdhash);
|
||||||
while ((ycd != null) && (!ycd.Loaded))
|
while ((ycd != null) && (!ycd.Loaded))
|
||||||
{
|
{
|
||||||
Thread.Sleep(20);//kinda hacky
|
Thread.Sleep(1);//kinda hacky
|
||||||
ycd = GameFileCache.GetYcd(ycdhash);
|
ycd = GameFileCache.GetYcd(ycdhash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,8 +82,6 @@ namespace CodeWalker.Project.Panels
|
|||||||
float density = 0.5f; //distance between vertices for the initial grid
|
float density = 0.5f; //distance between vertices for the initial grid
|
||||||
//float clipdz = 0.5f; //any polygons with greater steepness should be removed
|
//float clipdz = 0.5f; //any polygons with greater steepness should be removed
|
||||||
|
|
||||||
Vector2I imin = space.Grid.GetCellPos(new Vector3(min, 0));
|
|
||||||
Vector2I imax = space.Grid.GetCellPos(new Vector3(max, 0));
|
|
||||||
|
|
||||||
//Vector2 vertexCounts = (max - min) / density;
|
//Vector2 vertexCounts = (max - min) / density;
|
||||||
//int vertexCountX = (int)vertexCounts.X;
|
//int vertexCountX = (int)vertexCounts.X;
|
||||||
@ -113,30 +111,22 @@ namespace CodeWalker.Project.Panels
|
|||||||
|
|
||||||
var polys = new List<GenPoly>();
|
var polys = new List<GenPoly>();
|
||||||
|
|
||||||
for (int x = imin.X; x <= imax.X; x++) //generate verts for each world cell
|
var vertexCountXY = (max - min) / density;
|
||||||
{
|
|
||||||
for (int y = imin.Y; y <= imax.Y; y++)
|
|
||||||
{
|
|
||||||
Vector2I gi = new Vector2I(x, y);
|
|
||||||
var cell = space.Grid.GetCell(gi);
|
|
||||||
var cellstr = gi.ToString();
|
|
||||||
var cellmin = space.Grid.GetWorldPos(gi);
|
|
||||||
var cellmax = cellmin + SpaceGrid.CellSize;
|
|
||||||
var vertexCountXY = (cellmax - cellmin) / density;
|
|
||||||
int vertexCountX = (int)vertexCountXY.X+1;
|
int vertexCountX = (int)vertexCountXY.X+1;
|
||||||
int vertexCountY = (int)vertexCountXY.Y+1;
|
int vertexCountY = (int)vertexCountXY.Y+1;
|
||||||
//int vertexCountTot = vertexCountX * vertexCountY;
|
//int vertexCountTot = vertexCountX * vertexCountY;
|
||||||
vgrid.BeginGrid(vertexCountX, vertexCountY);
|
vgrid.BeginGrid(vertexCountX, vertexCountY);
|
||||||
cellmin.Z = 0.0f;//min probably not needed here
|
|
||||||
cellmax.Z = 0.0f;
|
|
||||||
Ray ray = new Ray(Vector3.Zero, new Vector3(0, 0, -1));//for casting with
|
Ray ray = new Ray(Vector3.Zero, new Vector3(0, 0, -1));//for casting with
|
||||||
|
|
||||||
UpdateStatus("Loading cell " + cellstr + " ...");
|
UpdateStatus("Loading YBNs...");
|
||||||
|
|
||||||
//pre-warm the bounds cache for this cell, and find the min/max Z
|
var bmin = new Vector3(min, 0);
|
||||||
if (cell.BoundsList != null)
|
var bmax = new Vector3(max, 0);
|
||||||
{
|
var boundslist = space.BoundsStore.GetItems(ref bmin, ref bmax);
|
||||||
foreach (var boundsitem in cell.BoundsList)
|
|
||||||
|
//pre-warm the bounds cache for this area, and find the min/max Z
|
||||||
|
foreach (var boundsitem in boundslist)
|
||||||
{
|
{
|
||||||
YbnFile ybn = gameFileCache.GetYbn(boundsitem.Name);
|
YbnFile ybn = gameFileCache.GetYbn(boundsitem.Name);
|
||||||
if (ybn == null)
|
if (ybn == null)
|
||||||
@ -160,9 +150,8 @@ namespace CodeWalker.Project.Panels
|
|||||||
}
|
}
|
||||||
if (ybn.Loaded && (ybn.Bounds != null))
|
if (ybn.Loaded && (ybn.Bounds != null))
|
||||||
{
|
{
|
||||||
cellmin.Z = Math.Min(cellmin.Z, ybn.Bounds.BoundingBoxMin.Z);
|
bmin.Z = Math.Min(bmin.Z, ybn.Bounds.BoundingBoxMin.Z);
|
||||||
cellmax.Z = Math.Max(cellmax.Z, ybn.Bounds.BoundingBoxMax.Z);
|
bmax.Z = Math.Max(bmax.Z, ybn.Bounds.BoundingBoxMax.Z);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +160,7 @@ namespace CodeWalker.Project.Panels
|
|||||||
//ray-cast each XY vertex position, and find the height and surface from ybn's
|
//ray-cast each XY vertex position, and find the height and surface from ybn's
|
||||||
//continue casting down to find more surfaces...
|
//continue casting down to find more surfaces...
|
||||||
|
|
||||||
UpdateStatus("Processing cell " + cellstr + " ...");
|
UpdateStatus("Processing...");
|
||||||
|
|
||||||
for (int vx = 0; vx < vertexCountX; vx++)
|
for (int vx = 0; vx < vertexCountX; vx++)
|
||||||
{
|
{
|
||||||
@ -179,8 +168,8 @@ namespace CodeWalker.Project.Panels
|
|||||||
{
|
{
|
||||||
vgrid.BeginCell(vx, vy);
|
vgrid.BeginCell(vx, vy);
|
||||||
var vcoffset = new Vector3(vx, vy, 0) * density;
|
var vcoffset = new Vector3(vx, vy, 0) * density;
|
||||||
ray.Position = cellmin + vcoffset;
|
ray.Position = bmin + vcoffset;
|
||||||
ray.Position.Z = cellmax.Z + 1.0f;//start the ray at the top of the cell
|
ray.Position.Z = bmax.Z + 1.0f;//start the ray at the top of the cell
|
||||||
var intres = space.RayIntersect(ray, float.MaxValue, layers);
|
var intres = space.RayIntersect(ray, float.MaxValue, layers);
|
||||||
hitTestCount++;
|
hitTestCount++;
|
||||||
while (intres.Hit)// && (intres.HitDist > 0))
|
while (intres.Hit)// && (intres.HitDist > 0))
|
||||||
@ -229,8 +218,20 @@ namespace CodeWalker.Project.Panels
|
|||||||
newCount += genPolys.Count;
|
newCount += genPolys.Count;
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//try merge generated polys into bigger ones, while keeping convex!
|
//try merge generated polys into bigger ones, while keeping convex!
|
||||||
|
@ -381,7 +381,7 @@ namespace CodeWalker.World
|
|||||||
var ycd = GameFileCache.GetYcd(ycdhash);
|
var ycd = GameFileCache.GetYcd(ycdhash);
|
||||||
while ((ycd != null) && (!ycd.Loaded))
|
while ((ycd != null) && (!ycd.Loaded))
|
||||||
{
|
{
|
||||||
Thread.Sleep(20);//bite me
|
Thread.Sleep(1);//bite me
|
||||||
ycd = GameFileCache.GetYcd(ycdhash);
|
ycd = GameFileCache.GetYcd(ycdhash);
|
||||||
}
|
}
|
||||||
if (ycd != null)
|
if (ycd != null)
|
||||||
|
@ -2213,7 +2213,7 @@ namespace CodeWalker
|
|||||||
public SpaceRayIntersectResult GetSpaceMouseRay()
|
public SpaceRayIntersectResult GetSpaceMouseRay()
|
||||||
{
|
{
|
||||||
SpaceRayIntersectResult ret = new SpaceRayIntersectResult();
|
SpaceRayIntersectResult ret = new SpaceRayIntersectResult();
|
||||||
if (space.Inited && space.Grid != null)
|
if (space.Inited && space.BoundsStore != null)
|
||||||
{
|
{
|
||||||
Ray mray = new Ray();
|
Ray mray = new Ray();
|
||||||
mray.Position = camera.MouseRay.Position + camera.Position;
|
mray.Position = camera.MouseRay.Position + camera.Position;
|
||||||
|
Loading…
Reference in New Issue
Block a user