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 void Initialise() { _animator = GetComponent <Animator>(); _skinnedMeshRenderer = GameObjectUtils.GetComponent <SkinnedMeshRenderer>(this.gameObject, true); _clipPlayers = new GPUAnimationPlayer[2]; _clipPlayerStates = new int[2]; _currentPlayerIndex = 0; _currentAnimationWeight = 1.0f; AnimatorOverrideController overrideController = new AnimatorOverrideController(_animator.runtimeAnimatorController); _animationLookUp = new Dictionary <AnimationClip, int>(); List <KeyValuePair <AnimationClip, AnimationClip> > anims = new List <KeyValuePair <AnimationClip, AnimationClip> >(); foreach (AnimationClip origClip in overrideController.animationClips) { //Override original animation AnimationClip overrideClip = CreateOverrideClip(origClip); anims.Add(new KeyValuePair <AnimationClip, AnimationClip>(origClip, overrideClip)); //Cache what gpu animation it corresponds too _animationLookUp[overrideClip] = GetAnimationIndex(origClip); } overrideController.ApplyOverrides(anims); _animator.runtimeAnimatorController = overrideController; }
public static ITimelineStateMachineTimer GetTimer(GameObject gameObject) { ITimelineStateMachineTimer timer = GameObjectUtils.GetComponent <ITimelineStateMachineTimer>(gameObject); if (timer == null) { timer = TimelineStateMachineStandardTimer.Instance; } return(timer); }
public override void Initialise(GPUAnimatorRenderer renderer) { base.Initialise(renderer); _animator = GetComponent <Animator>(); _skinnedMeshRenderer = GameObjectUtils.GetComponent <SkinnedMeshRenderer>(this.gameObject, true); int numLayers = Math.Max(Math.Min(1 + _numAdditionalLayers, _animator.layerCount), 1); _layers = new GPUAnimatorLayer[numLayers]; for (int i = 0; i < _layers.Length; i++) { _layers[i] = new GPUAnimatorLayer(_animator, i); } _animator.runtimeAnimatorController = GPUAnimatorRendererControllerOverrider.GetOverrideController(_renderer, _animator); _animator.avatar = GetDummyAvatar(); }
private void OnGUI() { ScriptableObject target = this; SerializedObject so = new SerializedObject(target); GUI.skin.label.richText = true; GUILayout.BeginHorizontal(); { GUILayout.FlexibleSpace(); } GUILayout.EndHorizontal(); EditorGUILayout.Separator(); GUILayout.BeginVertical(); { EditorGUILayout.LabelField("Generate GPU Animation Texture", EditorStyles.largeLabel); EditorGUILayout.Separator(); GameObject prefab = EditorGUILayout.ObjectField("Asset to Evaluate", _evaluatedObject, typeof(GameObject), true) as GameObject; if (prefab != _evaluatedObject) { _evaluatedObject = prefab; _skinnedMeshes = prefab != null?prefab.GetComponentsInChildren <SkinnedMeshRenderer>() : new SkinnedMeshRenderer[0]; _skinnedMeshIndex = 0; _boneNames = _skinnedMeshIndex < _skinnedMeshes.Length ? GetBoneNames(_skinnedMeshes[_skinnedMeshIndex]) : null; _exposedBones = new List <int>(); _useAnimator = prefab != null && GameObjectUtils.GetComponent <Animator>(_evaluatedObject, true) != null; } if (_evaluatedObject != null && _skinnedMeshes != null && _skinnedMeshes.Length > 0) { //Draw Skinned Mesh Popup { string[] skinnedMeshes = new string[_skinnedMeshes.Length]; for (int i = 0; i < skinnedMeshes.Length; i++) { skinnedMeshes[i] = _skinnedMeshes[i].gameObject.name; } int skinnedMeshIndex = EditorGUILayout.Popup("Skinned Mesh", _skinnedMeshIndex, skinnedMeshes); if (skinnedMeshIndex != _skinnedMeshIndex) { _skinnedMeshIndex = skinnedMeshIndex; _boneNames = GetBoneNames(_skinnedMeshes[_skinnedMeshIndex]); _exposedBones = new List <int>(); } } //Draw option for sampling with animator if object has one { Animator animator = GameObjectUtils.GetComponent <Animator>(_evaluatedObject, true); if (animator != null) { _useAnimator = EditorGUILayout.Toggle("Use Animator", _useAnimator); } else { _useAnimator = false; } } //If not usign animator, draw array for animations instead if (!_useAnimator) { //Draw list showing animation clip, SerializedProperty animationsProperty = so.FindProperty("_animations"); EditorGUILayout.PropertyField(animationsProperty, true); so.ApplyModifiedProperties(); } //Draw options for Exposed bones EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField(new GUIContent("Exposed Bones")); string exposedBones = _exposedBones.Count == 0 ? "None" : _boneNames[_exposedBones[0]]; for (int i = 1; i < _exposedBones.Count; i++) { exposedBones += ", " + _boneNames[_exposedBones[i]]; } if (EditorGUILayout.DropdownButton(new GUIContent(exposedBones), FocusType.Keyboard)) { GenericMenu menu = new GenericMenu(); for (int i = 0; i < _boneNames.Length; i++) { menu.AddItem(new GUIContent(_boneNames[i]), _exposedBones.Contains(i), OnClickExposedBone, i); } menu.ShowAsContext(); } } EditorGUILayout.EndHorizontal(); if (_working) { EditorGUILayout.LabelField("Generating Animation Texture", EditorStyles.helpBox); } else if (_skinnedMeshes != null && (_useAnimator || (_animations != null && _animations.Length > 0))) { if (GUILayout.Button("Generate")) { string path = EditorUtility.SaveFilePanelInProject("Save Animation Texture", Path.GetFileNameWithoutExtension(""), "bytes", "Please enter a file name to save the animation texture to"); if (!string.IsNullOrEmpty(path)) { Run(BakeAnimationTexture(path)); } } } } } GUILayout.EndVertical(); EditorGUILayout.Separator(); EditorGUILayout.Separator(); EditorGUILayout.Separator(); GUILayout.BeginVertical(); { EditorGUILayout.LabelField("Generate GPU Animated Mesh", EditorStyles.largeLabel); EditorGUILayout.Separator(); _mesh = EditorGUILayout.ObjectField("Mesh", _mesh, typeof(Mesh), true) as Mesh; _boneIdChanel = (TEXCOORD)EditorGUILayout.EnumPopup("Bone IDs UV Channel", _boneIdChanel); _boneWeightChannel = (TEXCOORD)EditorGUILayout.EnumPopup("Bone Weights UV Channel", _boneWeightChannel); _numBonesPerVertex = EditorGUILayout.IntSlider(new GUIContent("Bones Per Vertex"), _numBonesPerVertex, 1, 4); if (_mesh != null) { if (GUILayout.Button("Generate Animated Texture Ready Mesh")) { string path = EditorUtility.SaveFilePanel("Save Mesh Asset", "Assets/", name, "asset"); if (!string.IsNullOrEmpty(path)) { CreateMeshForAnimations(_mesh, _boneIdChanel, _boneWeightChannel, _numBonesPerVertex, path); } } } } GUILayout.EndVertical(); }
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 GPUAnimatedMeshInstance(GameObject instance, object extraData = null) { _gameObject = instance; _animator = GameObjectUtils.GetComponent <GPUAnimatorBase>(instance, true); _extraData = extraData; }
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 GPUAnimatorInstance(GameObject instance) { _gameObject = instance; _animator = GameObjectUtils.GetComponent <IGPUAnimatorInstance>(instance, true); }