Esempio n. 1
0
    private void PerformNode(BspNode inNode, CSGFace inFace, int nodeSide, OperationInfo info)
    {
        while (inNode != null)
        {
            CSGFace.EPlaneSide side = inFace.Side(inNode.plane);

            switch (side)
            {
            case CSGFace.EPlaneSide.Side_Front:

                //
                nodeSide = nodeSide | (inNode.IsCsg() ? 1 : 0);

                // leaf node
                if (inNode.front == null)
                {
                    // set operation infos
                    info.leafNode     = inNode;
                    info.leafLocation = BspNode.EBspLocation.BspLocation_Front;

                    // we are done, process face
                    ProcessFace(inFace, SIDE_Outside, info);
                }

                // get to next front node (if any)
                inNode = inNode.front;

                break;

            case CSGFace.EPlaneSide.Side_Back:

                int backSide = inNode.IsCsg() ? 0 : 1;
                //
                nodeSide = nodeSide & backSide;

                // leaf node
                if (inNode.back == null)
                {
                    // set leaf infos
                    info.leafNode     = inNode;
                    info.leafLocation = BspNode.EBspLocation.BspLocation_Back;

                    // we are done, process face
                    ProcessFace(inFace, SIDE_Inside, info);
                }

                // get to next front node (if any)
                inNode = inNode.back;
                break;

            case CSGFace.EPlaneSide.Side_Split:

                // split face and process front and back
                CSGFace frontFace, backFace;

                //
                inFace.Split(inNode.plane, out frontFace, out backFace);

                // TODO: set polygon cutted flags
                frontFace.flags |= CSGFace.FaceFlags_WasCutted;
                backFace.flags  |= CSGFace.FaceFlags_WasCutted;


                // front node is a leaf node
                if (inNode.front == null)
                {
                    //
                    info.leafNode     = inNode;
                    info.leafLocation = BspNode.EBspLocation.BspLocation_Front;


                    ProcessFace(frontFace, SIDE_Outside, info);
                }
                else
                {
                    PerformNode(inNode.front, frontFace, nodeSide, info);
                }

                // Prcess back node with back face
                if (inNode.back == null)
                {
                    //
                    info.leafNode     = inNode;
                    info.leafLocation = BspNode.EBspLocation.BspLocation_Back;


                    ProcessFace(backFace, SIDE_Inside, info);
                }
                else
                {
                    // process back node with new face
                    PerformNode(inNode.back, backFace, nodeSide, info);
                }

                // stop loop
                inNode = null;
                break;

            case CSGFace.EPlaneSide.Side_Planar:

                BspNode front, back;

                if (info.wasPlanar == true)
                {
                    Debug.Log("Reentering Planar Nodes!");
                }


                // set operation infos
                info.wasPlanar      = true;
                info.backNode       = null;
                info.processingBack = false;

                if (Vector3.Dot(inFace.GetPlane().normal, inNode.plane.normal) >= 0.0f)
                {
                    // same order as we face in the same order
                    front = inNode.front;
                    back  = inNode.back;

                    // we are for now outside (as we are looking outside)
                    info.planarSide = SIDE_Outside;
                }
                else
                {
                    // reverse order as we are facing in the opposite direction
                    front = inNode.back;
                    back  = inNode.front;

                    // we are now inside as we are looking to the inside
                    info.planarSide = SIDE_Inside;
                }

                // we are leaf node (coplanar face)
                if (front == null && back == null)
                {
                    // set leaf stuff
                    info.leafNode     = inNode;
                    info.leafLocation = BspNode.EBspLocation.BspLocation_Planar;

                    // process node
                    info.processingBack = true;

                    // process face
                    ProcessFace(inFace, InverseSide(info.planarSide), info);

                    // stop loop
                    inNode = null;
                }
                else if (front == null && back != null)
                {
                    // only back nodes
                    info.processingBack = true;

                    // process back
                    inNode = back;
                }
                else
                {
                    // tread like we were on front side (maybe we do have a back node)
                    info.processingBack = false;

                    // remember back node
                    info.backNode = back;

                    // process front
                    inNode = front;
                }

                break;
            }
        }
    }
Esempio n. 2
0
    public static BspNode AddNodeRecursive(BspNode inNode, CSGFace inFace, int inFlags)
    {
        while (inNode != null)
        {
            CSGFace.EPlaneSide planeSide = inFace.Side(inNode.plane);

            switch (planeSide)
            {
            case CSGFace.EPlaneSide.Side_Front:

                if (inNode.front == null)
                {
                    return(AddNode(inNode, BspNode.EBspLocation.BspLocation_Front, inFace, inFlags));
                }

                inNode = inNode.front;
                break;

            case CSGFace.EPlaneSide.Side_Back:

                if (inNode.back == null)
                {
                    return(AddNode(inNode, BspNode.EBspLocation.BspLocation_Back, inFace, inFlags));
                }

                inNode = inNode.back;
                break;

            case CSGFace.EPlaneSide.Side_Planar:
                return(AddNode(inNode, BspNode.EBspLocation.BspLocation_Planar, inFace, inFlags));

            case CSGFace.EPlaneSide.Side_Split:

                CSGFace frontFace, backFace;

                inFace.Split(inNode.plane, out frontFace, out backFace);

                if (inNode.front == null)
                {
                    AddNode(inNode, BspNode.EBspLocation.BspLocation_Front, frontFace, inFlags);
                }
                else
                {
                    AddNodeRecursive(inNode.front, frontFace, inFlags);
                }

                if (inNode.back == null)
                {
                    AddNode(inNode, BspNode.EBspLocation.BspLocation_Back, inFace, inFlags);
                }
                else
                {
                    AddNodeRecursive(inNode.back, backFace, inFlags);
                }

                inNode = null;
                break;
            }
        }

        // happens when face get splitted...
        return(null);
    }
