// 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); } }
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; } } }
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); }