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 List<string>? Bones;
public BoundingBox BoundingBox;
public List<string> MetaAttributes; public List<string> MetaAttributes;
public List<MeshShapeKey> ShapeKeys; public List<MeshShapeKey> ShapeKeys;
@ -50,6 +52,8 @@ public class MeshImporter(IEnumerable<Node> nodes)
private List<string>? _bones; private List<string>? _bones;
private readonly BoundingBox _boundingBox = new BoundingBox();
private readonly List<string> _metaAttributes = []; private readonly List<string> _metaAttributes = [];
private readonly Dictionary<string, List<MdlStructs.ShapeValueStruct>> _shapeValues = []; 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]), VertexBuffer = _streams[0].Concat(_streams[1]).Concat(_streams[2]),
Indices = _indices, Indices = _indices,
Bones = _bones, Bones = _bones,
BoundingBox = _boundingBox,
MetaAttributes = _metaAttributes, MetaAttributes = _metaAttributes,
ShapeKeys = _shapeValues ShapeKeys = _shapeValues
.Select(pair => new MeshShapeKey() .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. // And finally, merge in the sub-mesh struct itself.
_subMeshes.Add(subMesh.SubMeshStruct with _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<string> _bones = [];
private readonly List<MdlStructs.BoneTableStruct> _boneTables = []; private readonly List<MdlStructs.BoneTableStruct> _boneTables = [];
private readonly BoundingBox _boundingBox = new BoundingBox();
private readonly List<string> _metaAttributes = []; private readonly List<string> _metaAttributes = [];
private readonly Dictionary<string, List<MdlStructs.ShapeMeshStruct>> _shapeMeshes = []; private readonly Dictionary<string, List<MdlStructs.ShapeMeshStruct>> _shapeMeshes = [];
@ -95,9 +97,10 @@ public partial class ModelImporter(ModelRoot model)
Materials = [.. materials], Materials = [.. materials],
BoundingBoxes = _boundingBox.ToStruct(),
// TODO: Would be good to calculate all of this up the tree. // TODO: Would be good to calculate all of this up the tree.
Radius = 1, Radius = 1,
BoundingBoxes = MdlFile.EmptyBoundingBox,
BoneBoundingBoxes = Enumerable.Repeat(MdlFile.EmptyBoundingBox, _bones.Count).ToArray(), BoneBoundingBoxes = Enumerable.Repeat(MdlFile.EmptyBoundingBox, _bones.Count).ToArray(),
RemainingData = [.._vertexBuffer, ..indexBuffer], RemainingData = [.._vertexBuffer, ..indexBuffer],
}; };
@ -156,6 +159,8 @@ public partial class ModelImporter(ModelRoot model)
.ToArray(), .ToArray(),
}); });
_boundingBox.Merge(mesh.BoundingBox);
_subMeshes.AddRange(mesh.SubMeshStructs.Select(m => m with _subMeshes.AddRange(mesh.SubMeshStructs.Select(m => m with
{ {
AttributeIndexMask = Utility.GetMergedAttributeMask( AttributeIndexMask = Utility.GetMergedAttributeMask(

View file

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