private void CollectBones(List <GPUSkinningBone> bones_result, Transform[] bones_smr, Matrix4x4[] bindposes, GPUSkinningBone parentBone, Transform currentBoneTransform, int currentBoneIndex) { GPUSkinningBone currentBone = new GPUSkinningBone(); bones_result.Add(currentBone); int indexOfSmrBones = System.Array.IndexOf(bones_smr, currentBoneTransform); currentBone.transform = currentBoneTransform; currentBone.name = currentBone.transform.gameObject.name; currentBone.bindpose = indexOfSmrBones == -1 ? Matrix4x4.identity : bindposes[indexOfSmrBones]; currentBone.parentBoneIndex = parentBone == null ? -1 : bones_result.IndexOf(parentBone); if (parentBone != null) { parentBone.childrenBonesIndices[currentBoneIndex] = bones_result.IndexOf(currentBone); } int numChildren = currentBone.transform.childCount; if (numChildren > 0) { currentBone.childrenBonesIndices = new int[numChildren]; for (int i = 0; i < numChildren; ++i) { CollectBones(bones_result, bones_smr, bindposes, currentBone, currentBone.transform.GetChild(i), i); } } }
private void OnGUI_Bone(GPUSkinningBone bone, int indentLevel) { GUILayout.BeginHorizontal(); { for (int i = 0; i < indentLevel; ++i) { GUILayout.Space(20); } EditorGUI.BeginChangeCheck(); bool isExposed = GUILayout.Toggle(bone.isExposed, bone.name); if (EditorGUI.EndChangeCheck()) { bone.isExposed = isExposed; ApplyAnimModification(); } } GUILayout.EndHorizontal(); int numChildren = bone.childrenBonesIndices == null ? 0 : bone.childrenBonesIndices.Length; for (int i = 0; i < numChildren; ++i) { OnGUI_Bone(anim.bones[bone.childrenBonesIndices[i]], indentLevel + 1); } }
private IEnumerator SamplingCoroutine(GPUSkinningFrame frame, int totalFrames) { yield return(new WaitForEndOfFrame()); GPUSkinningBone[] bones = gpuSkinningAnimation.bones; int numBones = bones.Length; for (int i = 0; i < numBones; ++i) { Transform boneTransform = bones[i].transform; GPUSkinningBone currentBone = GetBoneByTransform(boneTransform); frame.matrices[i] = 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); } if (samplingFrameIndex == 0) { rootMotionPosition = bones[gpuSkinningAnimation.rootBoneIndex].transform.localPosition; rootMotionRotation = bones[gpuSkinningAnimation.rootBoneIndex].transform.localRotation; } else { Vector3 newPosition = bones[gpuSkinningAnimation.rootBoneIndex].transform.localPosition; Quaternion newRotation = bones[gpuSkinningAnimation.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; rootMotionPosition = newPosition; rootMotionRotation = newRotation; if (samplingFrameIndex == 1) { gpuSkinningClip.frames[0].rootMotionDeltaPositionQ = gpuSkinningClip.frames[1].rootMotionDeltaPositionQ; gpuSkinningClip.frames[0].rootMotionDeltaPositionL = gpuSkinningClip.frames[1].rootMotionDeltaPositionL; gpuSkinningClip.frames[0].rootMotionDeltaRotation = gpuSkinningClip.frames[1].rootMotionDeltaRotation; } } ++samplingFrameIndex; }
public static string BoneHierarchyPath(GPUSkinningBone[] bones, int boneIndex) { if (bones == null || boneIndex < 0 || boneIndex >= bones.Length) { return(null); } GPUSkinningBone bone = bones[boneIndex]; string path = bone.name; while (bone.parentBoneIndex != -1) { bone = bones[bone.parentBoneIndex]; path = bone.name + "/" + path; } return(path); }
public static void BonesHierarchy_Internal(GPUSkinningAnimation gpuSkinningAnimation, GPUSkinningBone bone, string tabs, ref string str) { str += tabs + bone.name + "\n"; int numChildren = bone.childrenBonesIndices == null ? 0 : bone.childrenBonesIndices.Length; for (int i = 0; i < numChildren; ++i) { BonesHierarchy_Internal(gpuSkinningAnimation, gpuSkinningAnimation.bones[bone.childrenBonesIndices[i]], tabs + " ", ref str); } }
private int GetBoneIndex(GPUSkinningBone bone) { return(System.Array.IndexOf(gpuSkinningAnimation.bones, bone)); }
private Mesh CreateNewMesh(Mesh mesh, string meshName) { Vector3[] normals = mesh.normals; Vector4[] tangents = mesh.tangents; Color[] colors = mesh.colors; Vector2[] uv = mesh.uv; Mesh newMesh = new Mesh(); newMesh.name = meshName; newMesh.vertices = mesh.vertices; if (normals != null && normals.Length > 0) { newMesh.normals = normals; } if (tangents != null && tangents.Length > 0) { newMesh.tangents = tangents; } if (colors != null && colors.Length > 0) { newMesh.colors = colors; } if (uv != null && uv.Length > 0) { newMesh.uv = uv; } int numVertices = mesh.vertexCount; BoneWeight[] boneWeights = mesh.boneWeights; Vector4[] uv2 = new Vector4[numVertices]; Vector4[] uv3 = new Vector4[numVertices]; Transform[] smrBones = smr.bones; for (int i = 0; i < numVertices; ++i) { BoneWeight boneWeight = boneWeights[i]; BoneWeightSortData[] weights = new BoneWeightSortData[4]; weights[0] = new BoneWeightSortData() { index = boneWeight.boneIndex0, weight = boneWeight.weight0 }; weights[1] = new BoneWeightSortData() { index = boneWeight.boneIndex1, weight = boneWeight.weight1 }; weights[2] = new BoneWeightSortData() { index = boneWeight.boneIndex2, weight = boneWeight.weight2 }; weights[3] = new BoneWeightSortData() { index = boneWeight.boneIndex3, weight = boneWeight.weight3 }; System.Array.Sort(weights); GPUSkinningBone bone0 = GetBoneByTransform(smrBones[weights[0].index]); GPUSkinningBone bone1 = GetBoneByTransform(smrBones[weights[1].index]); GPUSkinningBone bone2 = GetBoneByTransform(smrBones[weights[2].index]); GPUSkinningBone bone3 = GetBoneByTransform(smrBones[weights[3].index]); Vector4 skinData_01 = new Vector4(); skinData_01.x = GetBoneIndex(bone0); skinData_01.y = weights[0].weight; skinData_01.z = GetBoneIndex(bone1); skinData_01.w = weights[1].weight; uv2[i] = skinData_01; Vector4 skinData_23 = new Vector4(); skinData_23.x = GetBoneIndex(bone2); skinData_23.y = weights[2].weight; skinData_23.z = GetBoneIndex(bone3); skinData_23.w = weights[3].weight; uv3[i] = skinData_23; } newMesh.SetUVs(1, new List <Vector4>(uv2)); newMesh.SetUVs(2, new List <Vector4>(uv3)); newMesh.triangles = mesh.triangles; return(newMesh); }
private void ConstructJoints() { if (joints == null) { GPUSkinningPlayerJoint[] existingJoints = go.GetComponentsInChildren <GPUSkinningPlayerJoint>(); GPUSkinningBone[] bones = res.anim.bones; int numBones = bones == null ? 0 : bones.Length; for (int i = 0; i < numBones; ++i) { GPUSkinningBone bone = bones[i]; if (bone.isExposed) { if (joints == null) { joints = new List <GPUSkinningPlayerJoint>(); } bool inTheExistingJoints = false; if (existingJoints != null) { for (int j = 0; j < existingJoints.Length; ++j) { if (existingJoints[j] != null && existingJoints[j].BoneGUID == bone.guid) { if (existingJoints[j].BoneIndex != i) { existingJoints[j].Init(i, bone.guid); GPUSkinningUtil.MarkAllScenesDirty(); } joints.Add(existingJoints[j]); existingJoints[j] = null; inTheExistingJoints = true; break; } } } if (!inTheExistingJoints) { GameObject jointGo = new GameObject(bone.name); jointGo.transform.parent = go.transform; jointGo.transform.localPosition = Vector3.zero; jointGo.transform.localScale = Vector3.one; GPUSkinningPlayerJoint joint = jointGo.AddComponent <GPUSkinningPlayerJoint>(); joints.Add(joint); joint.Init(i, bone.guid); GPUSkinningUtil.MarkAllScenesDirty(); } } } if (!Application.isPlaying) { #if UNITY_EDITOR UnityEditor.EditorApplication.CallbackFunction DelayCall = null; DelayCall = () => { UnityEditor.EditorApplication.delayCall -= DelayCall; DeleteInvalidJoints(existingJoints); }; UnityEditor.EditorApplication.delayCall += DelayCall; #endif } else { DeleteInvalidJoints(existingJoints); } } }
private void BakeAllAnimClip(List <AnimationState> curAnims, string path, GameObject go, float frameRate, GameObject rootBone, GPUSkinningBone[] bones) { int curClipFrame = 0; float sampleTime = 0; float perFrameTime = 0; float len = 0; float s = 1; for (int i = 0; i < this.animData.animClips.Count; i++) { if (!this.animData.animClips[i].clip.legacy) { Debug.LogError(string.Format("{0} is not legacy!!", this.animData.animClips[i].clip.name)); continue; } if (this.animData.animClips[i].name.IndexOf("_all") >= 0) { continue; } //前后各加一帧 curClipFrame += Mathf.CeilToInt(curAnims[i].clip.frameRate * curAnims[i].length * s) + 2; } len = curClipFrame / frameRate; int pow1 = Mathf.NextPowerOfTwo(curClipFrame); int width = Mathf.NextPowerOfTwo(bones.Length * 3); Texture2D animMap = new Texture2D(width, pow1, format, false); animMap.wrapMode = TextureWrapMode.Clamp; animMap.filterMode = FilterMode.Point; animMap.name = this.animData.name; int startFrame = 0; for (int i = 0; i < this.animData.animClips.Count; i++) { if (!this.animData.animClips[i].clip.legacy) { Debug.LogError(string.Format("{0} is not legacy!!", this.animData.animClips[i].clip.name)); continue; } if (this.animData.animClips[i].name.IndexOf("_all") >= 0) { continue; } animData.AnimationPlay(curAnims[i].name); sampleTime = 0; int curClipFrame1 = Mathf.CeilToInt(curAnims[i].clip.frameRate * curAnims[i].length * s) + 2; perFrameTime = curAnims[i].length / (curClipFrame1 - 2); for (int k = startFrame; k < curClipFrame1 + startFrame - 2; k++) { if (sampleTime > curAnims[i].length) { sampleTime = curAnims[i].length; } curAnims[i].time = sampleTime; this.animData.animation.Sample(); for (int j = 0; j < bones.Length; j++) { GPUSkinningBone currentBone = bones[j]; Matrix4x4 lastMat = currentBone.bindpose; while (true) { if (currentBone.parentBoneIndex == -1) { Matrix4x4 mat = Matrix4x4.TRS(currentBone.transform.localPosition, currentBone.transform.localRotation, currentBone.transform.localScale); if (rootBone.transform != go.transform) { mat = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, go.transform.localScale) * mat; } lastMat = mat * lastMat; break; } else { Matrix4x4 mat = Matrix4x4.TRS(currentBone.transform.localPosition, currentBone.transform.localRotation, currentBone.transform.localScale); lastMat = mat * lastMat; currentBone = bones[currentBone.parentBoneIndex]; } } animMap.SetPixel(j * 3, k + 1, new Color(lastMat.m00, lastMat.m01, lastMat.m02, lastMat.m03)); animMap.SetPixel(j * 3 + 1, k + 1, new Color(lastMat.m10, lastMat.m11, lastMat.m12, lastMat.m13)); animMap.SetPixel(j * 3 + 2, k + 1, new Color(lastMat.m20, lastMat.m21, lastMat.m22, lastMat.m23)); if (k == startFrame) { animMap.SetPixel(j * 3, k, new Color(lastMat.m00, lastMat.m01, lastMat.m02, lastMat.m03)); animMap.SetPixel(j * 3 + 1, k, new Color(lastMat.m10, lastMat.m11, lastMat.m12, lastMat.m13)); animMap.SetPixel(j * 3 + 2, k, new Color(lastMat.m20, lastMat.m21, lastMat.m22, lastMat.m23)); } else if (k == curClipFrame1 + startFrame - 3) { animMap.SetPixel(j * 3, k + 2, new Color(lastMat.m00, lastMat.m01, lastMat.m02, lastMat.m03)); animMap.SetPixel(j * 3 + 1, k + 2, new Color(lastMat.m10, lastMat.m11, lastMat.m12, lastMat.m13)); animMap.SetPixel(j * 3 + 2, k + 2, new Color(lastMat.m20, lastMat.m21, lastMat.m22, lastMat.m23)); } } sampleTime += perFrameTime; } startFrame += curClipFrame1; } animMap.Apply(); this.bakedDataList.Add(new BakedData(animMap.name, pow1 / frameRate, animMap)); }
public List <BakedData> Bake(GameObject go, GameObject fbx, GameObject rootBone, string path, Dictionary <string, string> dic, ref Mesh tarMesh) { if (this.animData == null) { Debug.LogError("bake data is null!!"); return(this.bakedDataList); } List <GPUSkinningBone> bones_result = new List <GPUSkinningBone>(); SkinnedMeshRenderer skin = animData.skin; CollectBones(bones_result, skin.bones, skin.sharedMesh.bindposes, null, rootBone.transform, 0); GPUSkinningBone[] bones = bones_result.ToArray(); Mesh mesh = new Mesh(); mesh.name = skin.sharedMesh.name; mesh.vertices = skin.sharedMesh.vertices; mesh.normals = skin.sharedMesh.normals; mesh.tangents = skin.sharedMesh.tangents; mesh.uv = skin.sharedMesh.uv; BoneWeight[] boneWeights = skin.sharedMesh.boneWeights; int numVertices = mesh.vertices.Length; Vector4[] uv2 = new Vector4[numVertices]; Vector4[] uv3 = new Vector4[numVertices]; Transform[] smrBones = skin.bones; for (int i = 0; i < mesh.vertices.Length; i++) { BoneWeight weight = boneWeights[i]; BoneWeightSortData[] weights = new BoneWeightSortData[4]; weights[0] = new BoneWeightSortData() { index = weight.boneIndex0, weight = weight.weight0 }; weights[1] = new BoneWeightSortData() { index = weight.boneIndex1, weight = weight.weight1 }; weights[2] = new BoneWeightSortData() { index = weight.boneIndex2, weight = weight.weight2 }; weights[3] = new BoneWeightSortData() { index = weight.boneIndex3, weight = weight.weight3 }; System.Array.Sort(weights); //Debug.Log(weights[0].index + ":" + weights[0].weight + ":" + weights[1].index + ":" + weights[1].weight + ":" + weights[2].index + ":" + weights[2].weight + ":" + weights[3].index + ":" + weights[3].weight); GPUSkinningBone bone0 = GetBoneByTransform(smrBones[weights[0].index], bones); GPUSkinningBone bone1 = GetBoneByTransform(smrBones[weights[1].index], bones); GPUSkinningBone bone2 = GetBoneByTransform(smrBones[weights[2].index], bones); GPUSkinningBone bone3 = GetBoneByTransform(smrBones[weights[3].index], bones); Vector4 skinData_01 = new Vector4(); skinData_01.x = GetBoneIndex(bone0, bones); skinData_01.y = weights[0].weight; skinData_01.z = GetBoneIndex(bone1, bones); skinData_01.w = weights[1].weight; uv2[i] = skinData_01; } mesh.SetUVs(1, new List <Vector4>(uv2)); mesh.triangles = skin.sharedMesh.triangles; AssetDatabase.CreateAsset(mesh, "Assets/" + Path.Combine(path, mesh.name + "mesh.asset")); tarMesh = mesh; BakeAllAnimClip(this.animData.animClips, path, go, 30f, rootBone, bones); Object target = PrefabUtility.GetPrefabParent(fbx); string fbxName = AssetDatabase.GetAssetPath(target); if (target == null) { fbxName = AssetDatabase.GetAssetPath(fbx); } else { fbxName = "Assets/" + path + "/" + fbx.name + ".fbx"; } Debug.Log(fbxName); ModelImporter modelImporter = (ModelImporter)AssetImporter.GetAtPath(fbxName); GenAnimationDataFile(modelImporter.clipAnimations, this.animData.animClips, 30f, go, path, dic); return(this.bakedDataList); }
private int GetBoneIndex(GPUSkinningBone bone, GPUSkinningBone[] bones) { return(System.Array.IndexOf(bones, bone)); }