Esempio n. 3
0
    //
    void Partition(BspNode inNode, List <CSGFace> inFaces)
    {
        List <CSGFace> frontFaces = new List <CSGFace>();
        List <CSGFace> backFaces  = new List <CSGFace>();
        CSGFace        nodeFace;

        // find best splitter plane for this
        bool ret = FindSplitter(inFaces, out nodeFace);

        // return has to be true!!!
        if (ret == false)
        {
            Debug.DebugBreak();
            Debug.Log("Error processing Mesh!");
            return;
        }

        // setup node
        inNode.front  = null;
        inNode.back   = null;
        inNode.planar = null;
        inNode.face   = nodeFace;
        inNode.plane  = nodeFace.GetPlane();


        // split remaining faces into lists
        for (int i = 0; i < inFaces.Count; ++i)
        {
            // get face
            CSGFace face = inFaces[i] as CSGFace;

            // do not process our self
            if (face == nodeFace)
            {
                continue;
            }


            CSGFace.EPlaneSide side = face.Side(inNode.plane);

            switch (side)
            {
            case CSGFace.EPlaneSide.Side_Front:
                frontFaces.Add(face);
                break;

            case CSGFace.EPlaneSide.Side_Back:
                backFaces.Add(face);
                break;

            case CSGFace.EPlaneSide.Side_Planar:
                // get last planar node
                BspNode lastPlanar = inNode;
                while (lastPlanar.planar != null)
                {
                    lastPlanar = lastPlanar.planar;
                }

                // create new planar node
                BspNode planar = lastPlanar.planar = new BspNode();

                // setup planar node
                planar.front  = null;
                planar.back   = null;
                planar.planar = null;
                planar.face   = face;
                planar.plane  = face.GetPlane();

                break;

            case CSGFace.EPlaneSide.Side_Split:
                // TODO...
                CSGFace front, back;
                // split face into two parts...
                ret = face.Split(inNode.plane, out front, out back);

                if (ret == false)
                {
                    Debug.DebugBreak();
                }

                // add to front and back
                frontFaces.Add(front);
                backFaces.Add(back);
                break;
            }
        }

        // optimizing a bit, clear in array list as we do not need it any more
        inFaces.Clear();

        // process front faces
        if (frontFaces.Count > 0)
        {
            inNode.front = new BspNode();
            // partition front faces
            Partition(inNode.front, frontFaces);
        }


        // process back faces
        if (backFaces.Count > 0)
        {
            inNode.back = new BspNode();
            // partition back faces
            Partition(inNode.back, backFaces);
        }
    }
Esempio n. 4
0
    //
    bool FindSplitter(List <CSGFace> inFaces, out CSGFace outFace)
    {
        int increase  = 1;
        int bestValue = 9999999;

        // reset out face...
        outFace = null;

        // setup optimization...
        switch (bspOptm)
        {
        case BspOptm_Worse:
            increase = Mathf.Max(1, inFaces.Count / 24);
            break;

        case BspOptm_Average:
            increase = Mathf.Max(1, inFaces.Count / 12);
            break;

        case BspOptm_Best:
        default:
            increase = 1;
            break;
        }

        // find best splitter plane
        for (int i = 0; i < inFaces.Count; i += increase)
        {
            // statistics
            int numSplits = 0, numFront = 0, numBack = 0, numPlanar = 0;

            //
            CSGFace splitterFace = inFaces[i] as CSGFace;

            //
            Plane splitterPlane = splitterFace.GetPlane();

            // sort all faces to side where it lies...
            for (int j = 0; j < inFaces.Count; ++j)
            {
                CSGFace.EPlaneSide side = (inFaces[j] as CSGFace).Side(splitterPlane);

                switch (side)
                {
                case CSGFace.EPlaneSide.Side_Front:
                    numFront++;
                    break;

                case CSGFace.EPlaneSide.Side_Back:
                    numBack++;
                    break;

                case CSGFace.EPlaneSide.Side_Planar:
                    numPlanar++;
                    break;

                case CSGFace.EPlaneSide.Side_Split:
                    numSplits++;
                    break;

                default:
                    //ERROR
                    Debug.DebugBreak();
                    break;
                }
            }

            //
            int val = numSplits * 5 + Mathf.Abs(numFront - numBack) + numPlanar;

            if (val < bestValue)
            {
                bestValue = val;
                outFace   = splitterFace;
            }
        }

        // if we have a face found, return true
        return(outFace != null);
    }