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);
    }
Пример #2
0
    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);
    }