public override void Initialise(GPUAnimatorRenderer renderer) { base.Initialise(renderer); _skinnedMeshRenderer = GameObjectUtils.GetComponent <SkinnedMeshRenderer>(this.gameObject, true); _animationStates = new GPUAnimationState[0]; _primaryAnimationState = null; _secondaryAnimationState = null; GPUAnimations animations = _renderer._animations.GetAnimations(); _animationStates = new GPUAnimationState[animations._animations.Length]; for (int i = 0; i < animations._animations.Length; i++) { _animationStates[i] = new GPUAnimationState(this, animations._animations[i]); } _activeAnimationStates = new List <GPUAnimationState>(animations._animations.Length + 1); _primaryAnimationState = GetAnimationState(_defaultAnimation); _secondaryAnimationState = null; if (_primaryAnimationState != null && _playAutomatically) { _primaryAnimationState.Enabled = true; _primaryAnimationState.Weight = 1.0f; if (_wrapMode != WrapMode.Default) { _primaryAnimationState.WrapMode = _wrapMode; } } }
private static int GetExposedBoneIndex(GPUAnimations animations, string boneName) { if (animations != null) { string[] boneNames = animations._bones; for (int i = 0; i < boneNames.Length; i++) { if (boneNames[i] == boneName) { for (int j = 0; j < animations._exposedBones.Length; j++) { if (animations._exposedBones[j]._boneIndex == i) { return(j); } } UnityEngine.Debug.LogError("Bone '" + boneName + "' isn't exposed in GPU Animations Asset"); return(-1); } } } return(-1); }
private void LoadIfNeeded() { if (_animationTexture == null && _asset != null) { _animationTexture = GPUAnimations.LoadFromFile(_asset); } }
private GPUAnimations.Animation GetAnimation(int index) { GPUAnimations animations = _animationTexture.GetAnimations(); GPUAnimations.Animation animation = animations._animations[Mathf.Clamp(index, 0, animations._animations.Length)]; return(animation); }
private void OnDrawAnimationItem(Rect rect, int index, bool selected, bool focused) { GPUAnimatorParticleSystem particleSystem = target as GPUAnimatorParticleSystem; GPUAnimatorParticleSystem.ParticleAnimation animation = (GPUAnimatorParticleSystem.ParticleAnimation)_animationList.list[index]; float columnWidth = rect.width / 3f; rect.width = columnWidth; GPUAnimations animations = particleSystem._animationTexture.GetAnimations(); GUIContent[] animNames = new GUIContent[animations._animations.Length]; for (int i = 0; i < animNames.Length; i++) { animNames[i] = new GUIContent(animations._animations[i]._name); } animation._animationIndex = EditorGUI.Popup(rect, animation._animationIndex, animNames); rect.x += columnWidth; animation._probability = EditorGUI.Slider(rect, animation._probability, 0f, 1f); rect.x += columnWidth; { rect.width = columnWidth * 0.5f; animation._speedRange._min = EditorGUI.FloatField(rect, animation._speedRange._min); rect.x += rect.width; animation._speedRange._max = EditorGUI.FloatField(rect, animation._speedRange._max); } _animationList.list[index] = animation; }
private void UpdateBoneTransform() { bool followPosition = (_flags & TransformFlags.Translate) != 0; bool followRotation = (_flags & TransformFlags.Rotate) != 0; bool followScale = (_flags & TransformFlags.Scale) != 0; Vector3 localPosition; Quaternion localRotation; Vector3 localScale; //Work out local space bone transform { GPUAnimations animations = _animator.GetRenderer()._animations.GetAnimations(); float curAnimWeight = _animator.GetMainAnimationWeight(); GetFrameInfo(_animator.GetMainAnimationFrame(), out int prevFrame, out int nextFrame, out float frameLerp); animations._exposedBones[_exposedBoneIndex].GetBoneTransform(prevFrame, nextFrame, frameLerp, followPosition, followRotation, followScale, out localPosition, out localRotation, out localScale); if (curAnimWeight < 1.0f) { GetFrameInfo(_animator.GetBackgroundAnimationFrame(), out prevFrame, out nextFrame, out frameLerp); animations._exposedBones[_exposedBoneIndex].GetBoneTransform(prevFrame, nextFrame, frameLerp, followPosition, followRotation, followScale, out Vector3 backgroundLocalPosition, out Quaternion backgroundLocalRotation, out Vector3 backgroundLocalScale); if (followPosition) { localPosition = Vector3.Lerp(backgroundLocalPosition, localPosition, curAnimWeight); } if (followRotation) { localRotation = Quaternion.Slerp(backgroundLocalRotation, localRotation, curAnimWeight); } if (followScale) { localScale = Vector3.Lerp(backgroundLocalScale, localScale, curAnimWeight); } } } //Set world transform from this { if (followPosition && followRotation) { this.transform.SetPositionAndRotation(_animator.transform.TransformPoint(localPosition), _animator.transform.rotation * localRotation); } else if (followPosition) { this.transform.position = _animator.transform.TransformPoint(localPosition); } else if (followRotation) { this.transform.rotation = _animator.transform.rotation * localRotation; } if (followScale) { GameObjectUtils.SetTransformWorldScale(this.transform, Vector3.Scale(_animator.transform.lossyScale, localScale)); } } }
private void LoadIfNeeded() { if (_animationTexture == null && _asset != null) { BinaryReader reader = new BinaryReader(new MemoryStream(_asset.bytes)); _animationTexture = GPUAnimationsIO.Read(reader); } }
public void SetNormalizedTime(float normalizedTime) { if (_gameObject != null) { //TO DO! use wrap mode to clamp, loop or ping-pong float prevFrame = _frame; _frame = (_animation._totalFrames - 1) * (normalizedTime - Mathf.Floor(normalizedTime)); GPUAnimations.CheckForEvents(_gameObject, _animation, prevFrame, _frame); } }
private void Initialise() { _initialised = true; GPUAnimations animations = _animator.GetRenderer()._animations.GetAnimations(); _exposedBoneIndex = GetExposedBoneIndex(animations, _boneName); _exposedBoneNumSamples = animations._exposedBones[_exposedBoneIndex]._cachedBonePositions.Length; if (_exposedBoneIndex == -1) { this.enabled = false; } }
public GPUAnimatorOverrideController(RuntimeAnimatorController controller, GPUAnimations animations, List <KeyValuePair <AnimationClip, AnimationClip> > overrideClips) : base(controller) { this.name = controller.name + " (GPU Animated)"; _animations = animations; _animationLookUp = new Dictionary <AnimationClip, int>(); foreach (KeyValuePair <AnimationClip, AnimationClip> clipPair in overrideClips) { _animationLookUp[clipPair.Value] = GetAnimationIndex(clipPair.Key); } ApplyOverrides(overrideClips); }
public GPUAnimatorOverrideController(RuntimeAnimatorController controller, GPUAnimations animations) : base(controller) { this.name = controller.name + " (GPU Animated)"; _animations = animations; _animationLookUp = new Dictionary <AnimationClip, int>(); List <KeyValuePair <AnimationClip, AnimationClip> > overrideClips = new List <KeyValuePair <AnimationClip, AnimationClip> >(); foreach (AnimationClip origClip in controller.animationClips) { //Override original animation AnimationClip overrideClip = CreateOverrideClip(origClip); overrideClips.Add(new KeyValuePair <AnimationClip, AnimationClip>(origClip, overrideClip)); //Cache what gpu animation it corresponds too _animationLookUp[overrideClip] = GetAnimationIndex(origClip); } ApplyOverrides(overrideClips); }
private static void SaveAnimationTexture(GPUAnimations animationTexture, string fileName) { string directory = Path.GetDirectoryName(fileName); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } FileStream file = File.Open(fileName, FileMode.Create); BinaryWriter writer = new BinaryWriter(file); GPUAnimationsIO.Write(animationTexture, writer); file.Close(); #if UNITY_EDITOR //Refresh the saved asset AssetUtils.RefreshAsset(fileName); #endif }
public void Update(float deltaTime) { if (_gameObject != null && deltaTime > 0f && _speed > 0f) { float prevFrame = _frame; _frame += deltaTime * _animation._fps * _speed; GPUAnimations.CheckForEvents(_gameObject, _animation, prevFrame, _frame); if (_frame > _animation._totalFrames - 1) { switch (_wrapMode) { case WrapMode.Clamp: case WrapMode.ClampForever: { _frame = _animation._totalFrames - 1; } break; case WrapMode.PingPong: { //TO DO! speed should reverese } break; case WrapMode.Loop: case WrapMode.Default: default: { _frame -= (_animation._totalFrames - 1); } break; } } } }
private static void SaveAnimationTexture(GPUAnimations animationTexture, string fileName) { string directory = Path.GetDirectoryName(fileName); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } FileStream file = File.Open(fileName, FileMode.Create); BinaryWriter writer = new BinaryWriter(file); writer.Write(animationTexture._numBones); writer.Write(animationTexture._animations.Length); for (int i = 0; i < animationTexture._animations.Length; i++) { writer.Write(animationTexture._animations[i]._name); writer.Write(animationTexture._animations[i]._startFrameOffset); writer.Write(animationTexture._animations[i]._totalFrames); writer.Write(animationTexture._animations[i]._fps); writer.Write((int)animationTexture._animations[i]._wrapMode); writer.Write(animationTexture._animations[i]._events.Length); for (int j = 0; j < animationTexture._animations[i]._events.Length; j++) { writer.Write(animationTexture._animations[i]._events[j].time); writer.Write(animationTexture._animations[i]._events[j].functionName); writer.Write(animationTexture._animations[i]._events[j].stringParameter); writer.Write(animationTexture._animations[i]._events[j].floatParameter); writer.Write(animationTexture._animations[i]._events[j].intParameter); //TO DO? //writer.Write(animationTexture._animations[i]._events[j].objectReferenceParameter); } writer.Write(animationTexture._animations[i]._hasRootMotion); if (animationTexture._animations[i]._hasRootMotion) { for (int j = 0; j < animationTexture._animations[i]._totalFrames; j++) { writer.Write(animationTexture._animations[i]._rootMotionVelocities[j].x); writer.Write(animationTexture._animations[i]._rootMotionVelocities[j].y); writer.Write(animationTexture._animations[i]._rootMotionVelocities[j].z); writer.Write(animationTexture._animations[i]._rootMotionAngularVelocities[j].x); writer.Write(animationTexture._animations[i]._rootMotionAngularVelocities[j].y); writer.Write(animationTexture._animations[i]._rootMotionAngularVelocities[j].z); } } } //Write texture! byte[] bytes = animationTexture._texture.GetRawTextureData(); writer.Write(animationTexture._texture.width); writer.Write(animationTexture._texture.height); writer.Write(bytes.Length); writer.Write(bytes); file.Close(); #if UNITY_EDITOR //Refresh the saved asset AssetUtils.RefreshAsset(fileName); #endif }
private IEnumerator BakeAnimationTexture(string path) { _working = true; GameObject gameObject = Instantiate(_evaluatedObject); { if (PrefabUtility.IsAnyPrefabInstanceRoot(gameObject)) { PrefabUtility.UnpackPrefabInstance(gameObject, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction); } gameObject.SetActive(true); gameObject.transform.parent = null; gameObject.transform.localPosition = Vector3.zero; gameObject.transform.localRotation = Quaternion.identity; gameObject.transform.localScale = Vector3.one; } AnimationClip[] animationClips = _animations; string[] animationStateNames = null; int[] animationStateLayers = null; Animator animator = null; //If using animator then get clips and state names from controller if (_useAnimator) { animator = GameObjectUtils.GetComponent <Animator>(gameObject, true); GetAnimationClipsFromAnimator(animator, out animationClips, out animationStateNames, out animationStateLayers); if (animationClips.Length == 0) { DestroyImmediate(gameObject); _working = false; yield break; } AnimatorUtility.DeoptimizeTransformHierarchy(animator.gameObject); animator.cullingMode = AnimatorCullingMode.AlwaysAnimate; } Matrix4x4 rootMat = gameObject.transform.worldToLocalMatrix; SkinnedMeshRenderer[] skinnedMeshes = gameObject.GetComponentsInChildren <SkinnedMeshRenderer>(); Transform[] bones = skinnedMeshes[_skinnedMeshIndex].bones; Matrix4x4[] bindposes = skinnedMeshes[_skinnedMeshIndex].sharedMesh.bindposes; int numBones = bones.Length; if (numBones == 0) { DestroyImmediate(gameObject); _working = false; yield break; } Vector3[] origBonePositons = new Vector3[numBones]; Quaternion[] origBoneRotations = new Quaternion[numBones]; Vector3[] origBoneScales = new Vector3[numBones]; GPUAnimations.Animation[] animations = new GPUAnimations.Animation[animationClips.Length]; //3d array - animation / frame / bones Matrix4x4[][][] boneMatricies = new Matrix4x4[animations.Length + 1][][]; //Insert dummy one frame animation at start which is just the reference pose boneMatricies[0] = new Matrix4x4[1][]; boneMatricies[0][0] = new Matrix4x4[numBones]; for (int i = 0; i < numBones; i++) { origBonePositons[i] = bones[i].localPosition; origBoneRotations[i] = bones[i].localRotation; origBoneScales[i] = bones[i].localScale; //Save reference pose bone matrix boneMatricies[0][0][i] = rootMat * bones[i].localToWorldMatrix * bindposes[i]; } //Start after first frame (as this frame is our reference pose) int startOffset = 1; int totalNumberOfSamples = 1; for (int animIndex = 0; animIndex < animations.Length; animIndex++) { AnimationClip clip = animationClips[animIndex]; bool hasRootMotion = _useAnimator && clip.hasMotionCurves; string name = clip.name; int totalFrames = Mathf.Max(Mathf.FloorToInt(clip.length * clip.frameRate), 1); int totalSamples = totalFrames + 1; totalNumberOfSamples += totalSamples; WrapMode wrapMode = GetClipWrapMode(clip); AnimationEvent[] events = clip.events; //Sample animation boneMatricies[animIndex + 1] = new Matrix4x4[totalSamples][]; Vector3[] rootMotionVelocities = null; Vector3[] rootMotionAngularVelocities = null; if (hasRootMotion) { rootMotionVelocities = new Vector3[totalSamples]; rootMotionAngularVelocities = new Vector3[totalSamples]; } //Reset all bone transforms before sampling animations for (int i = 0; i < numBones; i++) { bones[i].localPosition = origBonePositons[i]; bones[i].localRotation = origBoneRotations[i]; bones[i].localScale = origBoneScales[i]; } //If using an animator, start playing animation with correct layer weights set if (_useAnimator) { for (int layer = 1; layer < animator.layerCount; layer++) { animator.SetLayerWeight(animIndex, layer == animationStateLayers[animIndex] ? 1.0f : 0.0f); } animator.Play(animationStateNames[animIndex], animationStateLayers[animIndex]); //Needed to prevent first frame pop? { animator.Update(0f); yield return(null); animator.Play(animationStateNames[animIndex], animationStateLayers[animIndex]); animator.Update(0f); yield return(null); animator.Play(animationStateNames[animIndex], animationStateLayers[animIndex]); animator.Update(0f); yield return(null); } } for (int i = 0; i < totalSamples; i++) { float normalisedTime = i / (float)totalFrames; //Using animator, update animator to progress forward with animation if (_useAnimator) { for (int layer = 1; layer < animator.layerCount; layer++) { animator.SetLayerWeight(layer, 0.0f); } animator.SetLayerWeight(animationStateLayers[animIndex], 1.0f); float layerWeight = animator.GetLayerWeight(animationStateLayers[animIndex]); animator.Play(animationStateNames[animIndex], animationStateLayers[animIndex], normalisedTime); animator.Update(0f); layerWeight = animator.GetLayerWeight(animationStateLayers[animIndex]); //Wait for end of frame yield return(null); } //Sample animation using legacy system else { bool wasLegacy = clip.legacy; clip.legacy = true; clip.SampleAnimation(gameObject, normalisedTime * clip.length); clip.legacy = wasLegacy; } //Save bone matrices boneMatricies[animIndex + 1][i] = new Matrix4x4[numBones]; for (int boneIndex = 0; boneIndex < numBones; boneIndex++) { boneMatricies[animIndex + 1][i][boneIndex] = rootMat * bones[boneIndex].localToWorldMatrix * bindposes[boneIndex]; } //Save root motion velocities if (hasRootMotion) { rootMotionVelocities[i] = animator.velocity; rootMotionAngularVelocities[i] = animator.angularVelocity; } } //Create animation animations[animIndex] = new GPUAnimations.Animation(name, startOffset, totalFrames, clip.frameRate, wrapMode, events, hasRootMotion, rootMotionVelocities, rootMotionAngularVelocities); startOffset += totalSamples; } //Create and save texture Texture2D texture; { if (!CalculateTextureSize(totalNumberOfSamples, numBones, out int textureSize)) { DestroyImmediate(gameObject); _working = false; yield break; } texture = new Texture2D(textureSize, textureSize, TextureFormat.RGBAHalf, false) { filterMode = FilterMode.Point }; //Loop through animations / frames / bones setting pixels for each bone matrix int pixelx = 0; int pixely = 0; //Foreach animation for (int animIndex = 0; animIndex < boneMatricies.Length; animIndex++) { //For each frame for (int j = 0; j < boneMatricies[animIndex].Length; j++) { //Convert all frame bone matrices to colors Color[] matrixPixels = ConvertMatricesToColor(boneMatricies[animIndex][j]); texture.SetPixels(pixelx, pixely, GPUAnimations.kPixelsPerBoneMatrix, numBones, matrixPixels); //Shift to next frame position pixelx += GPUAnimations.kPixelsPerBoneMatrix; //If less than 4 pixels from edge, move to next row if (textureSize - pixelx < GPUAnimations.kPixelsPerBoneMatrix) { pixelx = 0; pixely += numBones; } } } texture.Apply(); } //Save our exposed bones GPUAnimations.ExposedBone[] exposedBones; { exposedBones = new GPUAnimations.ExposedBone[_exposedBones.Count]; for (int i = 0; i < exposedBones.Length; i++) { //Work out bone index int boneIndex = _exposedBones[i]; Matrix4x4 inverseBindPose = bindposes[boneIndex].inverse; //Work out bone matrixes Vector3[] exposedBonePositions = new Vector3[totalNumberOfSamples]; Quaternion[] exposedBoneRotations = new Quaternion[totalNumberOfSamples]; Vector3[] exposedBoneScales = new Vector3[totalNumberOfSamples]; int sampleIndex = 0; for (int anim = 0; anim < boneMatricies.Length; anim++) { for (int frame = 0; frame < boneMatricies[anim].Length; frame++) { Matrix4x4 boneMatrix = boneMatricies[anim][frame][boneIndex] * inverseBindPose; exposedBonePositions[sampleIndex] = boneMatrix.MultiplyPoint3x4(Vector3.zero); exposedBoneRotations[sampleIndex] = boneMatrix.rotation; exposedBoneScales[sampleIndex] = boneMatrix.lossyScale; sampleIndex++; } } exposedBones[i] = new GPUAnimations.ExposedBone(boneIndex, exposedBonePositions, exposedBoneRotations, exposedBoneScales); } } GPUAnimations animationTexture = new GPUAnimations(texture, animations, _boneNames, exposedBones); SaveAnimationTexture(animationTexture, path); DestroyImmediate(gameObject); _working = false; yield break; }
public static void Write(GPUAnimations animations, BinaryWriter writer) { writer.Write(animations._bones.Length); for (int i = 0; i < animations._bones.Length; i++) { writer.Write(animations._bones[i]); } writer.Write(animations._animations.Length); for (int i = 0; i < animations._animations.Length; i++) { writer.Write(animations._animations[i]._name); writer.Write(animations._animations[i]._startFrameOffset); writer.Write(animations._animations[i]._totalFrames); writer.Write(animations._animations[i]._fps); writer.Write((int)animations._animations[i]._wrapMode); writer.Write(animations._animations[i]._events.Length); for (int j = 0; j < animations._animations[i]._events.Length; j++) { writer.Write(animations._animations[i]._events[j].time); writer.Write(animations._animations[i]._events[j].functionName); writer.Write(animations._animations[i]._events[j].stringParameter); writer.Write(animations._animations[i]._events[j].floatParameter); writer.Write(animations._animations[i]._events[j].intParameter); //TO DO? //writer.Write(animationTexture._animations[i]._events[j].objectReferenceParameter); } writer.Write(animations._animations[i]._hasRootMotion); if (animations._animations[i]._hasRootMotion) { for (int j = 0; j < animations._animations[i]._totalFrames; j++) { writer.Write(animations._animations[i]._rootMotionVelocities[j].x); writer.Write(animations._animations[i]._rootMotionVelocities[j].y); writer.Write(animations._animations[i]._rootMotionVelocities[j].z); writer.Write(animations._animations[i]._rootMotionAngularVelocities[j].x); writer.Write(animations._animations[i]._rootMotionAngularVelocities[j].y); writer.Write(animations._animations[i]._rootMotionAngularVelocities[j].z); } } } writer.Write(animations._exposedBones.Length); for (int i = 0; i < animations._exposedBones.Length; i++) { writer.Write(animations._exposedBones[i]._boneIndex); writer.Write(animations._exposedBones[i]._cachedBonePositions.Length); for (int j = 0; j < animations._exposedBones[i]._cachedBonePositions.Length; j++) { writer.Write(animations._exposedBones[i]._cachedBonePositions[j].x); writer.Write(animations._exposedBones[i]._cachedBonePositions[j].y); writer.Write(animations._exposedBones[i]._cachedBonePositions[j].z); writer.Write(animations._exposedBones[i]._cachedBoneRotations[j].x); writer.Write(animations._exposedBones[i]._cachedBoneRotations[j].y); writer.Write(animations._exposedBones[i]._cachedBoneRotations[j].z); writer.Write(animations._exposedBones[i]._cachedBoneRotations[j].w); writer.Write(animations._exposedBones[i]._cachedBoneScales[j].x); writer.Write(animations._exposedBones[i]._cachedBoneScales[j].y); writer.Write(animations._exposedBones[i]._cachedBoneScales[j].z); } } byte[] bytes = animations._texture.GetRawTextureData(); writer.Write((int)animations._texture.format); writer.Write(animations._texture.width); writer.Write(animations._texture.height); writer.Write(bytes.Length); writer.Write(bytes); }
private IEnumerator BakeAnimationTexture() { GameObject gameObject = Instantiate(_animatorObject); SkinnedMeshRenderer[] skinnedMeshes = gameObject.GetComponentsInChildren <SkinnedMeshRenderer>(); SkinnedMeshRenderer skinnedMesh = skinnedMeshes[_skinnedMeshIndex]; Transform[] bones = skinnedMesh.bones; Matrix4x4[] bindposes = skinnedMesh.sharedMesh.bindposes; AnimationClip[] animationClips = _animations; Animator animator = null; string[] animationStateNames = null; if (skinnedMesh.bones.Length == 0) { yield break; } //If using animator then get clips and state names from controller if (_useAnimator) { animator = GameObjectUtils.GetComponent <Animator>(gameObject, true); if (animator == null) { yield break; } GetAnimationClipsFromAnimator(animator, out animationClips, out animationStateNames); if (animationClips.Length == 0) { yield break; } } int numBones = bones.Length; GPUAnimations.Animation[] animations = new GPUAnimations.Animation[animationClips.Length]; //3d array - animation / frame / bones Matrix4x4[][][] boneWorldMatrix = new Matrix4x4[animations.Length][][]; Matrix4x4 rootMat = gameObject.transform.worldToLocalMatrix; int startOffset = 0; for (int animIndex = 0; animIndex < animations.Length; animIndex++) { AnimationClip clip = animationClips[animIndex]; bool hasRootMotion = animator != null && clip.hasMotionCurves; string name = clip.name; int totalFrames = Mathf.FloorToInt(clip.length * clip.frameRate); WrapMode wrapMode = clip.wrapMode; AnimationEvent[] events = clip.events; //Sample animation boneWorldMatrix[animIndex] = new Matrix4x4[totalFrames][]; Vector3[] rootMotionVelocities = null; Vector3[] rootMotionAngularVelocities = null; if (hasRootMotion) { rootMotionVelocities = new Vector3[totalFrames]; rootMotionAngularVelocities = new Vector3[totalFrames]; } float lastFrame = totalFrames - 1; for (int frame = 0; frame < totalFrames; frame++) { float normalisedTime = frame / lastFrame; //Sample animation using legacy system if (animator == null) { bool wasLegacy = clip.legacy; clip.legacy = true; clip.SampleAnimation(gameObject, normalisedTime * clip.length); clip.legacy = wasLegacy; } //Using animator, update animator to progress forward with animation else { animator.Play(animationStateNames[animIndex], 0, normalisedTime); animator.Update(0f); yield return(null); } //Save bone matrices boneWorldMatrix[animIndex][frame] = new Matrix4x4[numBones]; for (int boneIndex = 0; boneIndex < numBones; boneIndex++) { boneWorldMatrix[animIndex][frame][boneIndex] = rootMat * bones[boneIndex].localToWorldMatrix * bindposes[boneIndex]; } //Save root motion velocities if (hasRootMotion) { rootMotionVelocities[frame] = animator.velocity; rootMotionAngularVelocities[frame] = animator.angularVelocity; } } //Create animation animations[animIndex] = new GPUAnimations.Animation(name, startOffset, totalFrames, clip.frameRate, wrapMode, events, hasRootMotion, rootMotionVelocities, rootMotionAngularVelocities); startOffset += totalFrames; } //Create and save texture! Work out width! TextureFormat format = TextureFormat.RGBAHalf; int textureSize; if (!CalculateTextureSize(boneWorldMatrix, out textureSize)) { yield break; } Texture2D texture = new Texture2D(textureSize, textureSize, format, false); texture.filterMode = FilterMode.Point; //Loop through animations / frames / bones setting pixels for each bone matrix int pixelx = 0; int pixely = 0; //Foreach animation for (int animIndex = 0; animIndex < boneWorldMatrix.Length; animIndex++) { //For each frame for (int j = 0; j < boneWorldMatrix[animIndex].Length; j++) { //Convert all frame bone matrices to colors Color[] matrixPixels = ConvertMatricesToColor(boneWorldMatrix[animIndex][j]); texture.SetPixels(pixelx, pixely, 4, numBones, matrixPixels); //Shift to next frame position pixelx += 4; //If less than 4 pixels from edge, move to next row if (textureSize - pixelx < 4) { pixelx = 0; pixely += numBones; } } } texture.Apply(); GPUAnimations animationTexture = new GPUAnimations(animations, numBones, texture); SaveAnimationTexture(animationTexture, _currentFileName); DestroyImmediate(gameObject); }
public void UnloadTexture() { _animationTexture = null; }