private GPUAnimations.Animation GetAnimation(int index) { GPUAnimations animations = _animationTexture.GetAnimations(); GPUAnimations.Animation animation = animations._animations[Mathf.Clamp(index, 0, animations._animations.Length)]; return(animation); }
public void Play(GameObject gameObject, GPUAnimations.Animation animation, WrapMode wrapMode = WrapMode.Default, float speed = 1.0f) { _gameObject = gameObject; _animation = animation; _frame = 0f; _speed = speed; _wrapMode = wrapMode; }
public GPUAnimationPlayer(GPUAnimations.Animation animation, WrapMode wrapMode = WrapMode.Default, float speed = 1.0f) { _animation = animation; _wrapMode = wrapMode; _speed = speed; _frame = 0f; _loops = 0; }
internal GPUAnimationState(GPUAnimation owner, GPUAnimations.Animation animation) { _owner = owner; WrapMode wrapMode = animation._wrapMode; if (wrapMode == WrapMode.Default) { wrapMode = WrapMode.Once; } _player = new GPUAnimationPlayer(animation, wrapMode); }
private void PlayAnimation(AnimatorStateInfo state, AnimatorClipInfo[] clips, int playerIndex) { if (clips.Length > 0) { AnimationClip clip = clips[0].clip; GPUAnimations.Animation animation = ((GPUAnimatorOverrideController)_animator.runtimeAnimatorController).GetAnimation(clip); _clipPlayers[playerIndex] = new GPUAnimationPlayer(animation, animation._wrapMode, 0.0f); } else { _clipPlayers[playerIndex] = new GPUAnimationPlayer(); } }
private void PlayAnimation(AnimatorStateInfo state, AnimatorClipInfo[] clips, int playerIndex) { if (clips.Length > 0) { AnimationClip clip = clips[0].clip; int animationIndex = _animationLookUp[clip]; GPUAnimations.Animation animation = _animations.GetAnimations()[animationIndex]; _clipPlayers[playerIndex].Play(this.gameObject, animation, clip.wrapMode, 0f); } else { _clipPlayers[playerIndex].Stop(); } }
private Vector4 StartNewAnimation(bool randomOffset) { ParticleAnimation anim = PickRandomAnimation(); GPUAnimations.Animation animation = GetAnimation(anim._animationIndex); Vector4 data; data.x = anim._animationIndex; data.y = randomOffset ? Random.Range(0, animation._totalFrames - 2) : 0; data.z = anim._speedRange.GetRandomValue(); data.w = 1.0f; return(data); }
protected override void UpdateProperties() { #if UNITY_EDITOR for (int i = 0; i < _materials.Length; i++) { _animationTexture.SetMaterialProperties(_materials[i]); } #endif //Update property block for (int i = 0; i < GetNumRenderedParticles(); i++) { int index = GetRenderedParticlesIndex(i); GPUAnimations.Animation animation = GetAnimation(Mathf.RoundToInt(_particleCustomData[index].x)); _particleCurrentFrame[i] = animation._startFrameOffset + _particleCustomData[index].y; } //Update property block _propertyBlock.SetFloatArray("frameIndex", _particleCurrentFrame); }
private void UpdateAnimations() { int numParticles = _particleSystem.GetCustomParticleData(_particleCustomData, _customDataChannel); //Update particle frame progress for (int i = 0; i < numParticles; i++) { Vector4 customData = _particleCustomData[i]; //New particle - start playing new animation if (customData.w == 0.0f) { _particleCustomData[i] = StartNewAnimation(true); } //Progress current animation else { GPUAnimations.Animation animation = GetAnimation(Mathf.RoundToInt(customData.x)); //Update current frame customData.y += Time.deltaTime * animation._fps * customData.z; //If animation is finished start playing new animation if (customData.y > animation._totalFrames) { _particleCustomData[i] = StartNewAnimation(false); } else { _particleCustomData[i] = customData; } } } //Update custom data _particleSystem.SetCustomParticleData(_particleCustomData, _customDataChannel); }
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 GPUAnimations Read(BinaryReader reader) { string[] bones = new string[reader.ReadInt32()]; for (int i = 0; i < bones.Length; i++) { bones[i] = reader.ReadString(); } int animCount = reader.ReadInt32(); GPUAnimations.Animation[] animations = new GPUAnimations.Animation[animCount]; for (int i = 0; i < animCount; i++) { string name = reader.ReadString(); int startOffset = reader.ReadInt32(); int totalFrames = reader.ReadInt32(); float fps = reader.ReadSingle(); WrapMode wrapMode = (WrapMode)reader.ReadInt32(); int numEvents = reader.ReadInt32(); AnimationEvent[] events = new AnimationEvent[numEvents]; for (int j = 0; j < numEvents; j++) { events[j] = new AnimationEvent { time = reader.ReadSingle(), functionName = reader.ReadString(), stringParameter = reader.ReadString(), floatParameter = reader.ReadSingle(), intParameter = reader.ReadInt32() //TO DO? //evnt.objectReferenceParameter = reader.Rea(); }; } bool hasRootMotion = reader.ReadBoolean(); Vector3[] rootMotionVelocities = null; Vector3[] rootMotionAngularVelocities = null; if (hasRootMotion) { rootMotionVelocities = new Vector3[totalFrames]; rootMotionAngularVelocities = new Vector3[totalFrames]; for (int j = 0; j < totalFrames; j++) { rootMotionVelocities[j] = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); rootMotionAngularVelocities[j] = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); } } animations[i] = new GPUAnimations.Animation(name, startOffset, totalFrames, fps, wrapMode, events, hasRootMotion, rootMotionVelocities, rootMotionAngularVelocities); } int exposedBoneCount = reader.ReadInt32(); GPUAnimations.ExposedBone[] exposedBones = new GPUAnimations.ExposedBone[exposedBoneCount]; for (int i = 0; i < exposedBoneCount; i++) { int boneIndex = reader.ReadInt32(); int numSamples = reader.ReadInt32(); Vector3[] bonePositions = new Vector3[numSamples]; Quaternion[] boneRotations = new Quaternion[numSamples]; Vector3[] boneScales = new Vector3[numSamples]; for (int j = 0; j < numSamples; j++) { bonePositions[j] = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); boneRotations[j] = new Quaternion(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); boneScales[j] = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); } exposedBones[i] = new GPUAnimations.ExposedBone(boneIndex, bonePositions, boneRotations, boneScales); } TextureFormat format = (TextureFormat)reader.ReadInt32(); int textureWidth = reader.ReadInt32(); int textureHeight = reader.ReadInt32(); int byteLength = reader.ReadInt32(); byte[] bytes = new byte[byteLength]; bytes = reader.ReadBytes(byteLength); Texture2D texture = new Texture2D(textureWidth, textureHeight, format, false); texture.filterMode = FilterMode.Point; texture.LoadRawTextureData(bytes); texture.Apply(); return(new GPUAnimations(texture, animations, bones, exposedBones)); }
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); }