Ejemplo n.º 1
0
    // Split this Face with given Plane
    public bool Split(Plane inPlane, out CSGFace outFront, out CSGFace outBack)
    {
        outFront = new CSGFace();
        outBack  = new CSGFace();

        float[]      distance = new float[vertices.Length + 1];
        EPlaneSide[] side     = new EPlaneSide[vertices.Length + 1];


        for (int i = 0; i < vertices.Length; ++i)
        {
            distance[i] = inPlane.GetDistanceToPoint(vertices[i]);
            side[i]     = Side(inPlane, vertices[i]);
        }

        distance[vertices.Length] = distance[0];
        side[vertices.Length]     = side[0];

        for (int i = 0; i < vertices.Length; ++i)
        {
            // if we lie on plane, add them to both
            if (side[i] == EPlaneSide.Side_Planar)
            {
                outFront.AddVertex(vertices[i], uv[i]);
                outBack.AddVertex(vertices[i], uv[i]);
                // nothing todo with this vertex
                continue;
            }

            // if we are on the front, add it to front face
            if (side[i] == EPlaneSide.Side_Front)
            {
                outFront.AddVertex(vertices[i], uv[i]);
            }
            // if we are on the back, add it to the back side
            else if (side[i] == EPlaneSide.Side_Back)
            {
                outBack.AddVertex(vertices[i], uv[i]);
            }

            // check if the next vertex is planar or on the same side, then we do not split
            if (side[i + 1] == EPlaneSide.Side_Planar || side[i] == side[i + 1])
            {
                continue;
            }

            // create split point
            Vector3 nextVector = vertices[(i + 1) % vertices.Length];
            Vector2 nextUV = uv[(i + 1) % uv.Length];
            Vector3 newVector, newUV;

            // if we were on the front
            if (side[i] == EPlaneSide.Side_Front)
            {
                float t = distance[i] / (distance[i] - distance[i + 1]);

                newVector = vertices[i] + t * (nextVector - vertices[i]);
                newUV     = uv[i] + t * (nextUV - uv[i]);
            }
            else             // back side...
            {
                float t = distance[i + 1] / (distance[i + 1] - distance[i]);

                newVector = nextVector + t * (vertices[i] - nextVector);
                newUV     = nextUV + t * (uv[i] - nextUV);
            }

            // split points are added

            // add to front
            outFront.AddVertex(newVector, newUV);

            // add to back
            outBack.AddVertex(newVector, newUV);
        }

        // Debugging checks
        if (outFront.vertices.Length < 3 || outBack.vertices.Length < 3)
        {
            Debug.Log("Degenerate Faces");
        }


        // todo...
        outFront.material = material;

        //
        outBack.material = material;

        return(true);
    }
Ejemplo n.º 2
0
    public bool Merge(CSGFace inOther, out CSGFace outFace)
    {
        outFace = null;


        // do not share same material
        if (material != inOther.material || vertices.Length < 1)
        {
            return(false);
        }

        Vector3 p1, p2;
        Vector3 p3, p4;
        int     i = 0, j = 0;

        // just to fix compiler error
        p1 = vertices[0];
        p2 = vertices[1 % vertices.Length];

        // check if we share an edge
        for (i = 0; i < vertices.Length; ++i)
        {
            // get edge
            p1 = vertices[i];
            p2 = vertices[(i + 1) % vertices.Length];


            // go through all edges of other face
            for (j = 0; j < inOther.vertices.Length; ++j)
            {
                // get other edge
                p3 = inOther.vertices[j];
                p4 = inOther.vertices[(j + 1) % inOther.vertices.Length];

                // check if we are sharing an edge
                if (p1.Equals(p4) && p2.Equals(p3))
                {
                    break;
                }
            }

            // found edge
            if (j < inOther.vertices.Length)
            {
                break;
            }
        }

        // no edge found
        if (i == vertices.Length)
        {
            return(false);
        }

        //  ...
        Vector3 back  = vertices[(i + vertices.Length - 1) % vertices.Length];
        Vector3 delta = p1 - back;

        Vector3 normal = Vector3.Cross(GetPlane().normal, delta);

        normal.Normalize();

        back  = inOther.vertices[(j + 2) % inOther.vertices.Length];
        delta = back - p1;

        float dot = Vector3.Dot(delta, normal);

        // not a convex polygon
        if (dot > GlobalSettings.Epsilonf)
        {
            return(false);
        }

        // if they are co linear
        bool keep1 = (dot < -GlobalSettings.Epsilonf);

        // ...
        back   = vertices[(i + 2) % vertices.Length];
        delta  = back - p2;
        normal = Vector3.Cross(GetPlane().normal, delta);
        normal.Normalize();

        back  = inOther.vertices[(j + inOther.vertices.Length - 1) % inOther.vertices.Length];
        delta = back - p2;
        dot   = Vector3.Dot(delta, normal);

        // not convex
        if (dot > GlobalSettings.Epsilonf)
        {
            return(false);
        }

        bool keep2 = (dot < -GlobalSettings.Epsilonf);

        bool keep = false;

        // create out face
        outFace = new CSGFace();

        outFace.flags    = flags;
        outFace.material = material;

        // copy vertices from this
        for (int k = (i + 1) % vertices.Length; k != i; k = (k + 1) % vertices.Length)
        {
            if (!keep && k == (i + 1) % vertices.Length && !keep2)
            {
                continue;
            }

            // copy vector
            outFace.AddVertex(vertices[k], uv[k]);
        }

        // copy vertices from other
        for (int k = (j + 1) % inOther.vertices.Length; k != j; k = (k + 1) % inOther.vertices.Length)
        {
            if (!keep && k == (j + 1) % inOther.vertices.Length && !keep1)
            {
                continue;
            }

            outFace.AddVertex(inOther.vertices[k], inOther.uv[k]);
        }

        return(true);
    }