mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2025-01-09 23:15:09 +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)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -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,126 +111,129 @@ 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;
|
||||||
|
int vertexCountX = (int)vertexCountXY.X+1;
|
||||||
|
int vertexCountY = (int)vertexCountXY.Y+1;
|
||||||
|
//int vertexCountTot = vertexCountX * vertexCountY;
|
||||||
|
vgrid.BeginGrid(vertexCountX, vertexCountY);
|
||||||
|
|
||||||
|
Ray ray = new Ray(Vector3.Zero, new Vector3(0, 0, -1));//for casting with
|
||||||
|
|
||||||
|
UpdateStatus("Loading YBNs...");
|
||||||
|
|
||||||
|
var bmin = new Vector3(min, 0);
|
||||||
|
var bmax = new Vector3(max, 0);
|
||||||
|
var boundslist = space.BoundsStore.GetItems(ref bmin, ref bmax);
|
||||||
|
|
||||||
|
//pre-warm the bounds cache for this area, and find the min/max Z
|
||||||
|
foreach (var boundsitem in boundslist)
|
||||||
{
|
{
|
||||||
for (int y = imin.Y; y <= imax.Y; y++)
|
YbnFile ybn = gameFileCache.GetYbn(boundsitem.Name);
|
||||||
|
if (ybn == null)
|
||||||
|
{ continue; } //ybn not found?
|
||||||
|
if (!ybn.Loaded) //ybn not loaded yet...
|
||||||
{
|
{
|
||||||
Vector2I gi = new Vector2I(x, y);
|
UpdateStatus("Loading ybn: " + boundsitem.Name.ToString() + " ...");
|
||||||
var cell = space.Grid.GetCell(gi);
|
int waitCount = 0;
|
||||||
var cellstr = gi.ToString();
|
while (!ybn.Loaded)
|
||||||
var cellmin = space.Grid.GetWorldPos(gi);
|
|
||||||
var cellmax = cellmin + SpaceGrid.CellSize;
|
|
||||||
var vertexCountXY = (cellmax - cellmin) / density;
|
|
||||||
int vertexCountX = (int)vertexCountXY.X+1;
|
|
||||||
int vertexCountY = (int)vertexCountXY.Y+1;
|
|
||||||
//int vertexCountTot = 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
|
|
||||||
|
|
||||||
UpdateStatus("Loading cell " + cellstr + " ...");
|
|
||||||
|
|
||||||
//pre-warm the bounds cache for this cell, and find the min/max Z
|
|
||||||
if (cell.BoundsList != null)
|
|
||||||
{
|
{
|
||||||
foreach (var boundsitem in cell.BoundsList)
|
waitCount++;
|
||||||
|
if (waitCount > 10000)
|
||||||
{
|
{
|
||||||
YbnFile ybn = gameFileCache.GetYbn(boundsitem.Name);
|
UpdateStatus("Timeout waiting for ybn " + boundsitem.Name.ToString() + " to load!");
|
||||||
if (ybn == null)
|
Thread.Sleep(1000); //just to let the message display for a second...
|
||||||
{ continue; } //ybn not found?
|
break;
|
||||||
if (!ybn.Loaded) //ybn not loaded yet...
|
|
||||||
{
|
|
||||||
UpdateStatus("Loading ybn: " + boundsitem.Name.ToString() + " ...");
|
|
||||||
int waitCount = 0;
|
|
||||||
while (!ybn.Loaded)
|
|
||||||
{
|
|
||||||
waitCount++;
|
|
||||||
if (waitCount > 10000)
|
|
||||||
{
|
|
||||||
UpdateStatus("Timeout waiting for ybn " + boundsitem.Name.ToString() + " to load!");
|
|
||||||
Thread.Sleep(1000); //just to let the message display for a second...
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Thread.Sleep(20);//~50fps should be fine
|
|
||||||
ybn = gameFileCache.GetYbn(boundsitem.Name); //try queue it again..
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ybn.Loaded && (ybn.Bounds != null))
|
|
||||||
{
|
|
||||||
cellmin.Z = Math.Min(cellmin.Z, ybn.Bounds.BoundingBoxMin.Z);
|
|
||||||
cellmax.Z = Math.Max(cellmax.Z, ybn.Bounds.BoundingBoxMax.Z);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Thread.Sleep(20);//~50fps should be fine
|
||||||
|
ybn = gameFileCache.GetYbn(boundsitem.Name); //try queue it again..
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (ybn.Loaded && (ybn.Bounds != null))
|
||||||
|
{
|
||||||
//ray-cast each XY vertex position, and find the height and surface from ybn's
|
bmin.Z = Math.Min(bmin.Z, ybn.Bounds.BoundingBoxMin.Z);
|
||||||
//continue casting down to find more surfaces...
|
bmax.Z = Math.Max(bmax.Z, ybn.Bounds.BoundingBoxMax.Z);
|
||||||
|
|
||||||
UpdateStatus("Processing cell " + cellstr + " ...");
|
|
||||||
|
|
||||||
for (int vx = 0; vx < vertexCountX; vx++)
|
|
||||||
{
|
|
||||||
for (int vy = 0; vy < vertexCountY; vy++)
|
|
||||||
{
|
|
||||||
vgrid.BeginCell(vx, vy);
|
|
||||||
var vcoffset = new Vector3(vx, vy, 0) * density;
|
|
||||||
ray.Position = cellmin + vcoffset;
|
|
||||||
ray.Position.Z = cellmax.Z + 1.0f;//start the ray at the top of the cell
|
|
||||||
var intres = space.RayIntersect(ray, float.MaxValue, layers);
|
|
||||||
hitTestCount++;
|
|
||||||
while (intres.Hit)// && (intres.HitDist > 0))
|
|
||||||
{
|
|
||||||
if (intres.HitDist > 0)
|
|
||||||
{
|
|
||||||
hitCount++;
|
|
||||||
vert.Position = intres.Position;
|
|
||||||
vert.Normal = intres.Normal;
|
|
||||||
vert.Material = intres.Material.Type;
|
|
||||||
vert.PolyFlags = (ushort)intres.Material.Flags;
|
|
||||||
vert.PrevIDX = -1;
|
|
||||||
vert.PrevIDY = -1;
|
|
||||||
vert.NextIDX = -1;
|
|
||||||
vert.NextIDY = -1;
|
|
||||||
vert.CompPrevX = false;
|
|
||||||
vert.CompPrevY = false;
|
|
||||||
vert.CompNextX = false;
|
|
||||||
vert.CompNextY = false;
|
|
||||||
vert.PolyID = -1;
|
|
||||||
vgrid.AddVertex(ref vert);
|
|
||||||
|
|
||||||
if (vgrid.CurVertexCount > 15) //too many hits?
|
|
||||||
{ break; }
|
|
||||||
}
|
|
||||||
//continue down until no more hits..... step by 3m
|
|
||||||
ray.Position.Z = intres.Position.Z - 3.0f;
|
|
||||||
intres = space.RayIntersect(ray, float.MaxValue, layers);
|
|
||||||
}
|
|
||||||
vgrid.EndCell(vx, vy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vgrid.EndGrid(); //build vertex array
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vgrid.ConnectVertices();
|
|
||||||
|
|
||||||
|
|
||||||
var genPolys = vgrid.GenPolys2();
|
|
||||||
polys.AddRange(genPolys);
|
|
||||||
|
|
||||||
newCount += genPolys.Count;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//ray-cast each XY vertex position, and find the height and surface from ybn's
|
||||||
|
//continue casting down to find more surfaces...
|
||||||
|
|
||||||
|
UpdateStatus("Processing...");
|
||||||
|
|
||||||
|
for (int vx = 0; vx < vertexCountX; vx++)
|
||||||
|
{
|
||||||
|
for (int vy = 0; vy < vertexCountY; vy++)
|
||||||
|
{
|
||||||
|
vgrid.BeginCell(vx, vy);
|
||||||
|
var vcoffset = new Vector3(vx, vy, 0) * density;
|
||||||
|
ray.Position = bmin + vcoffset;
|
||||||
|
ray.Position.Z = bmax.Z + 1.0f;//start the ray at the top of the cell
|
||||||
|
var intres = space.RayIntersect(ray, float.MaxValue, layers);
|
||||||
|
hitTestCount++;
|
||||||
|
while (intres.Hit)// && (intres.HitDist > 0))
|
||||||
|
{
|
||||||
|
if (intres.HitDist > 0)
|
||||||
|
{
|
||||||
|
hitCount++;
|
||||||
|
vert.Position = intres.Position;
|
||||||
|
vert.Normal = intres.Normal;
|
||||||
|
vert.Material = intres.Material.Type;
|
||||||
|
vert.PolyFlags = (ushort)intres.Material.Flags;
|
||||||
|
vert.PrevIDX = -1;
|
||||||
|
vert.PrevIDY = -1;
|
||||||
|
vert.NextIDX = -1;
|
||||||
|
vert.NextIDY = -1;
|
||||||
|
vert.CompPrevX = false;
|
||||||
|
vert.CompPrevY = false;
|
||||||
|
vert.CompNextX = false;
|
||||||
|
vert.CompNextY = false;
|
||||||
|
vert.PolyID = -1;
|
||||||
|
vgrid.AddVertex(ref vert);
|
||||||
|
|
||||||
|
if (vgrid.CurVertexCount > 15) //too many hits?
|
||||||
|
{ break; }
|
||||||
|
}
|
||||||
|
//continue down until no more hits..... step by 3m
|
||||||
|
ray.Position.Z = intres.Position.Z - 3.0f;
|
||||||
|
intres = space.RayIntersect(ray, float.MaxValue, layers);
|
||||||
|
}
|
||||||
|
vgrid.EndCell(vx, vy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vgrid.EndGrid(); //build vertex array
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
vgrid.ConnectVertices();
|
||||||
|
|
||||||
|
|
||||||
|
var genPolys = vgrid.GenPolys2();
|
||||||
|
polys.AddRange(genPolys);
|
||||||
|
|
||||||
|
newCount += genPolys.Count;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//try merge generated polys into bigger ones, while keeping convex!
|
//try merge generated polys into bigger ones, while keeping convex!
|
||||||
UpdateStatus("Building edge dictionary...");
|
UpdateStatus("Building edge dictionary...");
|
||||||
var edgeDict = new Dictionary<GenEdgeKey, GenEdge>();
|
var edgeDict = new Dictionary<GenEdgeKey, GenEdge>();
|
||||||
|
@ -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