public void generateTexAndMesh(string parentFolder, string savePath, string dataFileName) { int numBones = animData.totalBoneNum; // 重新生成mesh rebuildAllMeshes(savePath, parentFolder); // 将骨骼矩阵写入纹理 var tex2D = new Texture2D(animData.texWidth, animData.texHeight, TextureFormat.RGBA32, false); tex2D.filterMode = FilterMode.Point; int clipIdx = 0; int pixelIdx = 0; Vector2Int pixelUv; GpuSkinningAnimClip boneAnimation = null; AnimationClip clip = null; List <Matrix4x4> boneMatrices = null; for (clipIdx = 0; clipIdx < animClips.Length; ++clipIdx) { boneAnimation = animData.clips[clipIdx]; clip = animClips[clipIdx]; for (int frameIndex = 0; frameIndex < boneAnimation.Length(); frameIndex++) { boneMatrices = samplerAnimationClipBoneMatrices(curGameObject, clip, (float)frameIndex / clip.frameRate); for (int boneIndex = 0; boneIndex < numBones; boneIndex++) { Matrix4x4 matrix = boneMatrices[boneIndex]; Quaternion rotation = ToQuaternion(matrix); Vector3 scale = matrix.lossyScale; float sx = Mathf.Floor(scale.x * 100.0f); float sy = Mathf.Floor(scale.y * 100.0f); float sz = Mathf.Floor(scale.z * 100.0f); if ((sx - sy) > 5.0f || (sx - sz) > 5.0f || (sy - sz) > 5.0f) { Transform remapBone = null; foreach (var key in boneIds.Keys) { if (boneIds[key] == boneIndex) { remapBone = key; break; } } string strLog = string.Format("AnimClip scale X Y Z not equal: {0} -> {1} {2}", curGameObject.name, boneAnimation.name, remapBone.transform.name); Warning("AnimClip scale", strLog); } pixelUv = convertPixel2UV(pixelIdx++); Color color1 = convertFloat16Bytes2Color(convertFloat32toFloat16Bytes(rotation.x), convertFloat32toFloat16Bytes(rotation.y)); tex2D.SetPixel(pixelUv.x, pixelUv.y, color1); pixelUv = convertPixel2UV(pixelIdx++); Color color2 = convertFloat16Bytes2Color(convertFloat32toFloat16Bytes(rotation.z), convertFloat32toFloat16Bytes(rotation.w)); tex2D.SetPixel(pixelUv.x, pixelUv.y, color2); pixelUv = convertPixel2UV(pixelIdx++); Color color3 = convertFloat16Bytes2Color(convertFloat32toFloat16Bytes(matrix.GetColumn(3).x), convertFloat32toFloat16Bytes(matrix.GetColumn(3).y)); tex2D.SetPixel(pixelUv.x, pixelUv.y, color3); pixelUv = convertPixel2UV(pixelIdx++); Color color4 = convertFloat16Bytes2Color(convertFloat32toFloat16Bytes(matrix.GetColumn(3).z), convertFloat32toFloat16Bytes(Mathf.Clamp01(matrix.lossyScale.magnitude))); tex2D.SetPixel(pixelUv.x, pixelUv.y, color4); //Debug.Log("==============frameIndex========start========"+ frameIndex); //Debug.Log("=======rotation==========="+ rotation.x+", "+ rotation.y+", " + rotation.z +", "+rotation.w); //Vector4 rrrr = convertColors2Halfs(color1, color2); //Debug.Log("=======rotation===22======" + rrrr.x + ", " + rrrr.y + ", " + rrrr.z + ", " + rrrr.w); //Debug.Log("=======translation===========" + matrix.GetColumn(3).x + ", " + matrix.GetColumn(3).y + ", " + matrix.GetColumn(3).z + ", " + Mathf.Clamp01(matrix.lossyScale.magnitude)); //Vector4 ttttt = convertColors2Halfs(color3, color4); //Debug.Log("=======translation===22======" + ttttt.x + ", " + ttttt.y + ", " + ttttt.z + ", " + ttttt.w); //Debug.Log("==============frameIndex========end========" + frameIndex); } } } tex2D.Apply(); // 导出动画纹理 animTexturePath = savePath + dataFileName.Replace(".bytes", "") + ".png"; exportTexture(tex2D, animTexturePath); setAnimationTextureProperties(animTexturePath); // 序列化后存储 byte[] array = MessagePackSerializer.Serialize(animData); string filePath = Path.Combine(parentFolder, savePath + dataFileName); if (File.Exists(filePath)) { File.Delete(filePath); } FileStream fs = new FileStream(filePath, FileMode.Create); fs.Write(array, 0, array.Length); fs.Close(); AssetDatabase.Refresh(); }
public void generateTexAndMesh_verticesAnim(string parentFolder, string savePath, string dataFileName) { // 重新生成mesh(这一步生成的mesh还是带骨骼indices和骨骼权重的,但顶点动画是不需要这些数据的,后面会删掉) rebuildAllMeshes(savePath, parentFolder); // 将骨骼矩阵写入纹理 var tex2D = new Texture2D(animData.texWidth, animData.texHeight, TextureFormat.RGB24, false); tex2D.filterMode = FilterMode.Point; int clipIdx = 0; int pixelIdx = 0; int totalFrameIndex = 0; GpuSkinningAnimClip boneAnimation = null; AnimationClip clip = null; List <Matrix4x4> boneMatrices = null; Vector4 boneIndices, boneWeights; Matrix4x4 boneMatrix0, boneMatrix1, boneMatrix2, boneMatrix3; Vector3 src_vertex; Vector4 vertex, position; for (clipIdx = 0; clipIdx < animClips.Length; ++clipIdx) { boneAnimation = animData.clips[clipIdx]; clip = animClips[clipIdx]; for (int frameIndex = 0; frameIndex < boneAnimation.Length(); frameIndex++) { boneMatrices = samplerAnimationClipBoneMatrices(curGameObject, clip, (float)frameIndex / clip.frameRate); for (int vertexIndex = 0; vertexIndex < instMesh.vertices.Length; ++vertexIndex) { src_vertex = instMesh.vertices[vertexIndex]; vertex = new Vector4(src_vertex.x, src_vertex.y, src_vertex.z, 1); boneIndices = boneIndicesList[vertexIndex]; boneWeights = boneWeightsList[vertexIndex]; boneMatrix0 = boneMatrices[Mathf.RoundToInt(boneIndices.x)]; boneMatrix1 = boneMatrices[Mathf.RoundToInt(boneIndices.y)]; boneMatrix2 = boneMatrices[Mathf.RoundToInt(boneIndices.z)]; boneMatrix3 = boneMatrices[Mathf.RoundToInt(boneIndices.w)]; matrixMulFloat(ref boneMatrix0, boneWeights.x); matrixMulFloat(ref boneMatrix1, boneWeights.y); matrixMulFloat(ref boneMatrix2, boneWeights.z); matrixMulFloat(ref boneMatrix3, boneWeights.w); position = (matrixAddMatrix(matrixAddMatrix(boneMatrix0, boneMatrix1), matrixAddMatrix(boneMatrix2, boneMatrix3))) * vertex; Color[] colors = convertThreeFloat16Bytes2TwoColor(convertFloat32toFloat16Bytes(position.x), convertFloat32toFloat16Bytes(position.y), convertFloat32toFloat16Bytes(position.z)); tex2D.SetPixel(vertexIndex, totalFrameIndex * 2, colors[0]); tex2D.SetPixel(vertexIndex, totalFrameIndex * 2 + 1, colors[1]); } ++totalFrameIndex; } } tex2D.Apply(); // 导出动画纹理 animTexturePath = savePath + dataFileName.Replace(".bytes", "") + ".png"; exportTexture(tex2D, animTexturePath); setAnimationTextureProperties(animTexturePath); // 序列化后存储 byte[] array = MessagePackSerializer.Serialize(animData); string filePath = Path.Combine(parentFolder, savePath + dataFileName); if (File.Exists(filePath)) { File.Delete(filePath); } FileStream fs = new FileStream(filePath, FileMode.Create); fs.Write(array, 0, array.Length); fs.Close(); AssetDatabase.Refresh(); // 删除mesh的骨骼信息 instMesh.uv2 = null; instMesh.uv3 = null; // 添加mesh的顶点索引 (TODO: unity shader中是否可以直接获取?) List <Vector4> indices = new List <Vector4>(); for (int vertexIndex = 0; vertexIndex < instMesh.vertices.Length; ++vertexIndex) { indices.Add(new Vector4(vertexIndex, vertexIndex, vertexIndex, vertexIndex)); } instMesh.SetUVs(1, indices); EditorUtility.SetDirty(instMesh); AssetDatabase.Refresh(); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); }