Fixed BoundComposite BVH crash issue for fragments with destroyed models, also fixed missing BVH for XML imported ybn

This commit is contained in:
dexy 2021-12-19 04:11:51 +11:00
parent a6a2acab75
commit a4998e36c8
3 changed files with 46 additions and 7 deletions

View File

@ -2222,7 +2222,7 @@ namespace CodeWalker.GameFiles
public override IResourceBlock[] GetReferences() public override IResourceBlock[] GetReferences()
{ {
BuildBVH(); BuildBVH(false);
var list = new List<IResourceBlock>(base.GetReferences()); var list = new List<IResourceBlock>(base.GetReferences());
if (BVH != null) list.Add(BVH); if (BVH != null) list.Add(BVH);
@ -2232,7 +2232,7 @@ namespace CodeWalker.GameFiles
public void BuildBVH() public void BuildBVH(bool updateParent = true)
{ {
if ((Polygons?.Length ?? 0) <= 0) //in some des_ drawables? if ((Polygons?.Length ?? 0) <= 0) //in some des_ drawables?
{ {
@ -2308,7 +2308,7 @@ namespace CodeWalker.GameFiles
BVH = bvh; BVH = bvh;
if (Parent != null) if (updateParent && (Parent != null)) //only update parent when live editing in world view!
{ {
Parent.BuildBVH(); Parent.BuildBVH();
} }
@ -2766,7 +2766,14 @@ namespace CodeWalker.GameFiles
if (!(Owner is FragPhysicsLOD) && !(Owner is FragPhysArchetype) && !(Owner is VerletCloth)) if (!(Owner is FragPhysicsLOD) && !(Owner is FragPhysArchetype) && !(Owner is VerletCloth))
{ } { }
} }
if (Owner is FragPhysArchetype fpa)
{
if (fpa == fpa.Owner?.Archetype2) //for destroyed yft archetype, don't use a BVH.
{
BVH = null;
return;
}
}
var items = new List<BVHBuilderItem>(); var items = new List<BVHBuilderItem>();
for (int i = 0; i < Children.data_items.Length; i++) for (int i = 0; i < Children.data_items.Length; i++)
@ -2783,6 +2790,10 @@ namespace CodeWalker.GameFiles
it.Bounds = child; it.Bounds = child;
items.Add(it); items.Add(it);
} }
else
{
items.Add(null);//items need to have correct count to set the correct capacity for the BVH!
}
} }
var bvh = BVHBuilder.Build(items, 1); //composites have BVH item threshold of 1 var bvh = BVHBuilder.Build(items, 1); //composites have BVH item threshold of 1
@ -4424,9 +4435,12 @@ namespace CodeWalker.GameFiles
var max = new Vector3(float.MinValue); var max = new Vector3(float.MinValue);
var nodes = new List<BVHBuilderNode>(); var nodes = new List<BVHBuilderNode>();
var trees = new List<BVHBuilderNode>(); var trees = new List<BVHBuilderNode>();
var iteml = new List<BVHBuilderItem>();
for (int i = 0; i < items.Count; i++) for (int i = 0; i < items.Count; i++)
{ {
var item = items[i]; var item = items[i];
if (item == null) continue;
iteml.Add(item);
min = Vector3.Min(min, item.Min); min = Vector3.Min(min, item.Min);
max = Vector3.Max(max, item.Max); max = Vector3.Max(max, item.Max);
} }
@ -4438,7 +4452,7 @@ namespace CodeWalker.GameFiles
bvh.QuantumInverse = new Vector4(1.0f / bvh.Quantum.XYZ(), float.NaN); bvh.QuantumInverse = new Vector4(1.0f / bvh.Quantum.XYZ(), float.NaN);
var root = new BVHBuilderNode(); var root = new BVHBuilderNode();
root.Items = items.ToList(); root.Items = iteml.ToList();
root.Build(itemThreshold); root.Build(itemThreshold);
root.GatherNodes(nodes); root.GatherNodes(nodes);
root.GatherTrees(trees); root.GatherTrees(trees);
@ -4491,8 +4505,21 @@ namespace CodeWalker.GameFiles
} }
var nodecount = bvhnodes.Count;
if (itemThreshold <= 1) //for composites, capacity needs to be (numchildren*2)+1, with empty nodes filling up the space..
{
var capacity = (items.Count * 2) + 1;
var emptynode = new BVHNode_s();
emptynode.ItemId = 1;
while (bvhnodes.Count < capacity)
{
bvhnodes.Add(emptynode);
}
}
bvh.Nodes = new ResourceSimpleList64b_s<BVHNode_s>(); bvh.Nodes = new ResourceSimpleList64b_s<BVHNode_s>();
bvh.Nodes.data_items = bvhnodes.ToArray(); bvh.Nodes.data_items = bvhnodes.ToArray();
bvh.Nodes.EntriesCount = (uint)nodecount;
bvh.Trees = new ResourceSimpleList64_s<BVHTreeInfo_s>(); bvh.Trees = new ResourceSimpleList64_s<BVHTreeInfo_s>();
bvh.Trees.data_items = bvhtrees.ToArray(); bvh.Trees.data_items = bvhtrees.ToArray();

