mirror of
https://github.com/KillzXGaming/Switch-Toolbox
synced 2024-11-22 20:43:09 +00:00
Handle skinned boundings better (may improve shadows and culling performance)
This commit is contained in:
parent
15dca5a055
commit
06e835fd3d
2 changed files with 79 additions and 12 deletions
|
@ -769,7 +769,6 @@ namespace Bfres.Structs
|
||||||
shape.BoneIndex = 0;
|
shape.BoneIndex = 0;
|
||||||
shape.Text = obj.ObjectName;
|
shape.Text = obj.ObjectName;
|
||||||
shape.lodMeshes = obj.lodMeshes;
|
shape.lodMeshes = obj.lodMeshes;
|
||||||
shape.CreateNewBoundingBoxes();
|
|
||||||
shape.CreateBoneList(obj, this, ForceSkinInfluence, ForceSkinInfluenceMax);
|
shape.CreateBoneList(obj, this, ForceSkinInfluence, ForceSkinInfluenceMax);
|
||||||
shape.CreateIndexList(obj, this);
|
shape.CreateIndexList(obj, this);
|
||||||
shape.ApplyImportSettings(csvsettings, GetMaterial(shape.MaterialIndex));
|
shape.ApplyImportSettings(csvsettings, GetMaterial(shape.MaterialIndex));
|
||||||
|
@ -793,6 +792,7 @@ namespace Bfres.Structs
|
||||||
shape.BoneIndex = boneIndex;
|
shape.BoneIndex = boneIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shape.CreateNewBoundingBoxes(Skeleton);
|
||||||
shape.OptmizeAttributeFormats();
|
shape.OptmizeAttributeFormats();
|
||||||
shape.SaveShape(IsWiiU);
|
shape.SaveShape(IsWiiU);
|
||||||
shape.SaveVertexBuffer(IsWiiU);
|
shape.SaveVertexBuffer(IsWiiU);
|
||||||
|
@ -1303,7 +1303,6 @@ namespace Bfres.Structs
|
||||||
shape.MaterialIndex = 0;
|
shape.MaterialIndex = 0;
|
||||||
|
|
||||||
shape.lodMeshes = obj.lodMeshes;
|
shape.lodMeshes = obj.lodMeshes;
|
||||||
shape.CreateNewBoundingBoxes();
|
|
||||||
shape.CreateBoneList(obj, this, ForceSkinInfluence, ForceSkinInfluenceMax);
|
shape.CreateBoneList(obj, this, ForceSkinInfluence, ForceSkinInfluenceMax);
|
||||||
shape.CreateIndexList(obj, this, ForceSkinInfluence, ForceSkinInfluenceMax);
|
shape.CreateIndexList(obj, this, ForceSkinInfluence, ForceSkinInfluenceMax);
|
||||||
shape.ApplyImportSettings(settings, GetMaterial(shape.MaterialIndex));
|
shape.ApplyImportSettings(settings, GetMaterial(shape.MaterialIndex));
|
||||||
|
@ -1329,6 +1328,7 @@ namespace Bfres.Structs
|
||||||
shape.BoneIndex = boneIndex;
|
shape.BoneIndex = boneIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shape.CreateNewBoundingBoxes(Skeleton);
|
||||||
shape.OptmizeAttributeFormats();
|
shape.OptmizeAttributeFormats();
|
||||||
shape.SaveShape(IsWiiU);
|
shape.SaveShape(IsWiiU);
|
||||||
shape.SaveVertexBuffer(IsWiiU);
|
shape.SaveVertexBuffer(IsWiiU);
|
||||||
|
|
|
@ -355,7 +355,7 @@ namespace Bfres.Structs
|
||||||
private void GenerateBoundingBoxes(object sender, EventArgs args)
|
private void GenerateBoundingBoxes(object sender, EventArgs args)
|
||||||
{
|
{
|
||||||
Cursor.Current = Cursors.WaitCursor;
|
Cursor.Current = Cursors.WaitCursor;
|
||||||
CreateNewBoundingBoxes();
|
CreateNewBoundingBoxes(GetParentModel().Skeleton);
|
||||||
SaveShape(GetResFileU() != null);
|
SaveShape(GetResFileU() != null);
|
||||||
UpdateVertexData();
|
UpdateVertexData();
|
||||||
Cursor.Current = Cursors.Default;
|
Cursor.Current = Cursors.Default;
|
||||||
|
@ -390,7 +390,7 @@ namespace Bfres.Structs
|
||||||
lod.subMeshes.Add(subMesh);
|
lod.subMeshes.Add(subMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateNewBoundingBoxes();
|
CreateNewBoundingBoxes(GetParentModel().Skeleton);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateLODMeshes(object sender, EventArgs args)
|
private void GenerateLODMeshes(object sender, EventArgs args)
|
||||||
|
@ -399,7 +399,7 @@ namespace Bfres.Structs
|
||||||
|
|
||||||
//Todo add lod generating
|
//Todo add lod generating
|
||||||
|
|
||||||
CreateNewBoundingBoxes();
|
CreateNewBoundingBoxes(GetParentModel().Skeleton);
|
||||||
SaveShape(GetResFileU() != null);
|
SaveShape(GetResFileU() != null);
|
||||||
UpdateVertexData();
|
UpdateVertexData();
|
||||||
GenerateBoundingNodes();
|
GenerateBoundingNodes();
|
||||||
|
@ -421,7 +421,7 @@ namespace Bfres.Structs
|
||||||
lodMeshes.Remove(meshes[i]);
|
lodMeshes.Remove(meshes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateNewBoundingBoxes();
|
CreateNewBoundingBoxes(GetParentModel().Skeleton);
|
||||||
SaveShape(GetResFileU() != null);
|
SaveShape(GetResFileU() != null);
|
||||||
UpdateVertexData();
|
UpdateVertexData();
|
||||||
GenerateBoundingNodes();
|
GenerateBoundingNodes();
|
||||||
|
@ -970,13 +970,13 @@ namespace Bfres.Structs
|
||||||
VertexSkinCount = obj.GetMaxSkinInfluenceCount();
|
VertexSkinCount = obj.GetMaxSkinInfluenceCount();
|
||||||
|
|
||||||
lodMeshes = obj.lodMeshes;
|
lodMeshes = obj.lodMeshes;
|
||||||
CreateNewBoundingBoxes();
|
|
||||||
CreateBoneList(obj, (FMDL)Parent.Parent, settings.LimitSkinCount, ForceSkinInfluenceMax);
|
CreateBoneList(obj, (FMDL)Parent.Parent, settings.LimitSkinCount, ForceSkinInfluenceMax);
|
||||||
CreateIndexList(obj, (FMDL)Parent.Parent, settings.LimitSkinCount, ForceSkinInfluenceMax);
|
CreateIndexList(obj, (FMDL)Parent.Parent, settings.LimitSkinCount, ForceSkinInfluenceMax);
|
||||||
BoneIndices = GetIndices(GetParentModel().Skeleton);
|
BoneIndices = GetIndices(GetParentModel().Skeleton);
|
||||||
|
|
||||||
ApplyImportSettings(settings, GetFMAT());
|
ApplyImportSettings(settings, GetFMAT());
|
||||||
|
|
||||||
|
CreateNewBoundingBoxes(GetParentModel().Skeleton);
|
||||||
OptmizeAttributeFormats();
|
OptmizeAttributeFormats();
|
||||||
SaveShape(IsWiiU);
|
SaveShape(IsWiiU);
|
||||||
SaveVertexBuffer(IsWiiU);
|
SaveVertexBuffer(IsWiiU);
|
||||||
|
@ -1178,23 +1178,53 @@ namespace Bfres.Structs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateNewBoundingBoxes()
|
public void CreateNewBoundingBoxes(STSkeleton skeleton)
|
||||||
{
|
{
|
||||||
boundingBoxes.Clear();
|
boundingBoxes.Clear();
|
||||||
boundingRadius.Clear();
|
boundingRadius.Clear();
|
||||||
foreach (LOD_Mesh mesh in lodMeshes)
|
foreach (LOD_Mesh mesh in lodMeshes)
|
||||||
{
|
{
|
||||||
BoundingBox box = CalculateBoundingBox();
|
BoundingBox box = CalculateBoundingBox(skeleton);
|
||||||
boundingBoxes.Add(box);
|
boundingBoxes.Add(box);
|
||||||
boundingRadius.Add(box.Radius);
|
boundingRadius.Add(box.Radius);
|
||||||
foreach (LOD_Mesh.SubMesh sub in mesh.subMeshes)
|
foreach (LOD_Mesh.SubMesh sub in mesh.subMeshes)
|
||||||
boundingBoxes.Add(box);
|
boundingBoxes.Add(box);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private BoundingBox CalculateBoundingBox()
|
|
||||||
|
private BoundingBox CalculateBoundingBox(STSkeleton skeleton)
|
||||||
{
|
{
|
||||||
Vector3 min = CalculateBBMin(vertices);
|
Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
|
||||||
Vector3 max = CalculateBBMax(vertices);
|
Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue);
|
||||||
|
|
||||||
|
if (VertexSkinCount > 0)
|
||||||
|
{
|
||||||
|
var aabb = CalculateSkinnedBoundings(skeleton, vertices);
|
||||||
|
//Failed to get bounding data for some reason, calculate normally
|
||||||
|
//This shouldn't happen but it's a fail safe option.
|
||||||
|
if (aabb.Count == 0)
|
||||||
|
{
|
||||||
|
min = CalculateBBMin(vertices);
|
||||||
|
max = CalculateBBMax(vertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the largest values in local space to create the largest bounding box
|
||||||
|
foreach (var bounding in aabb)
|
||||||
|
{
|
||||||
|
min.X = Math.Min(min.X, bounding.Min.X);
|
||||||
|
min.Y = Math.Min(min.Y, bounding.Min.Y);
|
||||||
|
min.Z = Math.Min(min.Z, bounding.Min.Z);
|
||||||
|
max.X = Math.Max(max.X, bounding.Max.X);
|
||||||
|
max.Y = Math.Max(max.Y, bounding.Max.Y);
|
||||||
|
max.Z = Math.Max(max.Z, bounding.Max.Z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
min = CalculateBBMin(vertices);
|
||||||
|
max = CalculateBBMax(vertices);
|
||||||
|
}
|
||||||
|
|
||||||
Vector3 center = max + min;
|
Vector3 center = max + min;
|
||||||
|
|
||||||
float xxMax = GetExtent(max.X, min.X);
|
float xxMax = GetExtent(max.X, min.X);
|
||||||
|
@ -1207,6 +1237,43 @@ namespace Bfres.Structs
|
||||||
return new BoundingBox() { Radius = radius, Center = center, Extend = extend };
|
return new BoundingBox() { Radius = radius, Center = center, Extend = extend };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<AABB> CalculateSkinnedBoundings(STSkeleton skeleton, List<Vertex> vertices)
|
||||||
|
{
|
||||||
|
Dictionary<int, AABB> skinnedBoundings = new Dictionary<int, AABB>();
|
||||||
|
for (int i = 0; i < vertices.Count; i++)
|
||||||
|
{
|
||||||
|
foreach (var boneID in vertices[i].boneIds)
|
||||||
|
{
|
||||||
|
if (!skinnedBoundings.ContainsKey(boneID))
|
||||||
|
skinnedBoundings.Add(boneID, new AABB());
|
||||||
|
|
||||||
|
//Get the skinned bone transform
|
||||||
|
var transform = skeleton.bones[boneID].Transform;
|
||||||
|
var inverted = transform.Inverted();
|
||||||
|
|
||||||
|
//Get the position in local coordinates
|
||||||
|
var position = vertices[i].pos;
|
||||||
|
position = OpenTK.Vector3.TransformPosition(position, inverted);
|
||||||
|
|
||||||
|
var bounding = skinnedBoundings[boneID];
|
||||||
|
//Set the min and max values
|
||||||
|
bounding.Min.X = Math.Min(bounding.Min.X, position.X);
|
||||||
|
bounding.Min.Y = Math.Min(bounding.Min.Y, position.Y);
|
||||||
|
bounding.Min.Z = Math.Min(bounding.Min.Z, position.Z);
|
||||||
|
bounding.Max.X = Math.Max(bounding.Max.X, position.X);
|
||||||
|
bounding.Max.Y = Math.Max(bounding.Max.Y, position.Y);
|
||||||
|
bounding.Max.Z = Math.Max(bounding.Max.Z, position.Z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return skinnedBoundings.Values.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AABB
|
||||||
|
{
|
||||||
|
public Vector3 Min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
|
||||||
|
public Vector3 Max = new Vector3(float.MinValue, float.MinValue, float.MinValue);
|
||||||
|
}
|
||||||
|
|
||||||
private float CalculateBoundingRadius(Vector3 min, Vector3 max)
|
private float CalculateBoundingRadius(Vector3 min, Vector3 max)
|
||||||
{
|
{
|
||||||
Vector3 length = max - min;
|
Vector3 length = max - min;
|
||||||
|
|
Loading…
Reference in a new issue