diff --git a/CodeWalker.Core/GameFiles/Resources/Bounds.cs b/CodeWalker.Core/GameFiles/Resources/Bounds.cs index 3425395..201ccf9 100644 --- a/CodeWalker.Core/GameFiles/Resources/Bounds.cs +++ b/CodeWalker.Core/GameFiles/Resources/Bounds.cs @@ -2222,7 +2222,7 @@ namespace CodeWalker.GameFiles public override IResourceBlock[] GetReferences() { - BuildBVH(); + BuildBVH(false); var list = new List(base.GetReferences()); 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? { @@ -2308,7 +2308,7 @@ namespace CodeWalker.GameFiles BVH = bvh; - if (Parent != null) + if (updateParent && (Parent != null)) //only update parent when live editing in world view! { Parent.BuildBVH(); } @@ -2766,7 +2766,14 @@ namespace CodeWalker.GameFiles 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(); for (int i = 0; i < Children.data_items.Length; i++) @@ -2783,6 +2790,10 @@ namespace CodeWalker.GameFiles it.Bounds = child; 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 @@ -4424,9 +4435,12 @@ namespace CodeWalker.GameFiles var max = new Vector3(float.MinValue); var nodes = new List(); var trees = new List(); + var iteml = new List(); for (int i = 0; i < items.Count; i++) { var item = items[i]; + if (item == null) continue; + iteml.Add(item); min = Vector3.Min(min, item.Min); max = Vector3.Max(max, item.Max); } @@ -4438,7 +4452,7 @@ namespace CodeWalker.GameFiles bvh.QuantumInverse = new Vector4(1.0f / bvh.Quantum.XYZ(), float.NaN); var root = new BVHBuilderNode(); - root.Items = items.ToList(); + root.Items = iteml.ToList(); root.Build(itemThreshold); root.GatherNodes(nodes); 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(); bvh.Nodes.data_items = bvhnodes.ToArray(); + bvh.Nodes.EntriesCount = (uint)nodecount; bvh.Trees = new ResourceSimpleList64_s(); bvh.Trees.data_items = bvhtrees.ToArray(); diff --git a/CodeWalker.Core/GameFiles/Resources/Frag.cs b/CodeWalker.Core/GameFiles/Resources/Frag.cs index 8792b05..5a05e75 100644 --- a/CodeWalker.Core/GameFiles/Resources/Frag.cs +++ b/CodeWalker.Core/GameFiles/Resources/Frag.cs @@ -2277,6 +2277,14 @@ namespace CodeWalker.GameFiles } } + if (Archetype1 != null) + { + Archetype1.Owner = this; + } + if (Archetype2 != null) + { + Archetype2.Owner = this; + } if (Bound != null) { Bound.Owner = this; @@ -2520,12 +2528,14 @@ namespace CodeWalker.GameFiles if (a1node != null) { Archetype1 = new FragPhysArchetype(); + Archetype1.Owner = this; Archetype1.ReadXml(a1node); } var a2node = node.SelectSingleNode("Archetype2"); if (a2node != null) { Archetype2 = new FragPhysArchetype(); + Archetype2.Owner = this; Archetype2.ReadXml(a2node); } var abnode = node.SelectSingleNode("ArticulatedBody"); @@ -3349,6 +3359,8 @@ namespace CodeWalker.GameFiles 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) { diff --git a/CodeWalker.Core/GameFiles/Resources/ResourceBaseTypes.cs b/CodeWalker.Core/GameFiles/Resources/ResourceBaseTypes.cs index 4255542..00904e7 100644 --- a/CodeWalker.Core/GameFiles/Resources/ResourceBaseTypes.cs +++ b/CodeWalker.Core/GameFiles/Resources/ResourceBaseTypes.cs @@ -906,7 +906,7 @@ namespace CodeWalker.GameFiles // structure data 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; } // reference data @@ -939,7 +939,7 @@ namespace CodeWalker.GameFiles { // update structure data //TODO: fix 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); // write structure data