View File

@ -2277,6 +2277,14 @@ namespace CodeWalker.GameFiles
} }
} }
if (Archetype1 != null)
{
Archetype1.Owner = this;
}
if (Archetype2 != null)
{
Archetype2.Owner = this;
}
if (Bound != null) if (Bound != null)
{ {
Bound.Owner = this; Bound.Owner = this;
@ -2520,12 +2528,14 @@ namespace CodeWalker.GameFiles
if (a1node != null) if (a1node != null)
{ {
Archetype1 = new FragPhysArchetype(); Archetype1 = new FragPhysArchetype();
Archetype1.Owner = this;
Archetype1.ReadXml(a1node); Archetype1.ReadXml(a1node);
} }
var a2node = node.SelectSingleNode("Archetype2"); var a2node = node.SelectSingleNode("Archetype2");
if (a2node != null) if (a2node != null)
{ {
Archetype2 = new FragPhysArchetype(); Archetype2 = new FragPhysArchetype();
Archetype2.Owner = this;
Archetype2.ReadXml(a2node); Archetype2.ReadXml(a2node);
} }
var abnode = node.SelectSingleNode("ArticulatedBody"); var abnode = node.SelectSingleNode("ArticulatedBody");
@ -3349,6 +3359,8 @@ namespace CodeWalker.GameFiles
private string_r NameBlock = null;//used only when saving private string_r NameBlock = null;//used only when saving
public FragPhysicsLOD Owner { get; set; } //required for correct bounds BVH generation
public override void Read(ResourceDataReader reader, params object[] parameters) public override void Read(ResourceDataReader reader, params object[] parameters)
{ {

View File

@ -906,7 +906,7 @@ namespace CodeWalker.GameFiles
// structure data // structure data
public ulong EntriesPointer { get; private set; } public ulong EntriesPointer { get; private set; }
public uint EntriesCount { get; private set; } public uint EntriesCount { get; set; } //this needs to be set manually for this type! make sure it's <= capacity
public uint EntriesCapacity { get; private set; } public uint EntriesCapacity { get; private set; }
// reference data // reference data
@ -939,7 +939,7 @@ namespace CodeWalker.GameFiles
{ {
// update structure data //TODO: fix // update structure data //TODO: fix
this.EntriesPointer = (ulong)(this.data_block != null ? this.data_block.FilePosition : 0); this.EntriesPointer = (ulong)(this.data_block != null ? this.data_block.FilePosition : 0);
this.EntriesCount = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0); //this.EntriesCount = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
this.EntriesCapacity = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0); this.EntriesCapacity = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
// write structure data // write structure data