void CutMesh() { //SETUP QUAD VARIABLES================================================== planeNormal = -transform.forward; planeNormal = planeNormal.normalized; planePoint = transform.position; planeTangent = new Vector4(transform.right.x, transform.right.y, transform.right.z, 1); //================================================== Mesh targetMesh = target.GetComponent <MeshFilter>().mesh; targetRenderer = target.GetComponent <Renderer>(); List <int> tris; Vector2[] uvs = targetMesh.uv; Vector3[] verts = targetMesh.vertices; Vector3[] normals = targetMesh.normals; Vector4[] tangents = targetMesh.tangents; upVerts = new List <List <Vector3> >(); uphashVerts = new List <OrderedHashSet <Vector3> >(); upTris = new List <ProtoMesh>(); upUVs = new List <List <Vector2> >(); upNormals = new List <List <Vector3> >(); upTangents = new List <List <Vector4> >(); downVerts = new List <List <Vector3> >(); downhashVerts = new List <OrderedHashSet <Vector3> >(); downTris = new List <ProtoMesh>(); downUVs = new List <List <Vector2> >(); downNormals = new List <List <Vector3> >(); downTangents = new List <List <Vector4> >(); centerEdges = new List <Edge>(); bool[] intersected = new bool[3]; float submeshCount = targetMesh.subMeshCount; List <int> bigMeshVertsSizeUp = listPooler.GetPooledList(); List <int> bigMeshVertsSizeDown = listPooler.GetPooledList(); for (int j = 0; j < submeshCount; j++) { tris = listPooler.GetPooledList(); targetMesh.GetTriangles(tris, j); for (int i = 0; i < tris.Count; i += 3) { triVerts[0] = target.transform.TransformPoint(verts[tris[i]]); triVerts[1] = target.transform.TransformPoint(verts[tris[i + 1]]); triVerts[2] = target.transform.TransformPoint(verts[tris[i + 2]]); triUvs[0] = uvs[tris[i]]; triUvs[1] = uvs[tris[i + 1]]; triUvs[2] = uvs[tris[i + 2]]; triNormals[0] = normals[tris[i]]; triNormals[1] = normals[tris[i + 1]]; triNormals[2] = normals[tris[i + 2]]; triTangents[0] = tangents[tris[i]]; triTangents[1] = tangents[tris[i + 1]]; triTangents[2] = tangents[tris[i + 2]]; DoesTriIntersectPlane(triVerts[0], triVerts[1], triVerts[2], intersected); if (intersected[0] || intersected[1] || intersected[2]) { TriIntersectionPoints(intersected, triVerts, triUvs, triNormals, triTangents); } else { if (Mathf.Sign(Vector3.Dot(planeNormal, (triVerts[0] - planePoint))) > 0) {//above AddTriToCorrectMeshObject(triVerts, triNormals, triTangents, triUvs, upVerts, uphashVerts, upNormals, upUVs, upTangents); } else { AddTriToCorrectMeshObject(triVerts, triNormals, triTangents, triUvs, downVerts, downhashVerts, downNormals, downUVs, downTangents); } } } if (j == 0) { for (int k = 0; k < upVerts.Count; k++) { bigMeshVertsSizeUp.Add(upVerts[k].Count); } for (int k = 0; k < downVerts.Count; k++) { bigMeshVertsSizeDown.Add(downVerts[k].Count); } } listPooler.PoolList(tris); } if (centerEdges.Count == 0 || upVerts.Count == 0 || downVerts.Count == 0) { return; } CreateBodyTris(upVerts, upTris, bigMeshVertsSizeUp); CreateBodyTris(downVerts, downTris, bigMeshVertsSizeDown); List <List <Vector3> > groupedVerts = GroupConnectedCenterVerts(); List <IntersectionLoop> faceLoops = new List <IntersectionLoop>(); for (int i = 0; i < groupedVerts.Count; i++) { faceLoops.Add(new IntersectionLoop(groupedVerts[i])); } CreateHullMeshFromEdgeLoop(upVerts, uphashVerts, upTris, upUVs, upNormals, upTangents, faceLoops, true); CreateHullMeshFromEdgeLoop(downVerts, downhashVerts, downTris, downUVs, downNormals, downTangents, faceLoops, false); CreateFinalGameObjects(upVerts, upTris, upNormals, upTangents, upUVs); CreateFinalGameObjects(downVerts, downTris, downNormals, downTangents, downUVs); Destroy(target); }
void CutMesh() { //SETUP QUAD VARIABLES================================================== planeNormal = -transform.forward; planeNormal = planeNormal.normalized; planePoint = transform.position; planeTangent = new Vector4(transform.right.x, transform.right.y, transform.right.z, 1); //================================================== SkinnedMeshRenderer skin = target.GetComponentInChildren <SkinnedMeshRenderer>(); Mesh targetMesh = skin.sharedMesh; targetRenderer = target.GetComponent <Renderer>(); List <int> tris; Vector2[] uvs = targetMesh.uv; Vector3[] verts = targetMesh.vertices; Vector3[] normals = targetMesh.normals; Vector4[] tangents = targetMesh.tangents; Transform[] bones = skin.bones; List <Matrix4x4> bindPoses = new List <Matrix4x4>(); targetMesh.GetBindposes(bindPoses); Matrix4x4[] boneMatrices = new Matrix4x4[bones.Length]; for (int i = 0; i < bones.Length; i++) { boneMatrices[i] = bones[i].localToWorldMatrix * bindPoses[i]; } List <BoneWeight> boneWeights = new List <BoneWeight>(); targetMesh.GetBoneWeights(boneWeights); upVerts = new List <List <Vector3> >(); uphashVerts = new List <OrderedHashSet <Vector3> >(); upTris = new List <ProtoMesh>(); upUVs = new List <List <Vector2> >(); upNormals = new List <List <Vector3> >(); upTangents = new List <List <Vector4> >(); downVerts = new List <List <Vector3> >(); downhashVerts = new List <OrderedHashSet <Vector3> >(); downTris = new List <ProtoMesh>(); downUVs = new List <List <Vector2> >(); downNormals = new List <List <Vector3> >(); downTangents = new List <List <Vector4> >(); centerEdges = new List <Edge>(); bool[] intersected = new bool[3]; float submeshCount = targetMesh.subMeshCount; List <int> bigMeshVertsSizeUp = listPooler.GetPooledList(); List <int> bigMeshVertsSizeDown = listPooler.GetPooledList(); Matrix4x4 vertexBoneMatrix = new Matrix4x4(); for (int j = 0; j < submeshCount; j++) { tris = listPooler.GetPooledList(); targetMesh.GetTriangles(tris, j); for (int i = 0; i < tris.Count; i += 3) { int vertexIndex = tris[i]; int vertexIndex1 = tris[i + 1]; int vertexIndex2 = tris[i + 2]; Matrix4x4 bm0 = boneMatrices[boneWeights[vertexIndex].boneIndex0]; Matrix4x4 bm1 = boneMatrices[boneWeights[vertexIndex].boneIndex1]; Matrix4x4 bm2 = boneMatrices[boneWeights[vertexIndex].boneIndex2]; Matrix4x4 bm3 = boneMatrices[boneWeights[vertexIndex].boneIndex3]; for (int n = 0; n < 16; n++) { vertexBoneMatrix[n] = bm0[n] * boneWeights[vertexIndex].weight0 + bm1[n] * boneWeights[vertexIndex].weight1 + bm2[n] * boneWeights[vertexIndex].weight2 + bm3[n] * boneWeights[vertexIndex].weight3; } //tris[i] triVerts[0] = vertexBoneMatrix.MultiplyPoint3x4(verts[vertexIndex]); triUvs[0] = uvs[vertexIndex]; triNormals[0] = normals[vertexIndex]; triTangents[0] = tangents[vertexIndex]; bm0 = boneMatrices[boneWeights[vertexIndex1].boneIndex0]; bm1 = boneMatrices[boneWeights[vertexIndex1].boneIndex1]; bm2 = boneMatrices[boneWeights[vertexIndex1].boneIndex2]; bm3 = boneMatrices[boneWeights[vertexIndex1].boneIndex3]; for (int n = 0; n < 16; n++) { vertexBoneMatrix[n] = bm0[n] * boneWeights[vertexIndex1].weight0 + bm1[n] * boneWeights[vertexIndex1].weight1 + bm2[n] * boneWeights[vertexIndex1].weight2 + bm3[n] * boneWeights[vertexIndex1].weight3; } triVerts[1] = vertexBoneMatrix.MultiplyPoint3x4(verts[vertexIndex1]); triUvs[1] = uvs[vertexIndex1]; triNormals[1] = normals[vertexIndex1]; triTangents[1] = tangents[vertexIndex1]; bm0 = boneMatrices[boneWeights[vertexIndex2].boneIndex0]; bm1 = boneMatrices[boneWeights[vertexIndex2].boneIndex1]; bm2 = boneMatrices[boneWeights[vertexIndex2].boneIndex2]; bm3 = boneMatrices[boneWeights[vertexIndex2].boneIndex3]; for (int n = 0; n < 16; n++) { vertexBoneMatrix[n] = bm0[n] * boneWeights[vertexIndex2].weight0 + bm1[n] * boneWeights[vertexIndex2].weight1 + bm2[n] * boneWeights[vertexIndex2].weight2 + bm3[n] * boneWeights[vertexIndex2].weight3; } triVerts[2] = vertexBoneMatrix.MultiplyPoint3x4(verts[vertexIndex2]); triUvs[2] = uvs[vertexIndex2]; triNormals[2] = normals[vertexIndex2]; triTangents[2] = tangents[vertexIndex2]; DoesTriIntersectPlane(triVerts[0], triVerts[1], triVerts[2], intersected); if (intersected[0] || intersected[1] || intersected[2]) { TriIntersectionPoints(intersected, triVerts, triUvs, triNormals, triTangents); } else { if (Mathf.Sign(Vector3.Dot(planeNormal, (triVerts[0] - planePoint))) > 0) {//above AddTriToCorrectMeshObject(triVerts, triNormals, triTangents, triUvs, upVerts, uphashVerts, upNormals, upUVs, upTangents); } else { AddTriToCorrectMeshObject(triVerts, triNormals, triTangents, triUvs, downVerts, downhashVerts, downNormals, downUVs, downTangents); } } } if (j == 0) { for (int k = 0; k < upVerts.Count; k++) { bigMeshVertsSizeUp.Add(upVerts[k].Count); } for (int k = 0; k < downVerts.Count; k++) { bigMeshVertsSizeDown.Add(downVerts[k].Count); } } listPooler.PoolList(tris); } if (centerEdges.Count == 0 || upVerts.Count == 0 || downVerts.Count == 0) { return; } CreateBodyTris(upVerts, upTris, bigMeshVertsSizeUp); CreateBodyTris(downVerts, downTris, bigMeshVertsSizeDown); List <List <Vector3> > groupedVerts = GroupConnectedCenterVerts(); List <IntersectionLoop> faceLoops = new List <IntersectionLoop>(); for (int i = 0; i < groupedVerts.Count; i++) { faceLoops.Add(new IntersectionLoop(groupedVerts[i])); } CreateHullMeshFromEdgeLoop(upVerts, uphashVerts, upTris, upUVs, upNormals, upTangents, faceLoops, true); CreateHullMeshFromEdgeLoop(downVerts, downhashVerts, downTris, downUVs, downNormals, downTangents, faceLoops, false); CreateFinalGameObjects(upVerts, upTris, upNormals, upTangents, upUVs); CreateFinalGameObjects(downVerts, downTris, downNormals, downTangents, downUVs); Destroy(target); }
void CutMesh() { //setup quad variables at the time of the cut planeNormal = (-transform.forward).normalized; planePoint = transform.position; planeTangent = new Vector4(transform.right.x, transform.right.y, transform.right.z, 1); //retrieve data about the target to be cut Mesh targetMesh = target.GetComponent <MeshFilter>().mesh; targetRenderer = target.GetComponent <Renderer>(); List <int> tris; Vector2[] uvs = targetMesh.uv; Vector3[] verts = targetMesh.vertices; Vector3[] normals = targetMesh.normals; Vector4[] tangents = targetMesh.tangents; //initialize big lists (each of the inner lists represents a new object) upVerts = new List <List <Vector3> >(); uphashVerts = new List <OrderedHashSet <Vector3> >(); upTris = new List <ProtoMesh>(); upUVs = new List <List <Vector2> >(); upNormals = new List <List <Vector3> >(); upTangents = new List <List <Vector4> >(); downVerts = new List <List <Vector3> >(); downhashVerts = new List <OrderedHashSet <Vector3> >(); downTris = new List <ProtoMesh>(); downUVs = new List <List <Vector2> >(); downNormals = new List <List <Vector3> >(); downTangents = new List <List <Vector4> >(); centerEdges = new List <Edge>(); bool[] intersected = new bool[3]; List <int> bigMeshVertsSizeUp = listPooler.GetPooledList(); List <int> bigMeshVertsSizeDown = listPooler.GetPooledList(); float submeshCount = targetMesh.subMeshCount; //for each submesh, go through the triangles //do line-plane intersection for each of the 3 lines of the triangle //triangles that have atleast one line intersection, calculate how to split it in two //triangles that dont intersect, if they are above, save them in one list, if bellow save them in another for (int j = 0; j < submeshCount; j++) { tris = listPooler.GetPooledList(); targetMesh.GetTriangles(tris, j); for (int i = 0; i < tris.Count; i += 3) { triVerts[0] = target.transform.TransformPoint(verts[tris[i]]); triVerts[1] = target.transform.TransformPoint(verts[tris[i + 1]]); triVerts[2] = target.transform.TransformPoint(verts[tris[i + 2]]); triUvs[0] = uvs[tris[i]]; triUvs[1] = uvs[tris[i + 1]]; triUvs[2] = uvs[tris[i + 2]]; triNormals[0] = normals[tris[i]]; triNormals[1] = normals[tris[i + 1]]; triNormals[2] = normals[tris[i + 2]]; triTangents[0] = tangents[tris[i]]; triTangents[1] = tangents[tris[i + 1]]; triTangents[2] = tangents[tris[i + 2]]; DoesTriIntersectPlane(triVerts[0], triVerts[1], triVerts[2], intersected); if (intersected[0] || intersected[1] || intersected[2]) { TriIntersectionPoints(intersected, triVerts, triUvs, triNormals, triTangents); } else { if (Mathf.Sign(Vector3.Dot(planeNormal, (triVerts[0] - planePoint))) > 0)//above { AddTriToCorrectMeshObject(triVerts, triNormals, triTangents, triUvs, upVerts, uphashVerts, upNormals, upUVs, upTangents); } else { AddTriToCorrectMeshObject(triVerts, triNormals, triTangents, triUvs, downVerts, downhashVerts, downNormals, downUVs, downTangents); } } } //On the first target submesh saves the number of verts for the resulting cut objects //The point is that, after you cut a mesh once, from a mesh it results into a 2 meshes with 2 submeshtes each (the body and the cut polygon) //Once you cut one of those meshes, you need to keep the second submesh (cut polygon) as a submesh with the "cut" material //So by saving the vertices resulting from the cut of the first submesh (the body) //we can infer that all the remaining vertices are from cutting submeshes with the "cut" material, and they should stay that way if (j == 0) { for (int k = 0; k < upVerts.Count; k++) { bigMeshVertsSizeUp.Add(upVerts[k].Count); } for (int k = 0; k < downVerts.Count; k++) { bigMeshVertsSizeDown.Add(downVerts[k].Count); } } listPooler.PoolList(tris); } //if nothing was cut, stop here if (centerEdges.Count == 0 || upVerts.Count == 0 || downVerts.Count == 0) { return; } //Create triangles for the cut bodies CreateBodyTris(upVerts, upTris, bigMeshVertsSizeUp); CreateBodyTris(downVerts, downTris, bigMeshVertsSizeDown); //Detect all polygons resulting from the cut List <List <Vector3> > groupedVerts = GroupConnectedCenterVerts(); List <IntersectionLoop> faceLoops = new List <IntersectionLoop>(); for (int i = 0; i < groupedVerts.Count; i++) { faceLoops.Add(new IntersectionLoop(groupedVerts[i])); } //From the polygons create tris, normals, etc for each CreateHullMeshFromEdgeLoop(upVerts, uphashVerts, upTris, upUVs, upNormals, upTangents, faceLoops, true); CreateHullMeshFromEdgeLoop(downVerts, downhashVerts, downTris, downUVs, downNormals, downTangents, faceLoops, false); //complete the Objects CreateFinalGameObjects(upVerts, upTris, upNormals, upTangents, upUVs); CreateFinalGameObjects(downVerts, downTris, downNormals, downTangents, downUVs); //Destroy original target object Destroy(target); }