Files
BookRPG/Library/PackageCache/com.unity.2d.animation@011d329ac58b/Runtime/SpriteSkinBoneBoundsUtility.cs
2026-07-16 21:49:59 +01:00

74 lines
3.4 KiB
C#

using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Mathematics;
namespace UnityEngine.U2D.Animation
{
internal static class SpriteSkinBoneBoundsUtility
{
[BurstCompile]
private static unsafe void CalculateBoneBoundsBurst(
ref NativeSlice<Vector3> vertices,
ref NativeSlice<BoneWeight> boneWeights,
ref NativeSlice<Matrix4x4> bindPoses,
int boneCount,
ref NativeArray<Bounds> boneBounds)
{
// Calculate bounds for each bone in bone local space (like SkinnedMeshRenderer)
for (int boneIndex = 0; boneIndex < boneCount; ++boneIndex)
{
float3 min = new float3(float.MaxValue, float.MaxValue, float.MaxValue);
float3 max = new float3(float.MinValue, float.MinValue, float.MinValue);
for (int i = 0; i < vertices.Length; i++)
{
BoneWeight weight = boneWeights[i];
float influence = 0f;
if (weight.boneIndex0 == boneIndex) influence += weight.weight0;
if (weight.boneIndex1 == boneIndex) influence += weight.weight1;
if (weight.boneIndex2 == boneIndex) influence += weight.weight2;
if (weight.boneIndex3 == boneIndex) influence += weight.weight3;
if (influence > 0f)
{
// Transform sprite local vertex to bone local coordinates using bindPose matrix
float3 spriteVertex = vertices[i];
float3 boneLocalVertex = math.transform(bindPoses[boneIndex], spriteVertex);
min = math.min(min, boneLocalVertex);
max = math.max(max, boneLocalVertex);
}
}
float3 ext = (max - min) * 0.5f;
float3 ctr = min + ext;
boneBounds[boneIndex] = new Bounds(ctr, ext * 2);
}
}
/// <summary>
/// Calculates bounds for each bone in bone local space.
/// For each bone, vertices are transformed using the bind pose to bone local space.
/// The returned NativeArray is allocated with Allocator.Persistent and must be disposed by the caller.
/// This method assumes the sprite has bones - use vertex-based bounds calculation mode for sprites without bones.
/// </summary>
/// <param name="sprite">The Sprite to calculate bone AABBs for.</param>
/// <returns>NativeArray of Bounds, one per bone in bone local space.</returns>
public static unsafe NativeArray<Bounds> CalculateBoneBounds(Sprite sprite)
{
if (sprite == null)
return default;
NativeSlice<Vector3> vertices = sprite.GetVertexAttribute<Vector3>(Rendering.VertexAttribute.Position);
NativeSlice<BoneWeight> boneWeights = sprite.GetVertexAttribute<BoneWeight>(Rendering.VertexAttribute.BlendWeight);
NativeSlice<Matrix4x4> bindPoses = sprite.GetBindPoses();
int boneCount = bindPoses.Length;
NativeArray<Bounds> boneBounds = new NativeArray<Bounds>(boneCount, Allocator.Persistent);
CalculateBoneBoundsBurst(ref vertices, ref boneWeights, ref bindPoses, boneCount, ref boneBounds);
return boneBounds;
}
}
}