static MeshWithMaterials ImportMesh(glTF gltf, int meshIndex, glTFMesh gltfMesh, List <Material> materials, GetBlendShapeName getBlendShapeName ) { glTFAttributes lastAttributes = null; var sharedAttributes = true; foreach (var prim in gltfMesh.primitives) { if (lastAttributes != null && !prim.attributes.Equals(lastAttributes)) { sharedAttributes = false; break; } lastAttributes = prim.attributes; } var positions = new List <Vector3>(); var normals = new List <Vector3>(); var tangents = new List <Vector4>(); var colors = new List <Vector4>(); var uv = new List <Vector2>(); var boneWeights = new List <BoneWeight>(); var subMeshes = new List <int[]>(); var materialIndices = new List <int>(); BlendShape[] blendShapes = null; if (sharedAttributes) { // multiple submesh sharing same VertexBuffer { var prim = gltfMesh.primitives.First(); positions.AddRange(gltf.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).Select(x => x.ReverseZ())); // normal if (prim.attributes.NORMAL != -1) { normals.AddRange(gltf.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).Select(x => x.ReverseZ())); } // tangent if (prim.attributes.TANGENT != -1) { tangents.AddRange(gltf.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).Select(x => x.ReverseZ())); } // vertex color if (prim.attributes.COLOR_0 != -1) { colors.AddRange(gltf.GetArrayFromAccessor <Vector4>(prim.attributes.COLOR_0)); } // uv if (prim.attributes.TEXCOORD_0 != -1) { uv.AddRange(gltf.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseY())); } else { // for inconsistent attributes in primitives uv.AddRange(new Vector2[positions.Count]); } // skin if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1) { var joints0 = gltf.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4 var weights0 = gltf.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0).Select(x => x.One()).ToArray(); for (int j = 0; j < joints0.Length; ++j) { var bw = new BoneWeight(); bw.boneIndex0 = joints0[j].x; bw.weight0 = weights0[j].x; bw.boneIndex1 = joints0[j].y; bw.weight1 = weights0[j].y; bw.boneIndex2 = joints0[j].z; bw.weight2 = weights0[j].z; bw.boneIndex3 = joints0[j].w; bw.weight3 = weights0[j].w; boneWeights.Add(bw); } } // blendshape if (prim.targets != null && prim.targets.Count > 0) { if (blendShapes == null) { blendShapes = prim.targets.Select((x, i) => new BlendShape(getBlendShapeName(meshIndex, i))).ToArray(); } for (int i = 0; i < prim.targets.Count; ++i) { //var name = string.Format("target{0}", i++); var primTarget = prim.targets[i]; var blendShape = blendShapes[i]; if (primTarget.POSITION != -1) { blendShape.Positions.AddRange( gltf.GetArrayFromAccessor <Vector3>(primTarget.POSITION).Select(x => x.ReverseZ()).ToArray()); } if (primTarget.NORMAL != -1) { blendShape.Normals.AddRange( gltf.GetArrayFromAccessor <Vector3>(primTarget.NORMAL).Select(x => x.ReverseZ()).ToArray()); } if (primTarget.TANGENT != -1) { blendShape.Tangents.AddRange( gltf.GetArrayFromAccessor <Vector3>(primTarget.TANGENT).Select(x => x.ReverseZ()).ToArray()); } } } } foreach (var prim in gltfMesh.primitives) { var indices = gltf.GetIndices(prim.indices).Select(x => x).ToArray(); subMeshes.Add(indices); // material materialIndices.Add(prim.material); } } else { // multiple submMesh is not sharing a VertexBuffer. // each subMesh use a independent VertexBuffer. var targets = gltfMesh.primitives[0].targets; for (int i = 1; i < gltfMesh.primitives.Count; ++i) { if (!gltfMesh.primitives[i].targets.SequenceEqual(targets)) { throw new NotImplementedException(string.Format("diffirent targets: {0} with {1}", gltfMesh.primitives[i], targets)); } } foreach (var prim in gltfMesh.primitives) { var indexOffset = positions.Count; var indexBuffer = prim.indices; var positionCount = positions.Count; positions.AddRange(gltf.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).Select(x => x.ReverseZ())); positionCount = positions.Count - positionCount; // normal if (prim.attributes.NORMAL != -1) { normals.AddRange(gltf.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).Select(x => x.ReverseZ())); } if (prim.attributes.TANGENT != -1) { tangents.AddRange(gltf.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).Select(x => x.ReverseZ())); } // vertex color if (prim.attributes.COLOR_0 != -1) { colors.AddRange(gltf.GetArrayFromAccessor <Vector4>(prim.attributes.COLOR_0)); } // uv if (prim.attributes.TEXCOORD_0 != -1) { uv.AddRange(gltf.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseY())); } else { // for inconsistent attributes in primitives uv.AddRange(new Vector2[positionCount]); } // skin if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1) { var joints0 = gltf.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4 var weights0 = gltf.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0).Select(x => x.One()).ToArray(); for (int j = 0; j < joints0.Length; ++j) { var bw = new BoneWeight(); bw.boneIndex0 = joints0[j].x; bw.weight0 = weights0[j].x; bw.boneIndex1 = joints0[j].y; bw.weight1 = weights0[j].y; bw.boneIndex2 = joints0[j].z; bw.weight2 = weights0[j].z; bw.boneIndex3 = joints0[j].w; bw.weight3 = weights0[j].w; boneWeights.Add(bw); } } // blendshape if (prim.targets != null && prim.targets.Count > 0) { if (blendShapes == null) { blendShapes = prim.targets.Select((x, i) => new BlendShape(i.ToString())).ToArray(); } for (int i = 0; i < prim.targets.Count; ++i) { //var name = string.Format("target{0}", i++); var primTarget = prim.targets[i]; var blendShape = blendShapes[i]; if (primTarget.POSITION != -1) { blendShape.Positions.AddRange( gltf.GetArrayFromAccessor <Vector3>(primTarget.POSITION).Select(x => x.ReverseZ()).ToArray()); } if (primTarget.NORMAL != -1) { blendShape.Normals.AddRange( gltf.GetArrayFromAccessor <Vector3>(primTarget.NORMAL).Select(x => x.ReverseZ()).ToArray()); } if (primTarget.TANGENT != -1) { blendShape.Tangents.AddRange( gltf.GetArrayFromAccessor <Vector3>(primTarget.TANGENT).Select(x => x.ReverseZ()).ToArray()); } } } var indices = (indexBuffer >= 0) ? gltf.GetIndices(indexBuffer).Select(x => x + indexOffset).ToArray() : TriangleUtil.FlipTriangle(Enumerable.Range(0, positions.Count)).ToArray() // without index array ; subMeshes.Add(indices); // material materialIndices.Add(prim.material); } } if (!materialIndices.Any()) { materialIndices.Add(0); } //Debug.Log(prims.ToJson()); var mesh = new Mesh(); mesh.name = gltfMesh.name; if (positions.Count > UInt16.MaxValue) { #if UNITY_2017_3_OR_NEWER mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; #else Debug.LogWarningFormat("vertices {0} exceed 65535. not implemented. Unity2017.3 supports large mesh", positions.Count); #endif } mesh.vertices = positions.ToArray(); if (normals.Any()) { mesh.normals = normals.ToArray(); } else { mesh.RecalculateNormals(); } if (tangents.Any()) { mesh.tangents = tangents.ToArray(); } else { mesh.RecalculateTangents(); } if (colors.Any()) { mesh.colors = colors.ConvertAll(x => new Color(x.x, x.y, x.z, 1f)).ToArray(); } if (uv.Any()) { mesh.uv = uv.ToArray(); } if (boneWeights.Any()) { mesh.boneWeights = boneWeights.ToArray(); } mesh.subMeshCount = subMeshes.Count; for (int i = 0; i < subMeshes.Count; ++i) { mesh.SetTriangles(subMeshes[i], i); } var result = new MeshWithMaterials { Mesh = mesh, Materials = materialIndices.Select(x => materials[x]).ToArray() }; List <Material> matList = result.Materials.ToList(); matList.RemoveAll(x => x == null); result.Materials = matList.ToArray(); if (blendShapes != null) { foreach (var blendShape in blendShapes) { if (blendShape.Positions.Count > 0) { if (blendShape.Positions.Count == mesh.vertexCount) { mesh.AddBlendShapeFrame(blendShape.Name, FRAME_WEIGHT, blendShape.Positions.ToArray(), normals.Count == mesh.vertexCount ? blendShape.Normals.ToArray() : null, null ); } else { Debug.LogWarningFormat("May be partial primitive has blendShape. Rquire separete mesh or extend blend shape, but not implemented: {0}", blendShape.Name); } } } } return(result); }
public static bool CutTriangleMeshFast(Mesh[] outputMeshes, Mesh sourceMesh, Transform objectTransform, Transform planeTransform, bool cap) { float epsilon = 0.00001f; hashCheck = new Dictionary <Vector3, int>(); debugPolyLoop = new List <Vector3>(); debugEdgePoints = new List <Vector3>(); debugEdges = new List <Vector3[]>(); debugLoopEdgePoints = new List <Vector3[]>(); int originalVertexCount = sourceMesh.vertexCount; Vector3[] originalVertices = sourceMesh.vertices; int originalIndexCount = sourceMesh.triangles.Length; int[] originalIndices = sourceMesh.triangles; Vector3 centre = objectTransform.transform.InverseTransformPoint(planeTransform.position); Vector3 up = objectTransform.transform.InverseTransformDirection(planeTransform.up); Plane cuttingPlane = new Plane(up, centre); int totalIndexCount = originalIndexCount; int totalVertexCount = originalVertexCount; int indexBufferCountA = 0; int vertexBufferCountA = 0; Vector3[] vertexBufferA = new Vector3[totalVertexCount * 10]; int[] indexBufferA = new int[originalIndexCount * 10]; int indexBufferCountB = 0; int vertexBufferCountB = 0; Vector3[] vertexBufferB = new Vector3[totalVertexCount * 10]; int[] indexBufferB = new int[originalIndexCount * 10]; Vector3[] points = new Vector3[3]; int[] triIndices = new int[3]; for (int i = 0; i < totalIndexCount; i += 3) { triIndices[0] = originalIndices[i]; triIndices[1] = originalIndices[i + 1]; triIndices[2] = originalIndices[i + 2]; points[0] = originalVertices[triIndices[0]]; points[1] = originalVertices[triIndices[1]]; points[2] = originalVertices[triIndices[2]]; int[] newTris; Vector3[] newPoints; ClassificationUtil.Classification side; TriangleUtil.SplitTriangleWithPlane( ref totalVertexCount, points, triIndices, cuttingPlane, epsilon, out side, cap, out newTris, out newPoints); // Slice the triangle then classify which side it's on if (newTris != null) { for (int j = 0; j < newTris.Length; j += 3) { ClassificationUtil.Classification[] classes; ClassificationUtil.Classification triClass = ClassificationUtil.ClassifyPoints( new Vector3[] { newPoints[j + 0], newPoints[j + 1], newPoints[j + 2] }, cuttingPlane, out classes, epsilon); //Debug.DrawLine(newPoints[j + 0], newPoints[j + 1]); //Debug.DrawLine(newPoints[j + 1], newPoints[j + 2]); //Debug.DrawLine(newPoints[j + 2], newPoints[j + 0]); if (triClass == ClassificationUtil.Classification.FRONT) { indexBufferA[indexBufferCountA++] = newTris[j + 0]; indexBufferA[indexBufferCountA++] = newTris[j + 1]; indexBufferA[indexBufferCountA++] = newTris[j + 2]; vertexBufferA[vertexBufferCountA++] = newPoints[j + 0]; vertexBufferA[vertexBufferCountA++] = newPoints[j + 1]; vertexBufferA[vertexBufferCountA++] = newPoints[j + 2]; } else if (triClass == ClassificationUtil.Classification.BACK) { indexBufferB[indexBufferCountB++] = newTris[j + 0]; indexBufferB[indexBufferCountB++] = newTris[j + 1]; indexBufferB[indexBufferCountB++] = newTris[j + 2]; vertexBufferB[vertexBufferCountB++] = newPoints[j + 0]; vertexBufferB[vertexBufferCountB++] = newPoints[j + 1]; vertexBufferB[vertexBufferCountB++] = newPoints[j + 2]; } } } else { ClassificationUtil.Classification[] classes; ClassificationUtil.Classification triClass = ClassificationUtil.ClassifyPoints( new Vector3[] { points[0], points[1], points[2] }, cuttingPlane, out classes, epsilon); //Debug.DrawLine(points[0], points[1], Color.red); //Debug.DrawLine(points[1], points[2], Color.red); //Debug.DrawLine(points[2], points[0], Color.red); if (triClass == ClassificationUtil.Classification.FRONT) { indexBufferA[indexBufferCountA++] = triIndices[0]; indexBufferA[indexBufferCountA++] = triIndices[1]; indexBufferA[indexBufferCountA++] = triIndices[2]; vertexBufferA[vertexBufferCountA++] = points[0]; vertexBufferA[vertexBufferCountA++] = points[1]; vertexBufferA[vertexBufferCountA++] = points[2]; } else if (triClass == ClassificationUtil.Classification.BACK) { indexBufferB[indexBufferCountB++] = triIndices[0]; indexBufferB[indexBufferCountB++] = triIndices[1]; indexBufferB[indexBufferCountB++] = triIndices[2]; vertexBufferB[vertexBufferCountB++] = points[0]; vertexBufferB[vertexBufferCountB++] = points[1]; vertexBufferB[vertexBufferCountB++] = points[2]; } } } if (indexBufferCountA > 0) { SortMesh(outputMeshes[0], indexBufferA, vertexBufferA, indexBufferCountA, false); } if (indexBufferCountB > 0) { SortMesh(outputMeshes[1], indexBufferB, vertexBufferB, indexBufferCountB, true); } return(true); }
// multiple submMesh is not sharing a VertexBuffer. // each subMesh use a independent VertexBuffer. private static MeshContext _ImportMeshIndependentVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh) { //Debug.LogWarning("_ImportMeshIndependentVertexBuffer"); var targets = gltfMesh.primitives[0].targets; for (int i = 1; i < gltfMesh.primitives.Count; ++i) { if (!gltfMesh.primitives[i].targets.SequenceEqual(targets)) { throw new NotImplementedException(string.Format("diffirent targets: {0} with {1}", gltfMesh.primitives[i], targets)); } } var positions = new List <Vector3>(); var normals = new List <Vector3>(); var tangents = new List <Vector4>(); var uv = new List <Vector2>(); var colors = new List <Color>(); var meshContext = new MeshContext(); foreach (var prim in gltfMesh.primitives) { var indexOffset = positions.Count; var indexBuffer = prim.indices; var positionCount = positions.Count; positions.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).Select(x => x.ReverseZ())); positionCount = positions.Count - positionCount; // normal if (prim.attributes.NORMAL != -1) { normals.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).Select(x => x.ReverseZ())); } if (prim.attributes.TANGENT != -1) { tangents.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).Select(x => x.ReverseZ())); } // uv if (prim.attributes.TEXCOORD_0 != -1) { if (ctx.IsGeneratedUniGLTFAndOlder(1, 16)) { #pragma warning disable 0612 // backward compatibility uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseY())); #pragma warning restore 0612 } else { uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseUV())); } } else { // for inconsistent attributes in primitives uv.AddRange(new Vector2[positionCount]); } // color if (prim.attributes.COLOR_0 != -1) { colors.AddRange(ctx.GLTF.GetArrayFromAccessor <Color>(prim.attributes.COLOR_0)); } // skin if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1) { var joints0 = ctx.GLTF.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4 var weights0 = ctx.GLTF.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0).Select(x => x.One()).ToArray(); for (int j = 0; j < joints0.Length; ++j) { var bw = new BoneWeight(); bw.boneIndex0 = joints0[j].x; bw.weight0 = weights0[j].x; bw.boneIndex1 = joints0[j].y; bw.weight1 = weights0[j].y; bw.boneIndex2 = joints0[j].z; bw.weight2 = weights0[j].z; bw.boneIndex3 = joints0[j].w; bw.weight3 = weights0[j].w; meshContext.boneWeights.Add(bw); } } // blendshape if (prim.targets != null && prim.targets.Count > 0) { for (int i = 0; i < prim.targets.Count; ++i) { //var name = string.Format("target{0}", i++); var primTarget = prim.targets[i]; var blendShape = new BlendShape(!string.IsNullOrEmpty(prim.extras.targetNames[i]) ? prim.extras.targetNames[i] : i.ToString()) ; if (primTarget.POSITION != -1) { blendShape.Positions.AddRange( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.POSITION).Select(x => x.ReverseZ()).ToArray()); } if (primTarget.NORMAL != -1) { blendShape.Normals.AddRange( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.NORMAL).Select(x => x.ReverseZ()).ToArray()); } if (primTarget.TANGENT != -1) { blendShape.Tangents.AddRange( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.TANGENT).Select(x => x.ReverseZ()).ToArray()); } meshContext.blendShapes.Add(blendShape); } } var indices = (indexBuffer >= 0) ? ctx.GLTF.GetIndices(indexBuffer) : TriangleUtil.FlipTriangle(Enumerable.Range(0, meshContext.positions.Length)).ToArray() // without index array ; for (int i = 0; i < indices.Length; ++i) { indices[i] += indexOffset; } meshContext.subMeshes.Add(indices); // material meshContext.materialIndices.Add(prim.material); } meshContext.positions = positions.ToArray(); meshContext.normals = normals.ToArray(); meshContext.tangents = tangents.ToArray(); meshContext.uv = uv.ToArray(); return(meshContext); }
// multiple submesh sharing same VertexBuffer private static MeshContext _ImportMeshSharingVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh) { var context = new MeshContext(); { var prim = gltfMesh.primitives.First(); context.positions = ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).SelectInplace(x => x.ReverseZ()); // normal if (prim.attributes.NORMAL != -1) { context.normals = ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).SelectInplace(x => x.ReverseZ()); } // tangent if (prim.attributes.TANGENT != -1) { context.tangents = ctx.GLTF.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).SelectInplace(x => x.ReverseZ()); } // uv if (prim.attributes.TEXCOORD_0 != -1) { if (ctx.IsGeneratedUniGLTFAndOlder(1, 16)) { #pragma warning disable 0612 // backward compatibility context.uv = ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseY()); #pragma warning restore 0612 } else { context.uv = ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseUV()); } } else { // for inconsistent attributes in primitives context.uv = new Vector2[context.positions.Length]; } // color if (prim.attributes.COLOR_0 != -1) { context.colors = ctx.GLTF.GetArrayFromAccessor <Color>(prim.attributes.COLOR_0); } // skin if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1) { var joints0 = ctx.GLTF.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4 var weights0 = ctx.GLTF.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0); for (int i = 0; i < weights0.Length; ++i) { weights0[i] = weights0[i].One(); } for (int j = 0; j < joints0.Length; ++j) { var bw = new BoneWeight(); bw.boneIndex0 = joints0[j].x; bw.weight0 = weights0[j].x; bw.boneIndex1 = joints0[j].y; bw.weight1 = weights0[j].y; bw.boneIndex2 = joints0[j].z; bw.weight2 = weights0[j].z; bw.boneIndex3 = joints0[j].w; bw.weight3 = weights0[j].w; context.boneWeights.Add(bw); } } // blendshape if (prim.targets != null && prim.targets.Count > 0) { context.blendShapes.AddRange(prim.targets.Select((x, i) => new BlendShape( i < prim.extras.targetNames.Count && !string.IsNullOrEmpty(prim.extras.targetNames[i]) ? prim.extras.targetNames[i] : i.ToString()))); for (int i = 0; i < prim.targets.Count; ++i) { //var name = string.Format("target{0}", i++); var primTarget = prim.targets[i]; var blendShape = context.blendShapes[i]; if (primTarget.POSITION != -1) { blendShape.Positions.Assign( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.POSITION), x => x.ReverseZ()); } if (primTarget.NORMAL != -1) { blendShape.Normals.Assign( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.NORMAL), x => x.ReverseZ()); } if (primTarget.TANGENT != -1) { blendShape.Tangents.Assign( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.TANGENT), x => x.ReverseZ()); } } } } foreach (var prim in gltfMesh.primitives) { if (prim.indices == -1) { context.subMeshes.Add(TriangleUtil.FlipTriangle(Enumerable.Range(0, context.positions.Length)).ToArray()); } else { var indices = ctx.GLTF.GetIndices(prim.indices); context.subMeshes.Add(indices); } // material context.materialIndices.Add(prim.material); } return(context); }
/// <summary> /// /// 各primitiveが同じ attribute を共有している場合専用のローダー。 /// /// </summary> /// <param name="ctx"></param> /// <param name="gltfMesh"></param> /// <returns></returns> public void ImportMeshSharingVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh) { { // 同じVertexBufferを共有しているので先頭のモノを使う var prim = gltfMesh.primitives.First(); m_positions.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).SelectInplace(x => x.ReverseZ())); // normal if (prim.attributes.NORMAL != -1) { m_normals.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).SelectInplace(x => x.ReverseZ())); } #if false // tangent if (prim.attributes.TANGENT != -1) { tangents.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).SelectInplace(x => x.ReverseZ())); } #endif // uv if (prim.attributes.TEXCOORD_0 != -1) { if (ctx.IsGeneratedUniGLTFAndOlder(1, 16)) { #pragma warning disable 0612 // backward compatibility m_uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseY())); #pragma warning restore 0612 } else { m_uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseUV())); } } // uv2 if (prim.attributes.TEXCOORD_1 != -1) { m_uv2.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_1).SelectInplace(x => x.ReverseUV())); } // color if (prim.attributes.COLOR_0 != -1) { if (ctx.GLTF.accessors[prim.attributes.COLOR_0].TypeCount == 3) { var vec3Color = ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.COLOR_0); m_colors.AddRange(new Color[vec3Color.Length]); for (int i = 0; i < vec3Color.Length; i++) { Vector3 color = vec3Color[i]; m_colors[i] = new Color(color.x, color.y, color.z); } } else if (ctx.GLTF.accessors[prim.attributes.COLOR_0].TypeCount == 4) { m_colors.AddRange(ctx.GLTF.GetArrayFromAccessor <Color>(prim.attributes.COLOR_0)); } else { throw new NotImplementedException(string.Format("unknown color type {0}", ctx.GLTF.accessors[prim.attributes.COLOR_0].type)); } } // skin if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1) { var joints0 = ctx.GLTF.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4 var weights0 = ctx.GLTF.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0); for (int i = 0; i < weights0.Length; ++i) { weights0[i] = weights0[i].One(); } for (int j = 0; j < joints0.Length; ++j) { var bw = new BoneWeight(); bw.boneIndex0 = joints0[j].x; bw.weight0 = weights0[j].x; bw.boneIndex1 = joints0[j].y; bw.weight1 = weights0[j].y; bw.boneIndex2 = joints0[j].z; bw.weight2 = weights0[j].z; bw.boneIndex3 = joints0[j].w; bw.weight3 = weights0[j].w; m_boneWeights.Add(bw); } } // blendshape if (prim.targets != null && prim.targets.Count > 0) { m_blendShapes.AddRange(prim.targets.Select((x, i) => new BlendShape(i.ToString()))); for (int i = 0; i < prim.targets.Count; ++i) { //var name = string.Format("target{0}", i++); var primTarget = prim.targets[i]; var blendShape = m_blendShapes[i]; if (primTarget.POSITION != -1) { blendShape.Positions.Assign( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.POSITION), x => x.ReverseZ()); } if (primTarget.NORMAL != -1) { blendShape.Normals.Assign( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.NORMAL), x => x.ReverseZ()); } if (primTarget.TANGENT != -1) { blendShape.Tangents.Assign( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.TANGENT), x => x.ReverseZ()); } } } } foreach (var prim in gltfMesh.primitives) { if (prim.indices == -1) { m_subMeshes.Add(TriangleUtil.FlipTriangle(Enumerable.Range(0, m_positions.Count)).ToArray()); } else { var indices = ctx.GLTF.GetIndices(prim.indices); m_subMeshes.Add(indices); } // material m_materialIndices.Add(prim.material); } }
static glTFMesh ExportPrimitives(glTF gltf, int bufferIndex, string rendererName, Mesh mesh, Material[] materials, List <Material> unityMaterials) { var positions = mesh.vertices.Select(y => y.ReverseZ()).ToArray(); var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, positions, glBufferTarget.ARRAY_BUFFER); gltf.accessors[positionAccessorIndex].min = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray(); gltf.accessors[positionAccessorIndex].max = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray(); var normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.normals.Select(y => y.normalized.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER); #if GLTF_EXPORT_TANGENTS var tangentAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.tangents.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER); #endif var uvAccessorIndex0 = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.uv.Select(y => y.ReverseUV()).ToArray(), glBufferTarget.ARRAY_BUFFER); var uvAccessorIndex1 = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.uv2.Select(y => y.ReverseUV()).ToArray(), glBufferTarget.ARRAY_BUFFER); var colorAccessorIndex = -1; var vColorState = MeshExportInfo.DetectVertexColor(mesh, materials); if (vColorState == MeshExportInfo.VertexColorState.ExistsAndIsUsed || // VColor使っている vColorState == MeshExportInfo.VertexColorState.ExistsAndMixed // VColorを使っているところと使っていないところが混在(とりあえずExportする) ) { // UniUnlit で Multiply 設定になっている colorAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.colors, glBufferTarget.ARRAY_BUFFER); } var boneweights = mesh.boneWeights; var weightAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneweights.Select(y => new Vector4(y.weight0, y.weight1, y.weight2, y.weight3)).ToArray(), glBufferTarget.ARRAY_BUFFER); var jointsAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneweights.Select(y => new UShort4((ushort)y.boneIndex0, (ushort)y.boneIndex1, (ushort)y.boneIndex2, (ushort)y.boneIndex3)).ToArray(), glBufferTarget.ARRAY_BUFFER); var attributes = new glTFAttributes { POSITION = positionAccessorIndex, }; if (normalAccessorIndex != -1) { attributes.NORMAL = normalAccessorIndex; } #if GLTF_EXPORT_TANGENTS if (tangentAccessorIndex != -1) { attributes.TANGENT = tangentAccessorIndex; } #endif if (uvAccessorIndex0 != -1) { attributes.TEXCOORD_0 = uvAccessorIndex0; } if (uvAccessorIndex1 != -1) { attributes.TEXCOORD_1 = uvAccessorIndex1; } if (colorAccessorIndex != -1) { attributes.COLOR_0 = colorAccessorIndex; } if (weightAccessorIndex != -1) { attributes.WEIGHTS_0 = weightAccessorIndex; } if (jointsAccessorIndex != -1) { attributes.JOINTS_0 = jointsAccessorIndex; } var gltfMesh = new glTFMesh(mesh.name); for (int j = 0; j < mesh.subMeshCount; ++j) { var indices = TriangleUtil.FlipTriangle(mesh.GetIndices(j)).Select(y => (uint)y).ToArray(); var indicesAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, indices, glBufferTarget.ELEMENT_ARRAY_BUFFER); if (j >= materials.Length) { Debug.LogWarningFormat("{0}.materials is not enough", rendererName); break; } gltfMesh.primitives.Add(new glTFPrimitives { attributes = attributes, indices = indicesAccessorIndex, mode = 4, // triangles ? material = unityMaterials.IndexOf(materials[j]) }); } return(gltfMesh); }
/// <summary> /// 各 primitive の attribute の要素が同じでない。=> uv が有るものと無いものが混在するなど /// glTF 的にはありうる。 /// /// primitive を独立した(Independent) Mesh として扱いこれを連結する。 /// </summary> /// <param name="ctx"></param> /// <param name="gltfMesh"></param> /// <returns></returns> public void ImportMeshIndependentVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh) { foreach (var prim in gltfMesh.primitives) { var indexOffset = m_positions.Count; var indexBuffer = prim.indices; // position は必ずある var positionCount = m_positions.Count; m_positions.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).Select(x => x.ReverseZ())); positionCount = m_positions.Count - positionCount; // normal if (prim.attributes.NORMAL != -1) { FillZero(m_normals); m_normals.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).Select(x => x.ReverseZ())); } #if false if (prim.attributes.TANGENT != -1) { FillZero(tangetns); tangents.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).Select(x => x.ReverseZ())); } #endif // uv if (prim.attributes.TEXCOORD_0 != -1) { FillZero(m_uv); if (ctx.IsGeneratedUniGLTFAndOlder(1, 16)) { #pragma warning disable 0612 // backward compatibility m_uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseY())); #pragma warning restore 0612 } else { m_uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseUV())); } } // uv2 if (prim.attributes.TEXCOORD_1 != -1) { FillZero(m_uv2); m_uv2.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_1).Select(x => x.ReverseUV())); } // color if (prim.attributes.COLOR_0 != -1) { FillZero(m_colors); m_colors.AddRange(ctx.GLTF.GetArrayFromAccessor <Color>(prim.attributes.COLOR_0)); } // skin if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1) { FillZero(m_boneWeights); var joints0 = ctx.GLTF.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4 var weights0 = ctx.GLTF.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0).Select(x => x.One()).ToArray(); for (int j = 0; j < joints0.Length; ++j) { var bw = new BoneWeight(); bw.boneIndex0 = joints0[j].x; bw.weight0 = weights0[j].x; bw.boneIndex1 = joints0[j].y; bw.weight1 = weights0[j].y; bw.boneIndex2 = joints0[j].z; bw.weight2 = weights0[j].z; bw.boneIndex3 = joints0[j].w; bw.weight3 = weights0[j].w; m_boneWeights.Add(bw); } } // blendshape if (prim.targets != null && prim.targets.Count > 0) { for (int i = 0; i < prim.targets.Count; ++i) { var primTarget = prim.targets[i]; var blendShape = new BlendShape(i.ToString()); if (primTarget.POSITION != -1) { FillZero(blendShape.Positions); blendShape.Positions.AddRange( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.POSITION).Select(x => x.ReverseZ()).ToArray()); } if (primTarget.NORMAL != -1) { FillZero(blendShape.Normals); blendShape.Normals.AddRange( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.NORMAL).Select(x => x.ReverseZ()).ToArray()); } if (primTarget.TANGENT != -1) { FillZero(blendShape.Tangents); blendShape.Tangents.AddRange( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.TANGENT).Select(x => x.ReverseZ()).ToArray()); } m_blendShapes.Add(blendShape); } } var indices = (indexBuffer >= 0) ? ctx.GLTF.GetIndices(indexBuffer) : TriangleUtil.FlipTriangle(Enumerable.Range(0, m_positions.Count)).ToArray() // without index array ; for (int i = 0; i < indices.Length; ++i) { indices[i] += indexOffset; } m_subMeshes.Add(indices); // material m_materialIndices.Add(prim.material); } }
public static Exported FromGameObject(glTF gltf, GameObject go) { var bytesBuffer = new ArrayByteBuffer(); var bufferIndex = gltf.AddBuffer(bytesBuffer); var unityNodes = go.transform.Traverse() .Skip(1) // exclude root object for the symmetry with the importer .ToList(); #region Material var unityMaterials = unityNodes.SelectMany(x => x.GetSharedMaterials()).Where(x => x != null).Distinct().ToList(); var unityTextures = unityMaterials.SelectMany(x => x.GetTextures()).Where(x => x != null).Distinct().ToList(); for (int i = 0; i < unityTextures.Count; ++i) { var texture = unityTextures[i]; ExportTexture(gltf, bufferIndex, texture); } gltf.materials = unityMaterials.Select(x => ExportMaterial(x, unityTextures)).ToList(); #endregion #region Meshes var unityMeshes = unityNodes .Select(x => new MeshWithRenderer { Mesh = x.GetSharedMesh(), Rendererer = x.GetComponent <Renderer>(), }) .Where(x => x.Mesh != null) .ToList(); for (int i = 0; i < unityMeshes.Count; ++i) { var x = unityMeshes[i]; var mesh = x.Mesh; var materials = x.Rendererer.sharedMaterials; var positions = mesh.vertices.Select(y => y.ReverseZ()).ToArray(); var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, positions, glBufferTarget.ARRAY_BUFFER); gltf.accessors[positionAccessorIndex].min = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray(); gltf.accessors[positionAccessorIndex].max = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray(); var normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.normals.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER); var tangentAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.tangents.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER); var uvAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.uv.Select(y => y.ReverseY()).ToArray(), glBufferTarget.ARRAY_BUFFER); var boneweights = mesh.boneWeights; var weightAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneweights.Select(y => new Vector4(y.weight0, y.weight1, y.weight2, y.weight3)).ToArray(), glBufferTarget.ARRAY_BUFFER); var jointsAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneweights.Select(y => new UShort4((ushort)y.boneIndex0, (ushort)y.boneIndex1, (ushort)y.boneIndex2, (ushort)y.boneIndex3)).ToArray(), glBufferTarget.ARRAY_BUFFER); var attributes = new glTFAttributes { POSITION = positionAccessorIndex, }; if (normalAccessorIndex != -1) { attributes.NORMAL = normalAccessorIndex; } if (tangentAccessorIndex != -1) { attributes.TANGENT = tangentAccessorIndex; } if (uvAccessorIndex != -1) { attributes.TEXCOORD_0 = uvAccessorIndex; } if (weightAccessorIndex != -1) { attributes.WEIGHTS_0 = weightAccessorIndex; } if (jointsAccessorIndex != -1) { attributes.JOINTS_0 = jointsAccessorIndex; } gltf.meshes.Add(new glTFMesh(mesh.name)); for (int j = 0; j < mesh.subMeshCount; ++j) { var indices = TriangleUtil.FlipTriangle(mesh.GetIndices(j)).Select(y => (uint)y).ToArray(); var indicesAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, indices, glBufferTarget.ELEMENT_ARRAY_BUFFER); gltf.meshes.Last().primitives.Add(new glTFPrimitives { attributes = attributes, indices = indicesAccessorIndex, mode = 4, // triangels ? material = unityMaterials.IndexOf(materials[j]) }); } if (mesh.blendShapeCount > 0) { for (int j = 0; j < mesh.blendShapeCount; ++j) { var blendShapeVertices = mesh.vertices; var blendShpaeNormals = mesh.normals; var blendShapeTangents = mesh.tangents.Select(y => (Vector3)y).ToArray(); var k = mesh.GetBlendShapeFrameCount(j); mesh.GetBlendShapeFrameVertices(j, k - 1, blendShapeVertices, blendShpaeNormals, null); var blendShapePositionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, blendShapeVertices.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER); var blendShapeNormalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, blendShpaeNormals.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER); var blendShapeTangentAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, blendShapeTangents.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER); // // first primitive has whole blendShape // gltf.meshes.Last().primitives[0].targets.Add(new gltfMorphTarget { extra = new extraName { name = mesh.GetBlendShapeName(j) }, POSITION = blendShapePositionAccessorIndex, NORMAL = blendShapeNormalAccessorIndex, TANGENT = blendShapeTangentAccessorIndex, }); } } } #endregion #region Skins var unitySkins = unityNodes .Select(x => x.GetComponent <SkinnedMeshRenderer>()).Where(x => x != null) .ToList(); gltf.nodes = unityNodes.Select(x => ExportNode(x, unityNodes, unityMeshes.Select(y => y.Mesh).ToList(), unitySkins)).ToList(); gltf.scenes = new List <gltfScene> { new gltfScene { nodes = go.transform.GetChildren().Select(x => unityNodes.IndexOf(x)).ToArray(), } }; foreach (var x in unitySkins) { var matrices = x.sharedMesh.bindposes.Select(y => y.ReverseZ()).ToArray(); var accessor = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, matrices, glBufferTarget.NONE); var skin = new glTFSkin { inverseBindMatrices = accessor, joints = x.bones.Select(y => unityNodes.IndexOf(y)).ToArray(), skeleton = unityNodes.IndexOf(x.rootBone), }; var skinIndex = gltf.skins.Count; gltf.skins.Add(skin); foreach (var z in unityNodes.Where(y => y.Has(x))) { var nodeIndex = unityNodes.IndexOf(z); gltf.nodes[nodeIndex].skin = skinIndex; } } #endregion #if UNITY_EDITOR #region Animations var animation = go.GetComponent <Animation>(); if (animation != null) { foreach (AnimationState state in animation) { var animationWithCurve = ExportAnimation(state.clip, go.transform, unityNodes); foreach (var kv in animationWithCurve.SamplerMap) { var sampler = animationWithCurve.Animation.samplers[kv.Key]; var inputAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Input); sampler.input = inputAccessorIndex; var outputAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Output); sampler.output = outputAccessorIndex; // modify accessors var outputAccessor = gltf.accessors[outputAccessorIndex]; var channel = animationWithCurve.Animation.channels.First(x => x.sampler == kv.Key); switch (glTFAnimationTarget.GetElementCount(channel.target.path)) { case 3: outputAccessor.type = "VEC3"; outputAccessor.count /= 3; break; case 4: outputAccessor.type = "VEC4"; outputAccessor.count /= 4; break; default: throw new NotImplementedException(); } } gltf.animations.Add(animationWithCurve.Animation); } } #endregion #endif // glb buffer gltf.buffers[bufferIndex].UpdateByteLength(); return(new Exported { Meshes = unityMeshes, Nodes = unityNodes.Select(x => x.transform).ToList(), Materials = unityMaterials, Textures = unityTextures, }); }
public List <PathNode> FindCenterPointPath(Vector3 start, Vector3 end) { //标记开始结束点 startVertex = FindNodeByPoint(start); endVertex = FindNodeByPoint(end); if (startVertex == null && endVertex == null) { return(null); } else if (startVertex == null) { startVertex = FindNearestNode(start); } else if (endVertex == null) { endVertex = FindNearestNode(end); } PathNode startNode = new PathNode(); startNode.node = startVertex; PathNode endNode = new PathNode(); endNode.node = endVertex; //如果起点和终点在同一个三角形中,则返回一个节点 if (startVertex.center == endVertex.center) { pathList.Clear(); pathList.Add(startNode); return(pathList); } //如果起点和终点在两个相邻的三角形中,则返回二个节点 else if (TriangleUtil.GetTwoPointsInTwoPath(startNode, endNode) != null) { pathList.Clear(); pathList.Add(startNode); pathList.Add(endNode); return(pathList); } List <PathNode> openList = new List <PathNode>(); closeList = new List <PathNode>(); PathNode path = new PathNode(); path.node = startVertex; path.dis = 0; closeList.Add(path); FindNextPath(path, endVertex, openList, closeList); //记录并显示路径 if (showProcessPath) { ShowProcessPath(); } else { ShowCenterPath(); } return(pathList); }
static glTFMesh ExportPrimitives(glTF gltf, int bufferIndex, string rendererName, Mesh mesh, Material[] materials, List <Material> unityMaterials) { var positions = mesh.vertices.Select(y => y.ReverseZ()).ToArray(); var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, positions, glBufferTarget.ARRAY_BUFFER); gltf.accessors[positionAccessorIndex].min = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray(); gltf.accessors[positionAccessorIndex].max = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray(); var normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.normals.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER); var tangentAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.tangents.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER); var uvAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.uv.Select(y => y.ReverseY()).ToArray(), glBufferTarget.ARRAY_BUFFER); var colorAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.colors, glBufferTarget.ARRAY_BUFFER); var boneweights = mesh.boneWeights; var weightAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneweights.Select(y => new Vector4(y.weight0, y.weight1, y.weight2, y.weight3)).ToArray(), glBufferTarget.ARRAY_BUFFER); var jointsAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneweights.Select(y => new UShort4((ushort)y.boneIndex0, (ushort)y.boneIndex1, (ushort)y.boneIndex2, (ushort)y.boneIndex3)).ToArray(), glBufferTarget.ARRAY_BUFFER); var attributes = new glTFAttributes { POSITION = positionAccessorIndex, }; if (normalAccessorIndex != -1) { attributes.NORMAL = normalAccessorIndex; } if (tangentAccessorIndex != -1) { attributes.TANGENT = tangentAccessorIndex; } if (uvAccessorIndex != -1) { attributes.TEXCOORD_0 = uvAccessorIndex; } if (colorAccessorIndex != -1) { attributes.COLOR_0 = colorAccessorIndex; } if (weightAccessorIndex != -1) { attributes.WEIGHTS_0 = weightAccessorIndex; } if (jointsAccessorIndex != -1) { attributes.JOINTS_0 = jointsAccessorIndex; } var gltfMesh = new glTFMesh(mesh.name); for (int j = 0; j < mesh.subMeshCount; ++j) { var indices = TriangleUtil.FlipTriangle(mesh.GetIndices(j)).Select(y => (uint)y).ToArray(); var indicesAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, indices, glBufferTarget.ELEMENT_ARRAY_BUFFER); if (j >= materials.Length) { Debug.LogWarningFormat("{0}.materials is not enough", rendererName); break; } gltfMesh.primitives.Add(new glTFPrimitives { attributes = attributes, indices = indicesAccessorIndex, mode = 4, // triangels ? material = unityMaterials.IndexOf(materials[j]) }); } return(gltfMesh); }
public static bool CutTriangleMesh(Mesh[] outputMeshes, Mesh sourceMesh, Plane cuttingPlane, Transform transform, Transform rotation, bool cap) { float epsilon = 0.00001f; debugPolyLoop = new List <Vector3>(); debugEdgePoints = new List <Vector3>(); debugEdges = new List <Vector3[]>(); debugLoopEdgePoints = new List <Vector3[]>(); int vertCount = sourceMesh.vertexCount; Vector3[] verts = sourceMesh.vertices; Triangle3D.Vertex[] allVerts = new Triangle3D.Vertex[vertCount]; for (int i = 0; i < vertCount; i++) { allVerts[i] = new Triangle3D.Vertex(transform.TransformPoint(verts[i])); } List <Triangle3D.Vertex> allVertList = new List <Triangle3D.Vertex>(); Vector2[] originalUVs = sourceMesh.uv; Vector3[] originalNormals = sourceMesh.normals; Vector4[] originalTangents = sourceMesh.tangents; int triCount = sourceMesh.triangles.Length / 3; Triangle3D[] originalTriangles = new Triangle3D[triCount]; int offset = 0; for (int j = 0; j < sourceMesh.subMeshCount; j++) { uint triOffset = 0; int[] subMeshIndices = sourceMesh.GetTriangles(j); int subMeshTriCount = subMeshIndices.Length / 3; for (int i = 0; i < subMeshTriCount; i++) { int idx0 = subMeshIndices[triOffset + 0]; int idx1 = subMeshIndices[triOffset + 1]; int idx2 = subMeshIndices[triOffset + 2]; originalTriangles[offset++] = new Triangle3D(allVertList, new Triangle3D.Vertex[] { allVerts[idx0], allVerts[idx1], allVerts[idx2] }, new Vector3[] { originalNormals[idx0], originalNormals[idx1], originalNormals[idx2] }, new Vector2[] { originalUVs[idx0], originalUVs[idx1], originalUVs[idx2] }, new Vector4[] { originalTangents[idx0], originalTangents[idx1], originalTangents[idx2] }, new int[] { subMeshIndices[triOffset + 0], subMeshIndices[triOffset + 1], subMeshIndices[triOffset + 2] }, j); triOffset += 3; } } if (originalTriangles.Length > 0) { int processedTriCount = 0; Triangle3D[] processedTris = new Triangle3D[originalTriangles.Length * 3]; ClassificationUtil.Classification prevSide = ClassificationUtil.Classification.UNDEFINED; foreach (Triangle3D originalTriangle in originalTriangles) { ClassificationUtil.Classification side; Triangle3D[] splitTriangles = TriangleUtil.SplitTriangleWithPlane(originalTriangle, cuttingPlane, epsilon, out side, cap); if (prevSide != ClassificationUtil.Classification.UNDEFINED && prevSide != side) { } prevSide = side; if (splitTriangles != null) { // Triangle was cut foreach (Triangle3D splitTriangle in splitTriangles) { processedTris[processedTriCount] = splitTriangle; processedTriCount++; } } else { // Triangle was not cut processedTris[processedTriCount] = originalTriangle; processedTriCount++; } } int triangleBucketACount = 0; int triangleBucketBCount = 0; Triangle3D[] triangleBucketA = new Triangle3D[processedTriCount]; Triangle3D[] triangleBucketB = new Triangle3D[processedTriCount]; for (int i = 0; i < processedTriCount; i++) { ClassificationUtil.Classification[] classes; ClassificationUtil.Classification triClass = ClassificationUtil.ClassifyPoints(processedTris[i].pos, cuttingPlane, out classes, epsilon); if (triClass == ClassificationUtil.Classification.FRONT) { triangleBucketA[triangleBucketACount++] = processedTris[i]; } else if (triClass == ClassificationUtil.Classification.BACK) { triangleBucketB[triangleBucketBCount++] = processedTris[i]; } } if (triangleBucketACount == 0 || triangleBucketBCount == 0) { return(false); } List <Triangle3D> totalCapTriBucket = new List <Triangle3D>(); List <Triangle3D.Vertex> totalCapVertBucket = new List <Triangle3D.Vertex>(); while (cap && debugEdges.Count > 2) { List <Triangle3D> capTriBucket = new List <Triangle3D>(); List <Triangle3D.Vertex> capVertBucket = new List <Triangle3D.Vertex>(); Triangle3D.Vertex[] sortedVerts = GetPolyLoop(ref debugEdges); if (sortedVerts != null) { CapMesh(out capTriBucket, out capVertBucket, sortedVerts, transform, rotation, totalCapTriBucket.Count); } if (capVertBucket.Count > 2) { for (int i = 0; i < capVertBucket.Count - 1; i++) { Debug.DrawLine(transform.TransformPoint(capVertBucket[i].pos), transform.TransformPoint(capVertBucket[i + 1].pos)); } Debug.DrawLine(transform.TransformPoint(capVertBucket[capVertBucket.Count - 1].pos), transform.TransformPoint(capVertBucket[0].pos)); } totalCapTriBucket.AddRange(capTriBucket); totalCapVertBucket.AddRange(capVertBucket); } if (triangleBucketACount > 0) { SortMesh(outputMeshes[0], triangleBucketA, triangleBucketACount, transform, totalCapTriBucket, totalCapVertBucket, false); } if (triangleBucketBCount > 0) { SortMesh(outputMeshes[1], triangleBucketB, triangleBucketBCount, transform, totalCapTriBucket, totalCapVertBucket, true); } return(true); } else { Debug.Log("source geometry empty"); return(false); } }