Calculate primary BoundingBox

This commit is contained in:
ackwell 2024-01-17 23:06:02 +11:00 committed by Ottermandias
parent eb02d2a7a7
commit 4b81b065aa
4 changed files with 60 additions and 1 deletions

View file

@ -0,0 +1,33 @@
using Lumina.Data.Parsing;
namespace Penumbra.Import.Models.Import;
/// <summary> Mutable representation of the bounding box surrouding a collection of vertices. </summary>
public class BoundingBox
{
private Vector3 _minimum = Vector3.Zero;
private Vector3 _maximum = Vector3.Zero;
/// <summary> Use the specified position to update this bounding box, expanding it if necessary. </summary>
public void Merge(Vector3 position)
{
_minimum = Vector3.Min(_minimum, position);
_maximum = Vector3.Max(_maximum, position);
}
/// <summary> Merge the provided bounding box into this one, expanding it if necessary. </summary>
/// <param name="other"></param>
public void Merge(BoundingBox other)
{
_minimum = Vector3.Min(_minimum, other._minimum);
_maximum = Vector3.Max(_maximum, other._maximum);
}
/// <summary> Convert this bounding box to the struct format used in .mdl data structures. </summary>
public MdlStructs.BoundingBoxStruct ToStruct()
=> new MdlStructs.BoundingBoxStruct
{
Min = [_minimum.X, _minimum.Y, _minimum.Z, 1],
Max = [_maximum.X, _maximum.Y, _maximum.Z, 1],
};
}

View file

@ -19,6 +19,8 @@ public class MeshImporter(IEnumerable<Node> nodes)
public List<string>? Bones;
public BoundingBox BoundingBox;
public List<string> MetaAttributes;
public List<MeshShapeKey> ShapeKeys;
@ -50,6 +52,8 @@ public class MeshImporter(IEnumerable<Node> nodes)
private List<string>? _bones;
private readonly BoundingBox _boundingBox = new BoundingBox();
private readonly List<string> _metaAttributes = [];
private readonly Dictionary<string, List<MdlStructs.ShapeValueStruct>> _shapeValues = [];
@ -87,6 +91,7 @@ public class MeshImporter(IEnumerable<Node> nodes)
VertexBuffer = _streams[0].Concat(_streams[1]).Concat(_streams[2]),
Indices = _indices,
Bones = _bones,
BoundingBox = _boundingBox,
MetaAttributes = _metaAttributes,
ShapeKeys = _shapeValues
.Select(pair => new MeshShapeKey()
@ -154,6 +159,8 @@ public class MeshImporter(IEnumerable<Node> nodes)
}));
}
_boundingBox.Merge(subMesh.BoundingBox);
// And finally, merge in the sub-mesh struct itself.
_subMeshes.Add(subMesh.SubMeshStruct with
{

View file

@ -29,6 +29,8 @@ public partial class ModelImporter(ModelRoot model)
private readonly List<string> _bones = [];
private readonly List<MdlStructs.BoneTableStruct> _boneTables = [];
private readonly BoundingBox _boundingBox = new BoundingBox();
private readonly List<string> _metaAttributes = [];
private readonly Dictionary<string, List<MdlStructs.ShapeMeshStruct>> _shapeMeshes = [];
@ -95,9 +97,10 @@ public partial class ModelImporter(ModelRoot model)
Materials = [.. materials],
BoundingBoxes = _boundingBox.ToStruct(),
// TODO: Would be good to calculate all of this up the tree.
Radius = 1,
BoundingBoxes = MdlFile.EmptyBoundingBox,
BoneBoundingBoxes = Enumerable.Repeat(MdlFile.EmptyBoundingBox, _bones.Count).ToArray(),
RemainingData = [.._vertexBuffer, ..indexBuffer],
};
@ -156,6 +159,8 @@ public partial class ModelImporter(ModelRoot model)
.ToArray(),
});
_boundingBox.Merge(mesh.BoundingBox);
_subMeshes.AddRange(mesh.SubMeshStructs.Select(m => m with
{
AttributeIndexMask = Utility.GetMergedAttributeMask(

View file

@ -21,6 +21,8 @@ public class SubMeshImporter
public ushort[] Indices;
public BoundingBox BoundingBox;
public string[] MetaAttributes;
public Dictionary<string, List<MdlStructs.ShapeValueStruct>> ShapeValues;
@ -44,6 +46,8 @@ public class SubMeshImporter
private ushort[]? _indices;
private BoundingBox _boundingBox = new BoundingBox();
private string[]? _metaAttributes;
private readonly List<string>? _morphNames;
@ -90,9 +94,11 @@ public class SubMeshImporter
private SubMesh Create()
{
// Build all the data we'll need.
// TODO: This structure is verging on a little silly. Reconsider.
BuildIndices();
BuildVertexAttributes();
BuildVertices();
BuildBoundingBox();
BuildMetaAttributes();
ArgumentNullException.ThrowIfNull(_indices);
@ -133,6 +139,7 @@ public class SubMeshImporter
Strides = _strides,
Streams = _streams,
Indices = _indices,
BoundingBox = _boundingBox,
MetaAttributes = _metaAttributes,
ShapeValues = _shapeValues,
};
@ -255,6 +262,13 @@ public class SubMeshImporter
_shapeValues = morphShapeValues;
}
private void BuildBoundingBox()
{
var positions = _primitive.VertexAccessors["POSITION"].AsVector3Array();
foreach (var position in positions)
_boundingBox.Merge(position);
}
private void BuildMetaAttributes()
{
// We consider any "extras" key with a boolean value set to `true` to be an attribute.