private void DoRootMotion(float deltaTime) { int frameIndex = GetFrameIndex(); GPUSkinFrame frame = playingClip.frames[frameIndex]; if (frame == null) { return; } Transform trans = transform; if (WrapMode == GPUSkinWrapMode.Once) { if (rootMotionFrameIndex != frameIndex) { Vector3 oldPos = rootMotionDeltaPosition; rootMotionDeltaPosition = frame.rootMotionDeltaPositionQ * trans.forward * frame.rootMotionDeltaPositionL; trans.Translate(rootMotionDeltaPosition - oldPos, Space.World); rootMotionFrameIndex = frameIndex; } } else { int totalFrameCount = Mathf.Max((int)(deltaTime * playingClip.frameRate), frameIndex - rootMotionFrameIndex); int lastFrameIndex = GetTheLastFrameIndex(playingClip); while (totalFrameCount > 0) { if (rootMotionFrameIndex + totalFrameCount >= lastFrameIndex) { var lastFrame = playingClip.frames[lastFrameIndex]; Vector3 oldPos = rootMotionDeltaPosition; rootMotionDeltaPosition = lastFrame.rootMotionDeltaPositionQ * trans.forward * lastFrame.rootMotionDeltaPositionL; trans.Translate(rootMotionDeltaPosition - oldPos, Space.World); totalFrameCount -= (lastFrameIndex - rootMotionFrameIndex); rootMotionFrameIndex = 0; rootMotionDeltaPosition = Vector3.zero; } else { Vector3 oldPos = rootMotionDeltaPosition; rootMotionDeltaPosition = frame.rootMotionDeltaPositionQ * trans.forward * frame.rootMotionDeltaPositionL; trans.Translate(rootMotionDeltaPosition - oldPos, Space.World); totalFrameCount = 0; } } rootMotionFrameIndex = frameIndex; } //if (doRotate) //{ // transform.rotation *= frame.rootMotionDeltaRotation; //} }
private void UpdateMaterial(float deltaTime) { int frameIndex = GetFrameIndex(); if (lastPlayingClip == playingClip && lastPlayingFrameIndex == frameIndex) { return; } lastPlayingClip = playingClip; lastPlayingFrameIndex = frameIndex; bool isCrossBlending = IsCrossFadeBlending(lastPlayedClip, crossFadeTime, crossFadeProgress); int frameIndexCrossFade = -1; GPUSkinFrame frameCrossFade = null; float crossFadeBlendFactor = 1; bool isRootMotion = playingClip.rootMotionEnabled && RootMotionEnabled; GPUSkinFrame frame = playingClip.frames[frameIndex]; if (isCrossBlending) { frameIndexCrossFade = GetCrossFadeFrameIndex(); frameCrossFade = lastPlayedClip.frames[frameIndexCrossFade]; crossFadeBlendFactor = Mathf.Clamp01(crossFadeProgress / crossFadeTime); } if (Visible || CullingMode == GPUSkinCullingMode.AlwaysAnimate) { mpb.SetVector(shaderPorpID_GPUSkin_FrameIndex_PixelSegmentation, new Vector4(frameIndex, playingClip.pixelSegmentation, 0, 0)); if (isRootMotion) { Matrix4x4 rootMotionInv = animData.rootTransformMatrix * frame.RootMotionInv(animData.rootBoneIndex); //Matrix4x4 rootMotionInv = frame.RootMotionInv(animData.rootBoneIndex); mpb.SetMatrix(shaderPorpID_GPUSkin_RootMotion, rootMotionInv); } else { mpb.SetMatrix(shaderPorpID_GPUSkin_RootMotion, Matrix4x4.identity); } if (isCrossBlending) { mpb.SetVector(shaderPorpID_GPUSkin_FrameIndex_PixelSegmentation_Blend_CrossFade, new Vector4(frameIndexCrossFade, lastPlayedClip.pixelSegmentation, crossFadeBlendFactor)); } else { mpb.SetVector(shaderPorpID_GPUSkin_FrameIndex_PixelSegmentation_Blend_CrossFade, new Vector4(0, 0, 1)); } meshRender.SetPropertyBlock(mpb); } if (isRootMotion && deltaTime > 0) { if (CullingMode != GPUSkinCullingMode.CullCompletely) { DoRootMotion(deltaTime); } } }
private IEnumerator SamplingCoroutine(GPUSkinFrame frame, int totalFrames) { yield return(new WaitForEndOfFrame()); List <GPUSkinBone> bones = gpuSkinAnimData.bones; int numBones = bones.Count; for (int i = 0; i < numBones; ++i) { Transform boneTransform = bones[i].transform; GPUSkinBone currentBone = GetBoneByTransform(boneTransform); frame.matrices[i] = Matrix4x4.identity;// currentBone.bindpose; do { Matrix4x4 mat = Matrix4x4.TRS(currentBone.transform.localPosition, currentBone.transform.localRotation, currentBone.transform.localScale); frame.matrices[i] = mat * frame.matrices[i]; if (currentBone.parentBoneIndex == -1) { break; } else { currentBone = bones[currentBone.parentBoneIndex]; } }while (true); } int rootBoneIndex = gpuSkinAnimData.rootBoneIndex; if (samplingFrameIndex == 0) { rootMotionPosition = bones[rootBoneIndex].transform.localPosition; rootMotionRotation = bones[rootBoneIndex].transform.localRotation; } else { Vector3 newPosition = bones[rootBoneIndex].transform.localPosition; Quaternion newRotation = bones[rootBoneIndex].transform.localRotation; Vector3 deltaPosition = newPosition - rootMotionPosition; frame.rootMotionDeltaPositionQ = Quaternion.Inverse(Quaternion.Euler(transform.forward.normalized)) * Quaternion.Euler(deltaPosition.normalized); frame.rootMotionDeltaPositionL = deltaPosition.magnitude; frame.rootMotionDeltaRotation = Quaternion.Inverse(rootMotionRotation) * newRotation; if (samplingFrameIndex == 1) { gpuSkinClip.frames[0].rootMotionDeltaPositionQ = gpuSkinClip.frames[1].rootMotionDeltaPositionQ; gpuSkinClip.frames[0].rootMotionDeltaPositionL = gpuSkinClip.frames[1].rootMotionDeltaPositionL; gpuSkinClip.frames[0].rootMotionDeltaRotation = gpuSkinClip.frames[1].rootMotionDeltaRotation; } } ++samplingFrameIndex; }
public static Texture2D CreateTexture2D(GPUSkinAnimationData animData, out Color[] pixels) { pixels = null; if (animData == null) { return(null); } if (SystemInfo.SupportsTextureFormat(TextureFormat.RGBAHalf)) { if (!bSwitchGpuSkinFloatTexture) { Shader.EnableKeyword("GPUSKIN_SUPPORT_FLOAT_TEXTURE"); Shader.DisableKeyword("GPUSKIN_NOSUPPORT_FLOAT_TEXTURE"); bSwitchGpuSkinFloatTexture = true; } Texture2D texture = new Texture2D(animData.textureWidth, animData.textureHeight, TextureFormat.RGBAHalf, false, true); texture.name = "GPUSkinTextureMatrix"; texture.filterMode = FilterMode.Point; pixels = texture.GetPixels(); int pixelIndex = 0; int clipCount = animData.clips.Count; for (int clipIndex = 0; clipIndex < clipCount; ++clipIndex) { GPUSkinClip clip = animData.clips[clipIndex]; var frames = clip.frames; int numFrames = frames.Length; for (int frameIndex = 0; frameIndex < numFrames; ++frameIndex) { GPUSkinFrame frame = frames[frameIndex]; Matrix4x4[] matrices = frame.matrices; int numMatrices = matrices.Length; for (int matrixIndex = 0; matrixIndex < numMatrices; ++matrixIndex) { Matrix4x4 matrix = matrices[matrixIndex]; pixels[pixelIndex++] = new Color(matrix.m00, matrix.m01, matrix.m02, matrix.m03); pixels[pixelIndex++] = new Color(matrix.m10, matrix.m11, matrix.m12, matrix.m13); pixels[pixelIndex++] = new Color(matrix.m20, matrix.m21, matrix.m22, matrix.m23); } } } texture.SetPixels(pixels, 0); texture.Apply(false); return(texture); } else if (SystemInfo.SupportsTextureFormat(TextureFormat.RGBA32)) { if (!bSwitchGpuSkinFloatTexture) { Shader.EnableKeyword("GPUSKIN_NOSUPPORT_FLOAT_TEXTURE"); Shader.DisableKeyword("GPUSKIN_SUPPORT_FLOAT_TEXTURE"); bSwitchGpuSkinFloatTexture = true; } Texture2D texture = new Texture2D(animData.textureWidth * 2, animData.textureHeight, TextureFormat.RGBA32, false, true); texture.name = "GPUSkinTextureMatrix"; texture.filterMode = FilterMode.Point; pixels = texture.GetPixels(); int pixelIndex = 0; int clipCount = animData.clips.Count; for (int clipIndex = 0; clipIndex < clipCount; ++clipIndex) { GPUSkinClip clip = animData.clips[clipIndex]; var frames = clip.frames; int numFrames = frames.Length; for (int frameIndex = 0; frameIndex < numFrames; ++frameIndex) { GPUSkinFrame frame = frames[frameIndex]; Matrix4x4[] matrices = frame.matrices; int numMatrices = matrices.Length; for (int matrixIndex = 0; matrixIndex < numMatrices; ++matrixIndex) { Matrix4x4 matrix = matrices[matrixIndex]; pixels[pixelIndex++] = Float2ToColor(matrix.m00, matrix.m01); pixels[pixelIndex++] = Float2ToColor(matrix.m02, matrix.m03); pixels[pixelIndex++] = Float2ToColor(matrix.m10, matrix.m11); pixels[pixelIndex++] = Float2ToColor(matrix.m12, matrix.m13); pixels[pixelIndex++] = Float2ToColor(matrix.m20, matrix.m21); pixels[pixelIndex++] = Float2ToColor(matrix.m22, matrix.m23); } } } texture.SetPixels(pixels, 0); texture.Apply(false); return(texture); } return(null); }
private void Update() { if (!isSampling) { return; } int totalFrams = (int)(gpuSkinClip.length * gpuSkinClip.frameRate); samplingTotalFrams = totalFrams; if (samplingFrameIndex >= totalFrams) { if (animator != null) { animator.StopPlayback(); } string savePath = null; if (animData == null) { savePath = EditorUtility.SaveFolderPanel("GPUSkinning Animation Data Save", GetUserPreferDir(), string.Empty); } else { string animPath = AssetDatabase.GetAssetPath(animData); savePath = new FileInfo(animPath).Directory.FullName.Replace('\\', '/'); } if (!string.IsNullOrEmpty(savePath)) { if (!savePath.Contains(Application.dataPath.Replace('\\', '/'))) { ShowDialog("Must select a directory in the project's Asset folder."); } else { SaveUserPreferDir(savePath); string dir = "Assets" + savePath.Substring(Application.dataPath.Length); string savedAnimPath = dir + "/GPUSKinAnimData_" + animName + ".asset"; SetTextureInfo(gpuSkinAnimData); EditorUtility.SetDirty(gpuSkinAnimData); if (animData != gpuSkinAnimData) { AssetDatabase.CreateAsset(gpuSkinAnimData, savedAnimPath); } WriteTempData(TEMP_SAVED_ANIM_PATH, savedAnimPath); animData = gpuSkinAnimData; if (samplingClipIndex == 0) { Mesh newMesh = CreateNewMesh(smr.sharedMesh, "GPUSkinMesh"); if (savedMesh != null) { newMesh.bounds = savedMesh.bounds; } string savedMeshPath = dir + "/GPUSKinMesh_" + animName + ".asset"; AssetDatabase.CreateAsset(newMesh, savedMeshPath); WriteTempData(TEMP_SAVED_MESH_PATH, savedMeshPath); savedMesh = newMesh; // CreateShaderAndMaterial(dir); // CreateLODMeshes(newMesh.bounds, dir); } AssetDatabase.Refresh(); AssetDatabase.SaveAssets(); } } isSampling = false; return; } float time = gpuSkinClip.length * ((float)samplingFrameIndex / totalFrams); GPUSkinFrame frame = new GPUSkinFrame(); gpuSkinClip.frames[samplingFrameIndex] = frame; frame.matrices = new Matrix4x4[gpuSkinAnimData.bones.Count]; if (animation == null) { animator.playbackTime = time; animator.Update(0); } else { animation.Stop(); AnimationState animState = animation[animClip.name]; if (animState != null) { animState.time = time; animation.Sample(); animation.Play(); } } StartCoroutine(SamplingCoroutine(frame, totalFrams)); }