private byte[] WriteMeshFile(ref JSONObject metadata) { MemoryStream fileStream = new MemoryStream(); //ushort subMeshCount = (ushort)mesh.subMeshCount; string item = meshName; // 分析vertexLayout WXMeshVertexLayout vertexLayout = new WXMeshVertexLayout(mesh); List <Transform> bones = new List <Transform>(); for (int j = 0; j < renderer.bones.Length; j++) { Transform item2 = renderer.bones[j]; if (bones.IndexOf(item2) == -1) { bones.Add(item2); } } //List<VertexData> vertexDatas = new List<VertexData>(); //List<VertexData> boneGroupVertex = new List<VertexData>(); //List<VertexData> vertexDataQueue = new List<VertexData>(); //int[] positionInBoneGroup = new int[3]; //List<int> indiceList = new List<int>(); //List<int> allBoneIndexes = new List<int>(); //List<int> vertexUsingBone = new List<int>(); //VertexData vertexData; //for (int i = 0; i < subMeshCount; i++) //{ // int[] indices = mesh.GetIndices(i); // for (int indiceIter = 0; indiceIter < indices.Length; indiceIter += 3) // { // // indice start // for (int k = 0; k < 3; k++) // { // int indiceIndex = indiceIter + k; // int vertexIndex = indices[indiceIndex]; // positionInBoneGroup[k] = -1; // int ii = 0; // while (ii < boneGroupVertex.Count) // { // if (boneGroupVertex[ii].index == vertexIndex) // { // positionInBoneGroup[k] = ii; // break; // } // ii++; // continue; // } // if (positionInBoneGroup[k] == -1) // { // vertexData = getVertexData(mesh, vertexIndex, vertexLayout); // vertexDataQueue.Add(vertexData); // // 每个点最多关联4根骨骼,所以遍历4下 // for (ii = 0; ii < 4; ii++) // { // float bone = vertexData.boneIndex[ii]; // if (allBoneIndexes.IndexOf((int)bone) == -1 && vertexUsingBone.IndexOf((int)bone) == -1) // { // vertexUsingBone.Add((int)bone); // } // } // } // } // // 没到达最大骨骼数 目前不知道这个24最大骨骼限制是干嘛用的 // if (allBoneIndexes.Count + vertexUsingBone.Count <= MaxBoneCount) // { // for (int l = 0; l < vertexUsingBone.Count; l++) // { // allBoneIndexes.Add(vertexUsingBone[l]); // } // int num8 = 1; // for (int l = 0; l < 3; l++) // { // if (positionInBoneGroup[l] == -1) // { // indiceList.Add(vertexDatas.Count + boneGroupVertex.Count - 1 + num8++); // } // else // { // indiceList.Add(vertexDatas.Count + positionInBoneGroup[l]); // } // } // for (int l = 0; l < vertexDataQueue.Count; l++) // { // boneGroupVertex.Add(vertexDataQueue[l]); // } // } // else // { // for (int l = 0; l < boneGroupVertex.Count; l++) // { // vertexDatas.Add(boneGroupVertex[l]); // } // // 回退一位? // indiceIter -= 3; // boneGroupVertex = new List<VertexData>(); // allBoneIndexes = new List<int>(); // } // // 最后一个face了 // if (indiceIter + 3 == indices.Length) // { // for (int l = 0; l < boneGroupVertex.Count; l++) // { // vertexDatas.Add(boneGroupVertex[l]); // } // boneGroupVertex = new List<VertexData>(); // allBoneIndexes = new List<int>(); // } // vertexUsingBone = new List<int>(); // vertexDataQueue = new List<VertexData>(); // // indice end // } //} long vertexStart = 0L; long vertexLength = 0L; long indiceStart = 0L; long indiceLength = 0L; long boneEndPosition = 0L; // 记录vertexBuffer在总buffer里的起始位置,一般是0 vertexStart = fileStream.Position; // 用于算包围球,计算模型的重心(所有点的位置均值) Vector3 vertexPositionAddup = new Vector3(0, 0, 0); // 遍历mesh里的所有定点 for (int j = 0; j < mesh.vertexCount; j++) { Vector3 vector = mesh.vertices[j]; // 写入position wxFileUtil.WriteData(fileStream, vector.x * -1f, vector.y, vector.z); // 统计position,用于算包围盒 vertexPositionAddup.Set(vertexPositionAddup.x + vector.x * -1f, vertexPositionAddup.y + vector.y, vertexPositionAddup.z + vector.z); // 如果vertexLayout有normal,写入normal if (vertexLayout.NORMAL) { Vector3 vector2 = mesh.normals[j]; wxFileUtil.WriteData(fileStream, vector2.x * -1f, vector2.y, vector2.z); } // 如果vertexLayout有color,写入color if (vertexLayout.COLOR) { Color color = mesh.colors[j]; wxFileUtil.WriteData(fileStream, color.r, color.g, color.b, color.a); } // 如果vertexLayout有uv,写入uv if (vertexLayout.UV) { Vector2 vector3 = mesh.uv[j]; wxFileUtil.WriteData(fileStream, vector3.x, vector3.y * -1f + 1f); } // 如果vertexLayout有uv1,写入uv1 if (vertexLayout.UV1) { Vector2 vector4 = mesh.uv2[j]; wxFileUtil.WriteData(fileStream, vector4.x, vector4.y * -1f + 1f); } if (vertexLayout.BONE) { BoneWeight boneWeight = mesh.boneWeights[j]; wxFileUtil.WriteData( fileStream, boneWeight.weight0, boneWeight.weight1, boneWeight.weight2, boneWeight.weight3 ); wxFileUtil.WriteData( fileStream, (float)boneWeight.boneIndex0, (float)boneWeight.boneIndex1, (float)boneWeight.boneIndex2, (float)boneWeight.boneIndex3 ); } // 如果vertexLayout有tangent,写入tangent if (vertexLayout.TANGENT) { Vector4 vector5 = mesh.tangents[j]; wxFileUtil.WriteData(fileStream, vector5.x * -1f, vector5.y, vector5.z, vector5.w); } } // 记录vertexBuffer在buffer里的结束位置 vertexLength = fileStream.Position - vertexStart; // 记录indiceBuffer在buffer里的起始位置 indiceStart = fileStream.Position; // indiceBuffer指的是给模型绘制面时,每个面所用的顶点index。在unity里叫triangles int[] triangles = mesh.triangles; for (int j = 0; j < triangles.Length; j++) { wxFileUtil.WriteData(fileStream, (ushort)triangles[j]); } // 记录indexBuffer在buffer里的结束位置 indiceLength = fileStream.Position - indiceStart; // 因为读取的时候是根据4位来读的所以末尾补0 long isFour = indiceLength % 4; if (isFour != 0) { wxFileUtil.WriteData(fileStream, (ushort)0.0); } long boneStartPosition = fileStream.Position; if (mesh.bindposes != null && mesh.bindposes.Length != 0) { Matrix4x4[] bonePoses = new Matrix4x4[mesh.bindposes.Length]; for (int i = 0; i < mesh.bindposes.Length; i++) { bonePoses[i] = mesh.bindposes[i]; bonePoses[i] = bonePoses[i].inverse; Vector3 s = default(Vector3); Quaternion q = default(Quaternion); Vector3 pos = default(Vector3); MathUtil.Decompose(bonePoses[i].transpose, out s, out q, out pos); pos.x *= -1f; q.x *= -1f; q.w *= -1f; bonePoses[i] = Matrix4x4.TRS(pos, q, s); } for (int i = 0; i < mesh.bindposes.Length; i++) { Matrix4x4 matrix4x = bonePoses[i]; } for (int i = 0; i < mesh.bindposes.Length; i++) { Matrix4x4 inverse = bonePoses[i].inverse; for (int j = 0; j < 16; j++) { wxFileUtil.WriteData(fileStream, inverse[j]); } } boneEndPosition = fileStream.Position; } long bonePoseLength = boneEndPosition - boneStartPosition; fileStream.Close(); metadata.AddField("indiceFormat", 1); // BIT16 = 1,BIT32 = 2 metadata.AddField("vertexLayout", vertexLayout.GetLayoutString()); //"POSITION,NORMAL,COLOR,UV,BLENDWEIGHT,BLENDINDICES,TANGENT", metadata.AddField("vertexStart", 0); metadata.AddField("vertexLength", vertexLength); metadata.AddField("indiceStart", vertexLength); // indice的偏移量 metadata.AddField("indiceLength", indiceLength); // indice的长度 metadata.AddField("bonePoseStart", boneStartPosition); metadata.AddField("bonePoseLength", bonePoseLength); metadata.AddField("capsule", GetCapsule()); bool succ = false; JSONObject bonesObject = GetSkinPaths(renderer.sharedMesh.name, ref succ); metadata.AddField("rootBone", bonesObject.GetField("root")); metadata.AddField("bones", bonesObject.GetField("bones")); metadata.AddField("version", 1); // 加入submesh JSONObject subMeshs = new JSONObject(JSONObject.Type.ARRAY); #if !UNITY_2017_1_OR_NEWER int indexStart = 0; #endif ushort subMeshCount = (ushort)mesh.subMeshCount; for (int i = 0; i < subMeshCount; i++) { JSONObject subMeshObj = new JSONObject(JSONObject.Type.OBJECT); #if !UNITY_2017_1_OR_NEWER subMeshObj.AddField("start", indexStart); subMeshObj.AddField("length", mesh.GetIndices(i).Length); indexStart += mesh.GetIndices(i).Length; #else subMeshObj.AddField("start", mesh.GetIndexStart(i)); subMeshObj.AddField("length", mesh.GetIndexCount(i)); #endif subMeshs.Add(subMeshObj); } // submesh一般指的是mesh里的其中一部分,所以用indiceBuffer的区间表示 metadata.AddField("subMeshs", subMeshs); return(fileStream.ToArray()); }
private byte[] WriteMeshFile(ref JSONObject metadata) { MemoryStream fileStream = new MemoryStream(); string meshName = mesh.name; WXMeshVertexLayout vertexLayout = new WXMeshVertexLayout(mesh); ushort subMeshCount = (ushort)mesh.subMeshCount; long vertexStart = 0L; long vertexLength = 0L; long indiceStart = 0L; long indiceLength = 0L; vertexStart = fileStream.Position; Vector3 vertexPositionMax = new Vector3(0, 0, 0); for (int j = 0; j < mesh.vertexCount; j++) { Vector3 vector = mesh.vertices[j]; wxFileUtil.WriteData(fileStream, vector.x * -1f, vector.y, vector.z); vertexPositionMax.Set(vertexPositionMax.x + vector.x * -1f, vertexPositionMax.y + vector.y, vertexPositionMax.z + vector.z); if (vertexLayout.NORMAL) { Vector3 vector2 = mesh.normals[j]; wxFileUtil.WriteData(fileStream, vector2.x * -1f, vector2.y, vector2.z); } if (vertexLayout.COLOR) { Color color = mesh.colors[j]; wxFileUtil.WriteData(fileStream, color.r, color.g, color.b, color.a); } if (vertexLayout.UV) { Vector2 vector3 = mesh.uv[j]; wxFileUtil.WriteData(fileStream, vector3.x, vector3.y * -1f + 1f); } if (vertexLayout.UV1) { Vector2 vector4 = mesh.uv2[j]; wxFileUtil.WriteData(fileStream, vector4.x, vector4.y * -1f + 1f); } if (vertexLayout.TANGENT) { Vector4 vector5 = mesh.tangents[j]; wxFileUtil.WriteData(fileStream, vector5.x * -1f, vector5.y, vector5.z, vector5.w); } } vertexLength = fileStream.Position - vertexStart; indiceStart = fileStream.Position; int[] triangles = mesh.triangles; for (int j = 0; j < triangles.Length; j++) { wxFileUtil.WriteData(fileStream, (ushort)triangles[j]); } indiceLength = fileStream.Position - indiceStart; fileStream.Close(); vertexPositionMax.Set(vertexPositionMax.x / mesh.vertices.Length, vertexPositionMax.y / mesh.vertices.Length, vertexPositionMax.z / mesh.vertices.Length); float capsuleRadius = CalCapsuleRadius(vertexPositionMax, mesh.vertices); JSONObject capsule = new JSONObject(JSONObject.Type.OBJECT); capsule.AddField("x", vertexPositionMax.x); capsule.AddField("y", vertexPositionMax.y); capsule.AddField("z", vertexPositionMax.z); capsule.AddField("radius", capsuleRadius); metadata.AddField("indiceFormat", 1); // BIT16 = 1,BIT32 = 2 metadata.AddField("vertexLayout", vertexLayout.GetLayoutString()); //"POSITION,NORMAL,COLOR,UV,BLENDWEIGHT,BLENDINDICES,TANGENT", metadata.AddField("vertexStart", 0); metadata.AddField("vertexLength", vertexLength); metadata.AddField("indiceStart", vertexLength); // indice的偏移量 metadata.AddField("indiceLength", indiceLength); // indice的长度 metadata.AddField("capsule", capsule); metadata.AddField("version", 1); JSONObject subMeshs = new JSONObject(JSONObject.Type.ARRAY); #if !UNITY_2017_1_OR_NEWER int indexStart = 0; #endif for (int i = 0; i < subMeshCount; i++) { JSONObject subMeshObj = new JSONObject(JSONObject.Type.OBJECT); #if UNITY_2017_1_OR_NEWER subMeshObj.AddField("start", mesh.GetIndexStart(i)); subMeshObj.AddField("length", mesh.GetIndexCount(i)); #else subMeshObj.AddField("start", indexStart); subMeshObj.AddField("length", mesh.GetIndices(i).Length); indexStart += mesh.GetIndices(i).Length; #endif subMeshs.Add(subMeshObj); } metadata.AddField("subMeshs", subMeshs); JSONObject boundBox = new JSONObject(JSONObject.Type.OBJECT); JSONObject boundBoxCenter = new JSONObject(JSONObject.Type.ARRAY); boundBoxCenter.Add(mesh.bounds.center.x); boundBoxCenter.Add(mesh.bounds.center.y); boundBoxCenter.Add(mesh.bounds.center.z); JSONObject boundBoxSize = new JSONObject(JSONObject.Type.ARRAY); boundBoxSize.Add(mesh.bounds.size.x); boundBoxSize.Add(mesh.bounds.size.y); boundBoxSize.Add(mesh.bounds.size.z); boundBox.AddField("center", boundBoxCenter); boundBox.AddField("size", boundBoxSize); metadata.AddField("boundBox", boundBox); return(fileStream.ToArray()); }