internal static void UpdateBounds(this SpriteSkin spriteSkin, Matrix4x4 worldToLocal, Matrix4x4 rootLocalToWorld) { //var worldToLocal = spriteSkin.transform.worldToLocalMatrix; //var rootLocalToWorld = spriteSkin.rootBone.localToWorldMatrix; var unityBounds = spriteSkin.bounds; var matrix = math.mul(worldToLocal, rootLocalToWorld); var center = new float4(unityBounds.center, 1); var extents = new float4(unityBounds.extents, 0); var p0 = math.mul(matrix, center + new float4(-extents.x, -extents.y, extents.z, extents.w)); var p1 = math.mul(matrix, center + new float4(-extents.x, extents.y, extents.z, extents.w)); var p2 = math.mul(matrix, center + extents); var p3 = math.mul(matrix, center + new float4(extents.x, -extents.y, extents.z, extents.w)); var min = math.min(p0, math.min(p1, math.min(p2, p3))); var max = math.max(p0, math.max(p1, math.max(p2, p3))); extents = (max - min) * 0.5f; center = min + extents; var newBounds = new Bounds() { center = new Vector3(center.x, center.y, center.z), extents = new Vector3(extents.x, extents.y, extents.z) }; InternalEngineBridge.SetLocalAABB(spriteSkin.spriteRenderer, newBounds); }
internal unsafe static void CalculateBounds(this SpriteSkin spriteSkin) { Debug.Assert(spriteSkin.isValid); var sprite = spriteSkin.sprite; var deformVertexData = new NativeArray <byte>(sprite.GetVertexStreamSize() * sprite.GetVertexCount(), Allocator.Temp, NativeArrayOptions.UninitializedMemory); void *dataPtr = NativeArrayUnsafeUtility.GetUnsafePtr(deformVertexData); var deformedPosSlice = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice <Vector3>(dataPtr, sprite.GetVertexStreamSize(), sprite.GetVertexCount()); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeSliceUnsafeUtility.SetAtomicSafetyHandle(ref deformedPosSlice, NativeArrayUnsafeUtility.GetAtomicSafetyHandle(deformVertexData)); #endif var rootBone = spriteSkin.rootBone; spriteSkin.Bake(ref deformVertexData); var bounds = new Bounds(); if (deformVertexData.Length > 0) { bounds.min = rootBone.InverseTransformPoint(deformedPosSlice[0]); bounds.max = bounds.min; } foreach (var v in deformedPosSlice) { bounds.Encapsulate(rootBone.InverseTransformPoint(v)); } bounds.extents = Vector3.Scale(bounds.extents, new Vector3(1.25f, 1.25f, 1f)); spriteSkin.bounds = bounds; }
internal static void Bake(this SpriteSkin spriteSkin, ref NativeArray <byte> deformVertexData) { if (!spriteSkin.isValid) { throw new Exception("Bake error: invalid SpriteSkin"); } var sprite = spriteSkin.spriteRenderer.sprite; var boneTransformsArray = spriteSkin.boneTransforms; Deform(sprite, Matrix4x4.identity, boneTransformsArray, ref deformVertexData); }
internal static int CalculateTransformHash(this SpriteSkin spriteSkin) { int bits = 0; int boneTransformHash = GetHash(spriteSkin.transform.localToWorldMatrix) >> bits; bits++; foreach (var transform in spriteSkin.boneTransforms) { boneTransformHash ^= GetHash(transform.localToWorldMatrix) >> bits; bits = (bits + 1) % 8; } return(boneTransformHash); }
internal static SpriteSkinValidationResult Validate(this SpriteSkin spriteSkin) { if (spriteSkin.spriteRenderer.sprite == null) { return(SpriteSkinValidationResult.SpriteNotFound); } var bindPoses = spriteSkin.spriteRenderer.sprite.GetBindPoses(); if (bindPoses.Length == 0) { return(SpriteSkinValidationResult.SpriteHasNoSkinningInformation); } if (spriteSkin.rootBone == null) { return(SpriteSkinValidationResult.RootTransformNotFound); } if (spriteSkin.boneTransforms == null) { return(SpriteSkinValidationResult.InvalidTransformArray); } if (bindPoses.Length != spriteSkin.boneTransforms.Length) { return(SpriteSkinValidationResult.InvalidTransformArrayLength); } var rootFound = false; foreach (var boneTransform in spriteSkin.boneTransforms) { if (boneTransform == null) { return(SpriteSkinValidationResult.TransformArrayContainsNull); } if (boneTransform == spriteSkin.rootBone) { rootFound = true; } } if (!rootFound) { return(SpriteSkinValidationResult.RootNotFoundInTransformArray); } return(SpriteSkinValidationResult.Ready); }
internal static unsafe void UpdateBounds(this SpriteSkin spriteSkin, NativeArray <byte> deformedVertices) { byte *deformedPosOffset = (byte *)NativeArrayUnsafeUtility.GetUnsafePtr(deformedVertices); var spriteVertexCount = spriteSkin.sprite.GetVertexCount(); var spriteVertexStreamSize = spriteSkin.sprite.GetVertexStreamSize(); NativeSlice <float3> deformedPositions = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice <float3>(deformedPosOffset, spriteVertexStreamSize, spriteVertexCount); #if ENABLE_UNITY_COLLECTIONS_CHECKS var handle = CreateSafetyChecks <float3>(ref deformedPositions); #endif spriteSkin.bounds = CalculateSpriteSkinBounds(deformedPositions); #if ENABLE_UNITY_COLLECTIONS_CHECKS DisposeSafetyChecks(handle); #endif InternalEngineBridge.SetLocalAABB(spriteSkin.spriteRenderer, spriteSkin.bounds); }
internal unsafe static void CalculateBounds(this SpriteSkin spriteSkin) { Debug.Assert(spriteSkin.isValid); var sprite = spriteSkin.sprite; var deformVertexData = new NativeArray <byte>(sprite.GetVertexStreamSize() * sprite.GetVertexCount(), Allocator.Temp, NativeArrayOptions.UninitializedMemory); void *dataPtr = NativeArrayUnsafeUtility.GetUnsafePtr(deformVertexData); var deformedPosSlice = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice <Vector3>(dataPtr, sprite.GetVertexStreamSize(), sprite.GetVertexCount()); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeSliceUnsafeUtility.SetAtomicSafetyHandle(ref deformedPosSlice, NativeArrayUnsafeUtility.GetAtomicSafetyHandle(deformVertexData)); #endif spriteSkin.Bake(ref deformVertexData); UpdateBounds(spriteSkin, deformVertexData); deformVertexData.Dispose(); }
internal static void CreateBoneHierarchy(this SpriteSkin spriteSkin) { if (spriteSkin.spriteRenderer.sprite == null) { throw new InvalidOperationException("SpriteRenderer has no Sprite set"); } var spriteBones = spriteSkin.spriteRenderer.sprite.GetBones(); var transforms = new Transform[spriteBones.Length]; Transform root = null; for (int i = 0; i < spriteBones.Length; ++i) { CreateGameObject(i, spriteBones, transforms, spriteSkin.transform); if (spriteBones[i].parentId < 0 && root == null) { root = transforms[i]; } } spriteSkin.rootBone = root; spriteSkin.boneTransforms = transforms; }
internal static void ResetBindPose(this SpriteSkin spriteSkin) { if (!spriteSkin.isValid) { throw new InvalidOperationException("SpriteSkin is not valid"); } var spriteBones = spriteSkin.spriteRenderer.sprite.GetBones(); var boneTransforms = spriteSkin.boneTransforms; for (int i = 0; i < boneTransforms.Length; ++i) { var boneTransform = boneTransforms[i]; var spriteBone = spriteBones[i]; if (spriteBone.parentId != -1) { boneTransform.localPosition = spriteBone.position; boneTransform.localRotation = spriteBone.rotation; boneTransform.localScale = Vector3.one; } } }
//TODO: Add other ways to find the transforms in case the named path fails internal static void Rebind(this SpriteSkin spriteSkin) { if (spriteSkin.spriteRenderer.sprite == null) { throw new ArgumentException("SpriteRenderer has no Sprite set"); } if (spriteSkin.rootBone == null) { throw new ArgumentException("SpriteSkin has no rootBone"); } var spriteBones = spriteSkin.spriteRenderer.sprite.GetBones(); var boneTransforms = new List <Transform>(); for (int i = 0; i < spriteBones.Length; ++i) { var boneTransformPath = CalculateBoneTransformPath(i, spriteBones); var boneTransform = spriteSkin.rootBone.Find(boneTransformPath); boneTransforms.Add(boneTransform); } spriteSkin.boneTransforms = boneTransforms.ToArray(); }