private int BoneAnimationFrameIndexOf(GPUSkinning_BoneAnimationFrame frame, GPUSkinning_Bone bone) { GPUSkinning_Bone[] bones = frame.bones; int numBones = bones.Length; for (int i = 0; i < numBones; ++i) { if (bones[i] == bone) { return(i); } } return(-1); }
private void UpdateBoneTransformMatrix(GPUSkinning_Bone bone, Matrix4x4 parentMatrix, GPUSkinning_BoneAnimationFrame frame) { int index = BoneAnimationFrameIndexOf(frame, bone); Matrix4x4 mat = parentMatrix * frame.matrices[index]; bone.animationMatrix = mat * bone.bindpose; GPUSkinning_Bone[] children = bone.children; int numChildren = children.Length; for (int i = 0; i < numChildren; ++i) { UpdateBoneTransformMatrix(children[i], mat, frame); } }
private string GetBoneHierarchyName(GPUSkinning_Bone bone) { string str = string.Empty; GPUSkinning_Bone currentBone = bone; while (currentBone != null) { if (str == string.Empty) { str = currentBone.name; } else { str = currentBone.name + "/" + str; } currentBone = currentBone.parent; } return(str); }
public GPUSkinning_Bone GetBoneByHierarchyName(string hierarchyName) { System.Func <GPUSkinning_Bone, string, GPUSkinning_Bone> Search = null; Search = (bone, name) => { if (name == hierarchyName) { return(bone); } foreach (GPUSkinning_Bone child in bone.children) { GPUSkinning_Bone result = Search(child, name + "/" + child.name); if (result != null) { return(result); } } return(null); }; return(Search(bones[rootBoneIndex], bones[rootBoneIndex].name)); }
public override void Init(GPUSkinning gpuSkinning) { base.Init(gpuSkinning); shaderPropID_Time = Shader.PropertyToID("_GameTime"); smr = gpuSkinning.GetComponentInChildren <SkinnedMeshRenderer>(); mesh = smr.sharedMesh; // Init Bones int numBones = smr.bones.Length; bones = new GPUSkinning_Bone[numBones]; for (int i = 0; i < numBones; ++i) { GPUSkinning_Bone bone = new GPUSkinning_Bone(); bones[i] = bone; bone.transform = smr.bones[i]; bone.name = bone.transform.gameObject.name; bone.bindpose = mesh.bindposes[i] /*smr to bone*/; } // Construct Hierarchy for (int i = 0; i < numBones; ++i) { if (bones[i].transform == smr.rootBone) { rootBoneIndex = i; break; } } System.Action <GPUSkinning_Bone> CollectChildren = null; CollectChildren = (currentBone) => { List <GPUSkinning_Bone> children = new List <GPUSkinning_Bone>(); for (int j = 0; j < currentBone.transform.childCount; ++j) { Transform childTransform = currentBone.transform.GetChild(j); GPUSkinning_Bone childBone = GetBoneByTransform(childTransform); if (childBone != null) { childBone.parent = currentBone; children.Add(childBone); CollectChildren(childBone); } } currentBone.children = children.ToArray(); }; CollectChildren(bones[rootBoneIndex]); // New MeshFilter MeshRenderer mf = gpuSkinning.gameObject.AddComponent <MeshFilter>(); mr = gpuSkinning.gameObject.AddComponent <MeshRenderer>(); newMtrl = new Material(Shader.Find("Unlit/GPUSkinning")); newMtrl.CopyPropertiesFromMaterial(smr.sharedMaterial); mr.sharedMaterial = newMtrl; // New Mesh newMesh = new Mesh(); newMesh.vertices = mesh.vertices; newMesh.tangents = GPUSkinningUtil.ExtractBoneWeights(mesh); newMesh.uv = mesh.uv; newMesh.triangles = mesh.triangles; mf.sharedMesh = newMesh; #if UNITY_EDITOR // Extract bone animation data int boneAnimationsCount = 0; boneAnimations = new GPUSkinning_BoneAnimation[gpuSkinning.GetComponent <Animator>().runtimeAnimatorController.animationClips.Length]; foreach (AnimationClip animClip in gpuSkinning.GetComponent <Animator>().runtimeAnimatorController.animationClips) { GPUSkinning_BoneAnimation boneAnimation = ScriptableObject.CreateInstance <GPUSkinning_BoneAnimation>(); boneAnimation.fps = 60; boneAnimation.animName = animClip.name; boneAnimation.frames = new GPUSkinning_BoneAnimationFrame[(int)(animClip.length * boneAnimation.fps)]; boneAnimation.length = animClip.length; boneAnimations[boneAnimationsCount++] = boneAnimation; for (int frameIndex = 0; frameIndex < boneAnimation.frames.Length; ++frameIndex) { GPUSkinning_BoneAnimationFrame frame = new GPUSkinning_BoneAnimationFrame(); boneAnimation.frames[frameIndex] = frame; float second = (float)(frameIndex) / (float)boneAnimation.fps; List <GPUSkinning_Bone> bones2 = new List <GPUSkinning_Bone>(); List <Matrix4x4> matrices = new List <Matrix4x4>(); List <string> bonesHierarchyNames = null; if (boneAnimation.bonesHierarchyNames == null) { bonesHierarchyNames = new List <string>(); } EditorCurveBinding[] curvesBinding = AnimationUtility.GetCurveBindings(animClip); foreach (var curveBinding in curvesBinding) { GPUSkinning_Bone bone = GetBoneByHierarchyName(curveBinding.path); if (bones2.Contains(bone)) { continue; } bones2.Add(bone); if (bonesHierarchyNames != null) { bonesHierarchyNames.Add(GetBoneHierarchyName(bone)); } AnimationCurve curveRX = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.x"); AnimationCurve curveRY = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.y"); AnimationCurve curveRZ = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.z"); AnimationCurve curveRW = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.w"); AnimationCurve curvePX = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.x"); AnimationCurve curvePY = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.y"); AnimationCurve curvePZ = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.z"); float curveRX_v = curveRX.Evaluate(second); float curveRY_v = curveRY.Evaluate(second); float curveRZ_v = curveRZ.Evaluate(second); float curveRW_v = curveRW.Evaluate(second); float curvePX_v = curvePX.Evaluate(second); float curvePY_v = curvePY.Evaluate(second); float curvePZ_v = curvePZ.Evaluate(second); Vector3 translation = new Vector3(curvePX_v, curvePY_v, curvePZ_v); Quaternion rotation = new Quaternion(curveRX_v, curveRY_v, curveRZ_v, curveRW_v); NormalizeQuaternion(ref rotation); matrices.Add( Matrix4x4.TRS(translation, rotation, Vector3.one) ); } frame.bones = bones2.ToArray(); frame.matrices = matrices.ToArray(); if (boneAnimation.bonesHierarchyNames == null) { boneAnimation.bonesHierarchyNames = bonesHierarchyNames.ToArray(); } } } // Save as ScriptableObject AssetDatabase.CreateAsset(boneAnimations[0], "Assets/GPUSkinning/Resources/anim0.asset"); AssetDatabase.Refresh(); #else // Read from ScriptableObject directly boneAnimations = new GPUSkinning_BoneAnimation[] { Resources.Load("anim0") as GPUSkinning_BoneAnimation }; foreach (var boneAnimation in boneAnimations) { foreach (var frame in boneAnimation.frames) { int numBones2 = boneAnimation.bonesHierarchyNames.Length; frame.bones = new GPUSkinning_Bone[numBones2]; for (int i = 0; i < numBones2; ++i) { frame.bones[i] = GetBoneByHierarchyName(boneAnimation.bonesHierarchyNames[i]); } } } #endif // Spawn many models if (spawnPoints != null) { List <GPUSkinning_SpawnObject> list = new List <GPUSkinning_SpawnObject>(); for (int i = 0; i < spawnPoints.Length; ++i) { for (int j = 0; j < spawnPoints[i].childCount; ++j) { GPUSkinning_SpawnObject spawnObject = new GPUSkinning_SpawnObject(); list.Add(spawnObject); spawnObject.transform = spawnPoints[i].GetChild(j); spawnObject.mf = spawnObject.transform.gameObject.AddComponent <MeshFilter>(); spawnObject.mr = spawnObject.transform.gameObject.AddComponent <MeshRenderer>(); spawnObject.mr.sharedMaterial = newMtrl; spawnObject.mf.sharedMesh = newMesh; } } spawnObjects = list.ToArray(); } }
public void Update() { if (!isDrawing) { return; } if (bone == null) { bone = gpuSkinning.model.GetBoneByHierarchyName(jointPath); if (bone != null) { boneIndex = System.Array.IndexOf(gpuSkinning.model.bones, bone); } } if (bone == null) { return; } if (instancingMatrices == null) { instancingMatrices = new Matrix4x4[gpuSkinning.model.spawnObjects.Length]; playMode0_mpb = new MaterialPropertyBlock(); hierarchyToObjectMatrices = new Matrix4x4[gpuSkinning.model.spawnObjects.Length]; playMode1_mpb = new MaterialPropertyBlock(); } if (gpuSkinning.playingMode.IsPlayMode0()) { Matrix4x4 hierarchyToObject = bone.hierarchyMatrix * localMatrix; var spawnObjects = gpuSkinning.model.spawnObjects; int numSpawnObjects = spawnObjects == null ? 0 : spawnObjects.Length; for (int i = 0; i < numSpawnObjects; ++i) { var spawnObject = spawnObjects[i]; // (1) // I think "transform.hasChanged" is not a reliable api in a complex case, it would be better to write your own game logic instead. if (spawnObject.transform.hasChanged) { spawnObject.transform.hasChanged = false; // (2) // Huge amount of accessing "transform.localToWorldMatrix" will spend much cpu time, so cache these in a buffer, updating once data is dirty. instancingMatrices[i] = spawnObject.transform.localToWorldMatrix; } if (!isBuiltInDrawMeshInstancedSupported || !gpuSkinning.instancing.IsGPUInstancingOn()) { // (3) // Matrix multiplication is a slow operation. Optimize it. Matrix4x4 hierarchyToWorld = instancingMatrices[i] * hierarchyToObject; // (4) // Invoke many times of "Graphics.DrawMesh" api will cause performance impact. // So "Graphics.DrawMesh" is not better than MeshRenderer in some cases. // Here is just a example for joint. Overhead should be considered in production. Graphics.DrawMesh(mesh, hierarchyToWorld, material, 0); } } if (isBuiltInDrawMeshInstancedSupported && gpuSkinning.instancing.IsGPUInstancingOn()) { playMode0_mpb.SetMatrix(shaderPropId_HierarchyToObjectMat, hierarchyToObject); #if UNITY_5_5 || UNITY_5_6 || UNITY_5_7 || UNITY_5_8 || UNITY_5_9 || UNITY_6 || UNITY_2017 || UNITY_2018 // etc. // (5) // https://forum.unity3d.com/threads/graphics-drawmesh-drawmeshinstanced-fundamentally-bottlenecked-by-the-cpu.429120/ Graphics.DrawMeshInstanced(mesh, 0, material, instancingMatrices, numSpawnObjects, playMode0_mpb); #endif } } else { var spawnObjects = gpuSkinning.model.spawnObjects; int numSpawnObjects = spawnObjects == null ? 0 : spawnObjects.Length; bool isInstancingOn = gpuSkinning.instancing.IsGPUInstancingOn(); int fps = gpuSkinning.model.boneAnimations[0].fps; float animLength = gpuSkinning.model.boneAnimations[0].length; for (int i = 0; i < numSpawnObjects; ++i) { var spawnObject = spawnObjects[i]; // (1) if (spawnObject.transform.hasChanged) { spawnObject.transform.hasChanged = false; // (2) instancingMatrices[i] = spawnObject.transform.localToWorldMatrix; } float timeOffset = isInstancingOn ? spawnObject.timeOffset_instancingOn : spawnObject.timeOffset_instancingOff; int frameIndex = (int)(((gpuSkinning.second + timeOffset) * fps) % (animLength * fps)); int frameStartIndex = frameIndex * gpuSkinning.matrixTexture.numHierarchyMatricesPerFrame; Matrix4x4 hierarchyToObject = gpuSkinning.matrixTexture.hierarchyMatrices[frameStartIndex + boneIndex]; if (!isBuiltInDrawMeshInstancedSupported || !gpuSkinning.instancing.IsGPUInstancingOn()) { // (3) Matrix4x4 hierarchyToWorld = instancingMatrices[i] * hierarchyToObject * localMatrix; // (4) Graphics.DrawMesh(mesh, hierarchyToWorld, material, 0); } else { hierarchyToObjectMatrices[i] = hierarchyToObject; } } if (isBuiltInDrawMeshInstancedSupported && gpuSkinning.instancing.IsGPUInstancingOn()) { playMode1_mpb.SetMatrixArray(shaderPorpId_HierarchyToObjectMats, hierarchyToObjectMatrices); playMode1_mpb.SetMatrix(shaderPropId_JointLocalMatrix, localMatrix); #if UNITY_5_5 || UNITY_5_6 || UNITY_5_7 || UNITY_5_8 || UNITY_5_9 || UNITY_6 || UNITY_2017 || UNITY_2018 // etc. // (5) Graphics.DrawMeshInstanced(mesh, 0, material, instancingMatrices, numSpawnObjects, playMode1_mpb); #endif } } }
private void Start() { shaderPropID_Matrices = Shader.PropertyToID("_Matrices"); smr = GetComponentInChildren <SkinnedMeshRenderer>(); mesh = smr.sharedMesh; // Init Bones int numBones = smr.bones.Length; bones = new GPUSkinning_Bone[numBones]; for (int i = 0; i < numBones; ++i) { GPUSkinning_Bone bone = new GPUSkinning_Bone(); bones[i] = bone; bone.transform = smr.bones[i]; bone.bindpose = mesh.bindposes[i] /*smr to bone*/; } matricesUniformBlock = new Matrix4x4[numBones]; // Construct Bones' Hierarchy for (int i = 0; i < numBones; ++i) { if (bones[i].transform == smr.rootBone) { rootBoneIndex = i; break; } } System.Action <GPUSkinning_Bone> CollectChildren = null; CollectChildren = (currentBone) => { List <GPUSkinning_Bone> children = new List <GPUSkinning_Bone>(); for (int j = 0; j < currentBone.transform.childCount; ++j) { Transform childTransform = currentBone.transform.GetChild(j); GPUSkinning_Bone childBone = GetBoneByTransform(childTransform); if (childBone != null) { childBone.parent = currentBone; children.Add(childBone); CollectChildren(childBone); } } currentBone.children = children.ToArray(); }; CollectChildren(bones[rootBoneIndex]); // New MeshFilter MeshRenderer mf = gameObject.AddComponent <MeshFilter>(); mr = gameObject.AddComponent <MeshRenderer>(); newMtrl = new Material(Shader.Find("Unlit/GPUSkinning")); newMtrl.CopyPropertiesFromMaterial(smr.sharedMaterial); mr.sharedMaterial = newMtrl; // Fetch bone-weight storing as tangents int numVertices = mesh.vertexCount; Vector4[] tangents = new Vector4[mesh.vertexCount]; Vector4[] uv2 = new Vector4[numVertices]; Vector4[] uv3 = new Vector4[numVertices]; for (int i = 0; i < numVertices; ++i) { BoneWeight boneWeight = mesh.boneWeights[i]; tangents[i].x = boneWeight.boneIndex0; tangents[i].y = boneWeight.weight0; tangents[i].z = boneWeight.boneIndex1; tangents[i].w = boneWeight.weight1; Vector4 skinData_01 = new Vector4(); skinData_01.x = boneWeight.boneIndex0; skinData_01.y = boneWeight.weight0; skinData_01.z = boneWeight.boneIndex1; skinData_01.w = boneWeight.weight1; uv2[i] = skinData_01; Vector4 skinData_23 = new Vector4(); skinData_23.x = boneWeight.boneIndex2; skinData_23.y = boneWeight.weight2; skinData_23.z = boneWeight.boneIndex3; skinData_23.w = boneWeight.weight3; uv3[i] = skinData_23; } // New Mesh newMesh = new Mesh(); newMesh.vertices = mesh.vertices; newMesh.normals = mesh.normals; newMesh.tangents = tangents; newMesh.uv = mesh.uv; newMesh.triangles = mesh.triangles; mf.sharedMesh = newMesh; newMesh.SetUVs(1, new List <Vector4>(uv2)); newMesh.SetUVs(2, new List <Vector4>(uv3)); /* * // Fetch animations' data #if UNITY_EDITOR * int boneAnimationsCount = 0; * boneAnimations = new GPUSkinning_BoneAnimation[GetComponent<Animator>().runtimeAnimatorController.animationClips.Length]; * foreach(AnimationClip animClip in GetComponent<Animator>().runtimeAnimatorController.animationClips) * { * GPUSkinning_BoneAnimation boneAnimation = ScriptableObject.CreateInstance<GPUSkinning_BoneAnimation>(); * boneAnimation.fps = 30; * boneAnimation.animName = animClip.name; * boneAnimation.frames = new GPUSkinning_BoneAnimationFrame[(int)(animClip.length * boneAnimation.fps)]; * boneAnimation.length = animClip.length; * boneAnimations[boneAnimationsCount++] = boneAnimation; * * for(int frameIndex = 0; frameIndex < boneAnimation.frames.Length; ++frameIndex) * { * GPUSkinning_BoneAnimationFrame frame = new GPUSkinning_BoneAnimationFrame(); * boneAnimation.frames[frameIndex] = frame; * float second = (float)(frameIndex) / (float)boneAnimation.fps; * * List<GPUSkinning_Bone> bones2 = new List<GPUSkinning_Bone>(); * List<Matrix4x4> matrices = new List<Matrix4x4>(); * List<string> bonesHierarchyNames = new List<string>(); * EditorCurveBinding[] curvesBinding = AnimationUtility.GetCurveBindings(animClip); * foreach(var curveBinding in curvesBinding) * { * GPUSkinning_Bone bone = GetBoneByHierarchyName(curveBinding.path); * * if(bones2.Contains(bone)) * { * continue; * } * bones2.Add(bone); * * bonesHierarchyNames.Add(GetBoneHierarchyName(bone)); * * AnimationCurve curveRX = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.x"); * AnimationCurve curveRY = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.y"); * AnimationCurve curveRZ = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.z"); * AnimationCurve curveRW = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.w"); * * AnimationCurve curvePX = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.x"); * AnimationCurve curvePY = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.y"); * AnimationCurve curvePZ = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.z"); * * float curveRX_v = curveRX.Evaluate(second); * float curveRY_v = curveRY.Evaluate(second); * float curveRZ_v = curveRZ.Evaluate(second); * float curveRW_v = curveRW.Evaluate(second); * * float curvePX_v = curvePX.Evaluate(second); * float curvePY_v = curvePY.Evaluate(second); * float curvePZ_v = curvePZ.Evaluate(second); * * Vector3 translation = new Vector3(curvePX_v, curvePY_v, curvePZ_v); * Quaternion rotation = new Quaternion(curveRX_v, curveRY_v, curveRZ_v, curveRW_v); * NormalizeQuaternion(ref rotation); * matrices.Add( * Matrix4x4.TRS(translation, rotation, Vector3.one) * ); * } * * frame.bones = bones2.ToArray(); * frame.matrices = matrices.ToArray(); * frame.bonesHierarchyNames = bonesHierarchyNames.ToArray(); * } * } * AssetDatabase.CreateAsset(boneAnimations[0], "Assets/GPUSkinning/Resources/anim0.asset"); * AssetDatabase.Refresh(); #else * boneAnimations = new GPUSkinning_BoneAnimation[] { Resources.Load("anim0") as GPUSkinning_BoneAnimation }; * foreach(var boneAnimation in boneAnimations) * { * foreach(var frame in boneAnimation.frames) * { * int numBones2 = frame.bonesHierarchyNames.Length; * frame.bones = new GPUSkinning_Bone[numBones2]; * for(int i = 0; i < numBones2; ++i) * { * frame.bones[i] = GetBoneByHierarchyName(frame.bonesHierarchyNames[i]); * } * } * } #endif * * * GameObject.Destroy(transform.Find("pelvis").gameObject); * GameObject.Destroy(transform.Find("mutant_mesh").gameObject); * Object.Destroy(gameObject.GetComponent<Animator>()); */ //smr.enabled = false; //PrintBones(); }
private void Start() { shaderPropID_Matrices = Shader.PropertyToID("_Matrices"); shaderPropID_MatricesTex = Shader.PropertyToID("_MatricesTex"); shaderPropID_MatricesTexSize = Shader.PropertyToID("_MatricesTexSize"); shaderPropID_AnimLength = Shader.PropertyToID("_AnimLength"); shaderPropID_AnimFPS = Shader.PropertyToID("_AnimFPS"); shaderPropID_TerrainTex = Shader.PropertyToID("_TerrainTex"); shaderPropID_TerrainSize = Shader.PropertyToID("_TerrainSize"); shaderPropID_TerrainPos = Shader.PropertyToID("_TerrainPos"); shaderPropID_mpb_time = Shader.PropertyToID("_mpb_time"); smr = GetComponentInChildren <SkinnedMeshRenderer>(); mesh = smr.sharedMesh; // 初始化骨骼对象 int numBones = smr.bones.Length; bones = new GPUSkinning_Bone[numBones]; for (int i = 0; i < numBones; ++i) { GPUSkinning_Bone bone = new GPUSkinning_Bone(); bones[i] = bone; bone.transform = smr.bones[i]; bone.bindpose = mesh.bindposes[i] /*smr to bone*/; } matricesUniformBlock = new Matrix4x4[numBones]; // 构建骨骼的层级结构 for (int i = 0; i < numBones; ++i) { if (bones[i].transform == smr.rootBone) { rootBoneIndex = i; break; } } System.Action <GPUSkinning_Bone> CollectChildren = null; CollectChildren = (currentBone) => { List <GPUSkinning_Bone> children = new List <GPUSkinning_Bone>(); for (int j = 0; j < currentBone.transform.childCount; ++j) { Transform childTransform = currentBone.transform.GetChild(j); GPUSkinning_Bone childBone = GetBoneByTransform(childTransform); if (childBone != null) { childBone.parent = currentBone; children.Add(childBone); CollectChildren(childBone); } } currentBone.children = children.ToArray(); }; CollectChildren(bones[rootBoneIndex]); // New MeshFilter MeshRenderer mf = gameObject.AddComponent <MeshFilter>(); mr = gameObject.AddComponent <MeshRenderer>(); newMtrl = new Material(Shader.Find("Unlit/GPUSkinning")); newMtrl.CopyPropertiesFromMaterial(smr.sharedMaterial); mr.sharedMaterial = newMtrl; // 保存骨骼动画权重 Vector4[] tangents = new Vector4[mesh.vertexCount]; for (int i = 0; i < mesh.vertexCount; ++i) { BoneWeight boneWeight = mesh.boneWeights[i]; tangents[i].x = boneWeight.boneIndex0; tangents[i].y = boneWeight.weight0; tangents[i].z = boneWeight.boneIndex1; tangents[i].w = boneWeight.weight1; } // New Mesh newMesh = new Mesh(); newMesh.vertices = mesh.vertices; newMesh.tangents = tangents; newMesh.uv = mesh.uv; newMesh.triangles = mesh.triangles; mf.sharedMesh = newMesh; // 为每个角色生成差异化数据 if (IsMatricesTextureSupported()) { additionalVertexStreames = new Mesh[50]; for (int i = 0; i < additionalVertexStreames.Length; ++i) { Mesh m = new Mesh(); float rnd = Random.Range(0.0f, 10.0f); Vector2[] uv2 = new Vector2[mesh.vertexCount]; for (int j = 0; j < mesh.vertexCount; ++j) { Vector2 uv = Vector2.zero; uv.x = rnd; uv2[j] = uv; } m.vertices = newMesh.vertices; m.uv2 = uv2; m.UploadMeshData(true); additionalVertexStreames[i] = m; } mr.additionalVertexStreams = additionalVertexStreames[0]; } #if UNITY_EDITOR // 从 Unity 的 Animation 中提取骨骼动画所需要的数据 int boneAnimationsCount = 0; boneAnimations = new GPUSkinning_BoneAnimation[GetComponent <Animator>().runtimeAnimatorController.animationClips.Length]; foreach (AnimationClip animClip in GetComponent <Animator>().runtimeAnimatorController.animationClips) { GPUSkinning_BoneAnimation boneAnimation = ScriptableObject.CreateInstance <GPUSkinning_BoneAnimation>(); boneAnimation.fps = 60; boneAnimation.animName = animClip.name; boneAnimation.frames = new GPUSkinning_BoneAnimationFrame[(int)(animClip.length * boneAnimation.fps)]; boneAnimation.length = animClip.length; boneAnimations[boneAnimationsCount++] = boneAnimation; for (int frameIndex = 0; frameIndex < boneAnimation.frames.Length; ++frameIndex) { GPUSkinning_BoneAnimationFrame frame = new GPUSkinning_BoneAnimationFrame(); boneAnimation.frames[frameIndex] = frame; float second = (float)(frameIndex) / (float)boneAnimation.fps; List <GPUSkinning_Bone> bones2 = new List <GPUSkinning_Bone>(); List <Matrix4x4> matrices = new List <Matrix4x4>(); List <string> bonesHierarchyNames = null; if (boneAnimation.bonesHierarchyNames == null) { bonesHierarchyNames = new List <string>(); } EditorCurveBinding[] curvesBinding = AnimationUtility.GetCurveBindings(animClip); foreach (var curveBinding in curvesBinding) { GPUSkinning_Bone bone = GetBoneByHierarchyName(curveBinding.path); if (bones2.Contains(bone)) { continue; } bones2.Add(bone); if (bonesHierarchyNames != null) { bonesHierarchyNames.Add(GetBoneHierarchyName(bone)); } AnimationCurve curveRX = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.x"); AnimationCurve curveRY = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.y"); AnimationCurve curveRZ = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.z"); AnimationCurve curveRW = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.w"); AnimationCurve curvePX = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.x"); AnimationCurve curvePY = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.y"); AnimationCurve curvePZ = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.z"); float curveRX_v = curveRX.Evaluate(second); float curveRY_v = curveRY.Evaluate(second); float curveRZ_v = curveRZ.Evaluate(second); float curveRW_v = curveRW.Evaluate(second); float curvePX_v = curvePX.Evaluate(second); float curvePY_v = curvePY.Evaluate(second); float curvePZ_v = curvePZ.Evaluate(second); Vector3 translation = new Vector3(curvePX_v, curvePY_v, curvePZ_v); Quaternion rotation = new Quaternion(curveRX_v, curveRY_v, curveRZ_v, curveRW_v); NormalizeQuaternion(ref rotation); matrices.Add( Matrix4x4.TRS(translation, rotation, Vector3.one) ); } frame.bones = bones2.ToArray(); frame.matrices = matrices.ToArray(); if (boneAnimation.bonesHierarchyNames == null) { boneAnimation.bonesHierarchyNames = bonesHierarchyNames.ToArray(); } } } AssetDatabase.CreateAsset(boneAnimations[0], "Assets/GPUSkinning/Resources/anim0.asset"); AssetDatabase.Refresh(); #else // 直接读取序列化的骨骼动画数据 boneAnimations = new GPUSkinning_BoneAnimation[] { Resources.Load("anim0") as GPUSkinning_BoneAnimation }; foreach (var boneAnimation in boneAnimations) { foreach (var frame in boneAnimation.frames) { int numBones2 = boneAnimation.bonesHierarchyNames.Length; frame.bones = new GPUSkinning_Bone[numBones2]; for (int i = 0; i < numBones2; ++i) { frame.bones[i] = GetBoneByHierarchyName(boneAnimation.bonesHierarchyNames[i]); } } } #endif // 创建出更多的角色模型 if (spawnPoints != null) { List <GPUSkinning_SpawnObject> list = new List <GPUSkinning_SpawnObject>(); for (int i = 0; i < spawnPoints.Length; ++i) { for (int j = 0; j < spawnPoints[i].childCount; ++j) { GPUSkinning_SpawnObject spawnObject = new GPUSkinning_SpawnObject(); list.Add(spawnObject); spawnObject.transform = spawnPoints[i].GetChild(j); spawnObject.mf = spawnObject.transform.gameObject.AddComponent <MeshFilter>(); spawnObject.mr = spawnObject.transform.gameObject.AddComponent <MeshRenderer>(); spawnObject.mr.sharedMaterial = newMtrl; spawnObject.mf.sharedMesh = newMesh; if (additionalVertexStreames != null) { // 当开启 GPUInstancing 时,这个是不需要的,偷懒就直接设置了 spawnObject.mr.additionalVertexStreams = additionalVertexStreames[Random.Range(0, additionalVertexStreames.Length)]; } } } spawnObjects = list.ToArray(); } // 销毁并暂停 Unity 的 Animator GameObject.Destroy(transform.FindChild("pelvis").gameObject); GameObject.Destroy(transform.FindChild("mutant_mesh").gameObject); Object.Destroy(gameObject.GetComponent <Animator>()); smr.enabled = false; //PrintBones(); CreateMatricesTexture(); BakeAnimationsToTexture(); SetPlayMode0(); InitTerrain(); SetTerrainHeightSwitch(); InitGPUInstancing(); InitComputeBuffer(newMesh); newMesh.UploadMeshData(true); }