// Meshを連結する。SingleMesh で使う public static void Append(this Mesh mesh, VertexBuffer vertices, BufferAccessor indices, List <Submesh> submeshes, List <MorphTarget> targets, int[] jointIndexMap, int rootIndex = -1, Matrix4x4 matrix = default(Matrix4x4)) { var lastCount = mesh.VertexBuffer != null ? mesh.VertexBuffer.Count : 0; // index buffer if (mesh.IndexBuffer == null) { var accessor = new BufferAccessor(new ArraySegment <byte>(new byte[0]), AccessorValueType.UNSIGNED_INT, indices.AccessorType, 0); mesh.IndexBuffer = accessor; mesh.IndexBuffer.Append(indices, 0); } else { mesh.IndexBuffer.Append(indices, lastCount); } { var submeshOffset = mesh.SubmeshTotalDrawCount; for (int i = 0; i < submeshes.Count; ++i) { var submesh = submeshes[i]; mesh.Submeshes.Add(new Submesh(submeshOffset, submesh.DrawCount, submesh.Material)); submeshOffset += submesh.DrawCount; } } // vertex buffer var vertexOffset = 0; if (mesh.VertexBuffer == null) { mesh.VertexBuffer = vertices; } else { vertexOffset = mesh.VertexBuffer.Count; mesh.VertexBuffer.Append(vertices); } if (jointIndexMap != null && mesh.VertexBuffer.Joints != null && mesh.VertexBuffer.Weights != null) { // JOINT index 参照の修正 var joints = SpanLike.Wrap <SkinJoints>(mesh.VertexBuffer.Joints.Bytes).Slice(vertexOffset); var weights = SpanLike.Wrap <Vector4>(mesh.VertexBuffer.Weights.Bytes).Slice(vertexOffset); FixSkinJoints(joints, weights, jointIndexMap); } else { var position = SpanLike.Wrap <Vector3>(mesh.VertexBuffer.Positions.Bytes).Slice(vertexOffset); var normal = SpanLike.Wrap <Vector3>(mesh.VertexBuffer.Normals.Bytes).Slice(vertexOffset); var joints = mesh.VertexBuffer.GetOrCreateJoints().Slice(vertexOffset); var weights = mesh.VertexBuffer.GetOrCreateWeights().Slice(vertexOffset); // Nodeの姿勢を反映して // JOINT と WEIGHT を追加する FixNoSkinJoints(joints, weights, rootIndex, position, normal, matrix); } // morph target foreach (var target in targets) { if (string.IsNullOrEmpty(target.Name)) { continue; } foreach (var kv in target.VertexBuffer) { if (kv.Value.Count != target.VertexBuffer.Count) { throw new Exception("different length"); } } var found = mesh.MorphTargets.FirstOrDefault(x => x.Name == target.Name); if (found == null) { // targetの前に0を足す found = new MorphTarget(target.Name); found.VertexBuffer = target.VertexBuffer.CloneWithOffset(lastCount); mesh.MorphTargets.Add(found); foreach (var kv in found.VertexBuffer) { if (kv.Value.Count != mesh.VertexBuffer.Count) { throw new Exception(); } } } else { found.VertexBuffer.Resize(lastCount); // foundの後ろにtargetを足す found.VertexBuffer.Append(target.VertexBuffer); foreach (var kv in found.VertexBuffer) { if (kv.Value.Count != mesh.VertexBuffer.Count) { throw new Exception(); } } } } }
private static VrmLib.MeshGroup CreateMesh(UnityEngine.Mesh mesh, Renderer renderer, List <UnityEngine.Material> materials) { var meshGroup = new VrmLib.MeshGroup(mesh.name); var vrmMesh = new VrmLib.Mesh(); vrmMesh.VertexBuffer = new VrmLib.VertexBuffer(); vrmMesh.VertexBuffer.Add(VrmLib.VertexBuffer.PositionKey, ToBufferAccessor(mesh.vertices)); if (mesh.boneWeights.Length == mesh.vertexCount) { vrmMesh.VertexBuffer.Add( VrmLib.VertexBuffer.WeightKey, ToBufferAccessor(mesh.boneWeights.Select(x => new Vector4(x.weight0, x.weight1, x.weight2, x.weight3)).ToArray() )); vrmMesh.VertexBuffer.Add( VrmLib.VertexBuffer.JointKey, ToBufferAccessor(mesh.boneWeights.Select(x => new SkinJoints((ushort)x.boneIndex0, (ushort)x.boneIndex1, (ushort)x.boneIndex2, (ushort)x.boneIndex3)).ToArray() )); } if (mesh.uv.Length == mesh.vertexCount) { vrmMesh.VertexBuffer.Add(VrmLib.VertexBuffer.TexCoordKey, ToBufferAccessor(mesh.uv)); } if (mesh.normals.Length == mesh.vertexCount) { vrmMesh.VertexBuffer.Add(VrmLib.VertexBuffer.NormalKey, ToBufferAccessor(mesh.normals)); } if (mesh.colors.Length == mesh.vertexCount) { vrmMesh.VertexBuffer.Add(VrmLib.VertexBuffer.ColorKey, ToBufferAccessor(mesh.colors)); } vrmMesh.IndexBuffer = ToBufferAccessor(mesh.triangles); int offset = 0; for (int i = 0; i < mesh.subMeshCount; i++) { #if UNITY_2019 var subMesh = mesh.GetSubMesh(i); try { vrmMesh.Submeshes.Add(new VrmLib.Submesh(offset, subMesh.indexCount, materials.IndexOf(renderer.sharedMaterials[i]))); } catch (Exception ex) { Debug.LogError(ex); } offset += subMesh.indexCount; #else var triangles = mesh.GetTriangles(i); try { vrmMesh.Submeshes.Add(new VrmLib.Submesh(offset, triangles.Length, materials.IndexOf(renderer.sharedMaterials[i]))); } catch (Exception ex) { Debug.LogError(ex); } offset += triangles.Length; #endif } for (int i = 0; i < mesh.blendShapeCount; i++) { var blendShapeVertices = mesh.vertices; var usePosition = blendShapeVertices != null && blendShapeVertices.Length > 0; var blendShapeNormals = mesh.normals; var useNormal = usePosition && blendShapeNormals != null && blendShapeNormals.Length == blendShapeVertices.Length; // var useNormal = usePosition && blendShapeNormals != null && blendShapeNormals.Length == blendShapeVertices.Length && !exportOnlyBlendShapePosition; var blendShapeTangents = mesh.tangents.Select(y => (Vector3)y).ToArray(); //var useTangent = usePosition && blendShapeTangents != null && blendShapeTangents.Length == blendShapeVertices.Length; // var useTangent = false; var frameCount = mesh.GetBlendShapeFrameCount(i); mesh.GetBlendShapeFrameVertices(i, frameCount - 1, blendShapeVertices, blendShapeNormals, null); if (usePosition) { var morphTarget = new VrmLib.MorphTarget(mesh.GetBlendShapeName(i)); morphTarget.VertexBuffer = new VrmLib.VertexBuffer(); morphTarget.VertexBuffer.Add(VrmLib.VertexBuffer.PositionKey, ToBufferAccessor(blendShapeVertices)); vrmMesh.MorphTargets.Add(morphTarget); } } meshGroup.Meshes.Add(vrmMesh); return(meshGroup); }