Esempio n. 1
0
    public static void DumpTree(BspNode inNode)
    {
        Debug.Log("Node...");

        Debug.Log("Planar Nodes");
        BspNode planar = inNode.planar;

        while (planar != null)
        {
            Debug.Log("Planar Node");
            planar = planar.planar;
        }

        if (inNode.front != null)
        {
            Debug.Log("FrontSide");
            DumpTree(inNode.front);
        }

        if (inNode.back != null)
        {
            Debug.Log("BackSide");
            DumpTree(inNode.back);
        }
    }
Esempio n. 2
0
    //
    public static void GetFaces(BspNode inNode, List <Face> outFaces)
    {
        while (inNode != null)
        {
            // if we are not destroyed
            if ((inNode.flags & BspNode.BspFlags_IsDestroyed) == 0)
            {
                // add to array list
                outFaces.Add(inNode.face);
            }


            if (inNode.front != null)
            {
                GetFaces(inNode.front, outFaces);
            }

            if (inNode.back != null)
            {
                GetFaces(inNode.back, outFaces);
            }

            // get to the next planar node
            inNode = inNode.planar;
        }
    }
Esempio n. 3
0
        public override void Initialize(int index, int id, int size, byte[] data,
                                        Dictionary <int, WldFragment> fragments,
                                        Dictionary <int, string> stringHash, ILogger logger)
        {
            base.Initialize(index, id, size, data, fragments, stringHash, logger);

            var reader = new BinaryReader(new MemoryStream(data));

            Name = stringHash[-reader.ReadInt32()];

            int nodeCount = reader.ReadInt32();

            Nodes = new List <BspNode>();

            for (int i = 0; i < nodeCount; ++i)
            {
                var node = new BspNode()
                {
                    NormalX       = reader.ReadSingle(),
                    NormalY       = reader.ReadSingle(),
                    NormalZ       = reader.ReadSingle(),
                    SplitDistance = reader.ReadSingle(),
                    RegionId      = reader.ReadInt32(),
                    LeftNode      = reader.ReadInt32(),
                    RightNode     = reader.ReadInt32()
                };

                Nodes.Add(node);
            }
        }
Esempio n. 4
0
    public static BspNode AddNode(BspNode inParent, BspNode.EBspLocation inLocation, Face inFace, int inFlags)
    {
        BspNode newNode = new BspNode();

        newNode.plane = inFace.GetPlane();
        newNode.face  = inFace;
        newNode.front = newNode.back = newNode.planar = null;
        newNode.flags = inFlags;

        if (inLocation == BspNode.EBspLocation.BspLocation_Front)
        {
            // check that front node is null
            inParent.front = newNode;
        }
        else if (inLocation == BspNode.EBspLocation.BspLocation_Back)
        {
            // TODO: check that back node is null
            inParent.back = newNode;
        }
        else if (inLocation == BspNode.EBspLocation.BspLocation_Planar)
        {
            // go to the last planar node
            BspNode lastPlanar = inParent;

            while (lastPlanar.planar != null)
            {
                lastPlanar = lastPlanar.planar;
            }

            // add planar node
            lastPlanar.planar = newNode;
        }

        return(newNode);
    }
Esempio n. 5
0
        private void ExecuteSplitFinalization()
        {
            WorkItem currentWorkItem = workItems.Pop();

            BspNode parentNode = currentWorkItem.Node;
            BspNode leftChild  = new BspNode();
            BspNode rightChild = new BspNode();

            parentNode.SetChildren(leftChild, rightChild);
            parentNode.Splitter = SplitCalculator.States.BestSplitter;

            List <BspSegment> rightSegs = Partitioner.States.RightSegments;
            List <BspSegment> leftSegs  = Partitioner.States.LeftSegments;

            rightSegs.AddRange(MinisegCreator.States.Minisegs);
            leftSegs.AddRange(MinisegCreator.States.Minisegs);

            string path = currentWorkItem.BranchPath;

            if (BspConfig.BranchRight)
            {
                workItems.Push(new WorkItem(leftChild, leftSegs, path + "L"));
                workItems.Push(new WorkItem(rightChild, rightSegs, path + "R"));
            }
            else
            {
                workItems.Push(new WorkItem(rightChild, rightSegs, path + "R"));
                workItems.Push(new WorkItem(leftChild, leftSegs, path + "L"));
            }

            LoadNextWorkItem();
        }
Esempio n. 6
0
    public static IEnumerable <int> GetNodeLeafs(ValveBspFile bsp, BspNode node)
    {
        if (node.ChildA.IsLeaf)
        {
            yield return(node.ChildA.Index);
        }
        else
        {
            foreach (var leaf in GetNodeLeafs(bsp, bsp.Nodes[node.ChildA.Index]))
            {
                yield return(leaf);
            }
        }

        if (node.ChildB.IsLeaf)
        {
            yield return(node.ChildB.Index);
        }
        else
        {
            foreach (var leaf in GetNodeLeafs(bsp, bsp.Nodes[node.ChildB.Index]))
            {
                yield return(leaf);
            }
        }
    }
Esempio n. 7
0
	public static void DumpTree( BspNode inNode )
	{
		Debug.Log( "Node..." );
		
		Debug.Log( "Planar Nodes" );
		BspNode planar = inNode.planar;
		while( planar != null )
		{
			Debug.Log( "Planar Node" );
			planar = planar.planar;
		}
		
		if( inNode.front != null )
		{
			Debug.Log( "FrontSide" );
			DumpTree( inNode.front );
		}
		
		if( inNode.back != null )
		{
			Debug.Log( "BackSide" );
			DumpTree( inNode.back );	
		}
		
	}
Esempio n. 8
0
        /// <summary>
        /// Combine this mesh with another.
        /// </summary>
        /// <param name="anotherMesh">Another mesh.</param>
        /// <seealso cref="ConstructiveSolidGeometry.Union"/>
        public virtual void Combine(IMesh anotherMesh)
        {
            BspNode <SplittableTriangle> a = this.ToBspTree();
            BspNode <SplittableTriangle> b = anotherMesh.ToBspTree();

            a.Unite(b);
            this.SetBsp(a);
        }
Esempio n. 9
0
        /// <summary>
        /// Creates a new work item that can be operated on in a BSP pass.
        /// </summary>
        /// <param name="node">The node to be operated on.</param>
        /// <param name="segments">The list of segments for this work item.
        /// </param>
        /// <param name="branchPath">The path taken to get here. This should be
        /// upper case.</param>
        public WorkItem(BspNode node, List <BspSegment> segments, string branchPath = "")
        {
            Debug.Assert(segments.Count > 0, "Should never have zero segments for a work item");
            Debug.Assert(branchPath == branchPath.ToUpper(), "Should be using upper case BSP branch paths");

            Node       = node;
            Segments   = segments;
            BranchPath = branchPath;
        }
Esempio n. 10
0
        /// <summary>
        /// Subtracts another mesh from this one.
        /// </summary>
        /// <param name="anotherMesh">Another mesh.</param>
        /// <seealso cref="ConstructiveSolidGeometry.Subtract"/>
        public virtual void Subtract(IMesh anotherMesh)
        {
            BspNode <SplittableTriangle> a = this.ToBspTree();
            BspNode <SplittableTriangle> b = anotherMesh.ToBspTree();

            a.Invert();
            a.Unite(b);
            a.Invert();
            this.SetBsp(a);
        }
Esempio n. 11
0
    //
    private void PerformFaces(BspNode inRoot, List <CSGFace> inFaces)
    {
        for (int i = 0; i < inFaces.Count; ++i)
        {
            OperationInfo info;
            InitializeOper(out info);

            PerformNode(inRoot, inFaces[i] as CSGFace, SIDE_Outside, info);
        }
    }
Esempio n. 12
0
    private void PerformTree(BspNode inNode, BspNode inOtherRoot)
    {
        while (inNode != null)
        {
            // if we are new, stop processing our node...
            if ((inNode.flags & BspNode.BspFlags_IsNew) != 0)
            {
                return;
            }

            // if we are not destroyed
            if ((inNode.flags & BspNode.BspFlags_IsDestroyed) == 0)
            {
                OperationInfo info;
                InitializeOper(out info);

                // save current node
                currentNode = inNode;

                // find last coplanar node
                BspNode lastPlanar = inNode;
                while (lastPlanar.planar != null)
                {
                    lastPlanar = lastPlanar.planar;
                }

                // perform nodes face with other tree
                PerformNode(inOtherRoot, inNode.face, SIDE_Outside, info);

                // nobody removed us
                if ((inNode.flags & BspNode.BspFlags_IsDestroyed) == 0)
                {
                    // remove all planar nodes added (if any)
                    lastPlanar.planar = null;
                }
            }


            // process front node
            if (inNode.front != null)
            {
                PerformTree(inNode.front, inOtherRoot);
            }

            // process back node
            if (inNode.back != null)
            {
                PerformTree(inNode.back, inOtherRoot);
            }

            // process next planar node
            inNode = inNode.planar;
        }
    }
Esempio n. 13
0
 //
 void RouteOper(BspNode inNode, CSGFace inFace, EPolySide inSide, OperationInfo info)
 {
     if (processState == EProcessState.Process_Master)
     {
         csgVisitor.ProcessMaster(this, inFace, inSide, info);
     }
     else
     {
         csgVisitor.ProcessSlave(this, inFace, inSide, info);
     }
 }
Esempio n. 14
0
        public static BspNode ReadBspNode(this BinaryReader br)
        {
            var result = new BspNode();

            result.plane            = br.ReadInt32();
            result.frontChild       = br.ReadInt16();
            result.backChild        = br.ReadInt16();
            br.BaseStream.Position += 16;

            return(result);
        }
Esempio n. 15
0
        private Collision CheckNode(int nodeIdx, Point3D start, Vector movement, float startFraction, float endFraction, float sphere)
        {
            // calculate start and end point
            Point3D s = start + movement * startFraction;
            Point3D e = start + movement * endFraction;

            // if this node is a leaf, check for collision within that leaf
            if (nodeIdx < 0)
            {
                return(CheckLeaf(~nodeIdx, start, movement, startFraction, endFraction, sphere));
            }

            // get node
            BspNode node = Nodes[nodeIdx];

            // get splitting plane
            Plane plane = Planes[node.plane];

            // calculate distance of start and end point to plane
            float ds = plane.Distance(s);
            float de = plane.Distance(e);

            if (ds > sphere && de > sphere)
            {
                // both points are in front of the plane
                return(CheckNode(node.frontChild, start, movement, startFraction, endFraction, sphere));
            }
            else if (ds < -sphere && de < -sphere)
            {
                // both points are behind the plane
                return(CheckNode(node.backChild, start, movement, startFraction, endFraction, sphere));
            }
            else
            {
                float f1, f2;

                float ads  = System.Math.Abs(ds);
                float ade  = System.Math.Abs(de);
                float ad   = ads + ade;
                float frac = endFraction - startFraction;

                f1 = frac * (ads + sphere) / ad + collisionMargin;
                f2 = frac * (ade + sphere) / ad + collisionMargin;

                Collision c1 = CheckNode(node.frontChild, start, movement, startFraction, startFraction + f1, sphere);
                Collision c2 = CheckNode(node.backChild, start, movement, endFraction - f2, endFraction, sphere);

                return(ClosestCollision(c1, c2));
            }
        }
Esempio n. 16
0
        /// <summary>
        /// Sets this mesh to value based on given BSP tree.
        /// </summary>
        /// <param name="tree">Root node of the BSP tree.</param>
        public override void SetBsp(BspNode <SplittableTriangle> tree)
        {
            // Calculate capacities.

            // Create vertex pool.
            List <SplittableTriangle> triangles      = tree.AllElements;
            List <MeshVertex>         vertexes       = new List <MeshVertex>(triangles.Count * 3);
            Action <MeshVertex>       registerVertex = delegate(MeshVertex vertex)
            {
                int index = vertexes.BinarySearch(vertex);
                if (index < 0)
                {
                    vertexes.Insert(~index, vertex);
                }
            };

            for (int i = 0; i < triangles.Count; i++)
            {
                registerVertex(triangles[i].First);
                registerVertex(triangles[i].Second);
                registerVertex(triangles[i].Third);
            }
            // Assign faces.
            this.faces.Capacity = triangles.Count;
            for (int i = 0; i < triangles.Count; i++)
            {
                this.faces[i] = new IndexedTriangleFace
                {
                    Indices = new Int32Vector3
                              (
                        vertexes.BinarySearch(triangles[i].First),
                        vertexes.BinarySearch(triangles[i].Second),
                        vertexes.BinarySearch(triangles[i].Third)
                              )
                };
            }
            // Assign vertex-related data.
            this.positions.Capacity = vertexes.Count;
            for (int i = 0; i < vertexes.Count; i++)
            {
                MeshVertex vertex = vertexes[i];
                this.positions[i] = vertex.Position;
                this.normals[i]   = vertex.Normal;
                this.texCoords[i] = vertex.UvMapPosition;
                this.colors0[i]   = vertex.PrimaryColor;
                this.colors1[i]   = vertex.SecondaryColor;
            }
        }
Esempio n. 17
0
        /// <summary>
        /// Intersects this mesh with another.
        /// </summary>
        /// <param name="anotherMesh">Another mesh.</param>
        /// <seealso cref="ConstructiveSolidGeometry.Intersection"/>
        public virtual void Intersect(IMesh anotherMesh)
        {
            BspNode <SplittableTriangle> a = this.ToBspTree();
            BspNode <SplittableTriangle> b = anotherMesh.ToBspTree();

            a.Invert();                                 // Cut geometry that is not common for the meshes.
            b.CutTreeOut(a);                            //
            b.Invert();                                 //
            a.CutTreeOut(b);                            //
            // Clean up remains.
            b.CutTreeOut(a);
            // Combine geometry.
            a.AddElements(b.AllElements);
            // Invert everything.
            a.Invert();
            this.SetBsp(a);
        }
Esempio n. 18
0
            public void Split(int minimumRoomSize)
            {
                int direction = -1;

                if (Size.Width > Size.Height)
                {
                    direction = 0;
                }
                else if (Size.Height > Size.Width)
                {
                    direction = 1;
                }
                else
                {
                    direction = Program.Game.Random.Next(2);
                }

                if (direction == 0)
                {
                    var childRoomWidth = (Size.Width / 2) + Program.Game.Random.Next(-3, 4);

                    if (childRoomWidth >= minimumRoomSize && Size.Width - childRoomWidth >= minimumRoomSize)
                    {
                        ChildA = new BspNode(this, new Rectangle(Size.Left, Size.Top, childRoomWidth, Size.Height));
                        ChildA.Split(minimumRoomSize);

                        ChildB = new BspNode(this, new Rectangle(Size.Left + childRoomWidth, Size.Top, Size.Width - childRoomWidth, Size.Height));
                        ChildB.Split(minimumRoomSize);
                    }
                }
                else
                {
                    var childRoomHeight = (Size.Height / 2) + Program.Game.Random.Next(-3, 4);

                    if (childRoomHeight >= minimumRoomSize && Size.Height - childRoomHeight >= minimumRoomSize)
                    {
                        ChildA = new BspNode(this, new Rectangle(Size.Left, Size.Top, Size.Width, childRoomHeight));
                        ChildA.Split(minimumRoomSize);

                        ChildB = new BspNode(this, new Rectangle(Size.Left, Size.Top + childRoomHeight, Size.Width, Size.Height - childRoomHeight));
                        ChildB.Split(minimumRoomSize);
                    }
                }
            }
Esempio n. 19
0
    //
    public void Perform(ECsgOperation inOper, CSGObject inMaster, CSGObject inSlave)
    {
        // we are processing our slave faces
        processState = EProcessState.Process_Slave;

        // process faces against master tree
        PerformFaces(inMaster.rootNode, inSlave.faces);

        // process face from master tree
        processState = EProcessState.Process_Master;

        // perform master faces on slave bsp tree
        PerformTree(inMaster.rootNode, inSlave.rootNode);

        // check if how do we need to process generated faces
        if (inOper == ECsgOperation.CsgOper_Additive || inOper == ECsgOperation.CsgOper_Subtractive)
        {
            // add deferred faces to master tree...
            for (int i = 0; i < deferredFaces.Count; i++)
            {
                CSGFace defFace   = ((DeferredFace)deferredFaces[i]).face;
                BspNode startNode = ((DeferredFace)deferredFaces[i]).node;

                // testing
                startNode = inMaster.rootNode;
                // add node to master tree
                BspGen.AddNodeRecursive(startNode, defFace, BspNode.BspFlags_IsNew);
            }
        }
        else
        {
            // clear old faces list
            inMaster.faces.Clear();

            // copy created faces
            for (int i = 0; i < deferredFaces.Count; i++)
            {
                inMaster.faces.Add(deferredFaces[i].face);
            }
        }

        // clear deferred faces
        deferredFaces.Clear();
    }
Esempio n. 20
0
	public static void FacesFromNodes( BspNode inNode, List<Face> outFaces )
	{
		while( inNode != null )
		{
			if( (inNode.flags & BspNode.BspFlags_IsDestroyed) == 0 )
			{
				outFaces.Add( inNode.face );	
			}
			
			if( inNode.front != null )
				FacesFromNodes( inNode.front, outFaces );
			
			if( inNode.back != null )
				FacesFromNodes( inNode.back, outFaces );
			
			// 
			inNode = inNode.planar;
		}
	}
Esempio n. 21
0
        public override Map Generate(int width, int height)
        {
            var map = new Map(width, height);

            rooms = new List <Rectangle>();

            var entireMap = new Rectangle(0, 0, map.Width, map.Height);

            var root = new BspNode(null, entireMap);

            root.Split(MinimumRoomSize);

            CreateRooms(root, map);

            var spawnRoom = root.GetRoom();

            Program.Game.Player.X = spawnRoom.Center.X;
            Program.Game.Player.Y = spawnRoom.Center.Y;

            var stairsRoom = rooms.Last();

            var stairs = ItemFactory.CreateStairs(stairsRoom.Center.X, stairsRoom.Center.Y, Program.Game.DungeonLevel);

            Program.Game.Entities.Add(stairs);

            foreach (var room in rooms)
            {
                // Don't spawn monsters in the player's room.
                if (room != spawnRoom)
                {
                    SpawnMonsters(room);
                }

                SpawnItems(map, room);
            }

            return(map);
        }
Esempio n. 22
0
	// 
	public BspNode GenerateBspTree( List<Face> inFaces )
	{
		if( inFaces == null )
		{
			Debug.Log("Not able to create Tree with no Faces");
			return null;
		}
		
		Debug.Log( "Building Bsp Tree for " + inFaces.Count + " Faces" );
		
		// create root node
		BspNode root = new BspNode();
		// partition all faces
		Partition( root, inFaces );
		
		// copy bsp faces back to array list (resulting faces...)
		GetFaces( root, inFaces );
		
		Debug.Log( "Resulting in " + inFaces.Count + " Faces" );
		
		// result
		return root;
	}
Esempio n. 23
0
    public static void FacesFromNodes(BspNode inNode, List <CSGFace> outFaces)
    {
        while (inNode != null)
        {
            if ((inNode.flags & BspNode.BspFlags_IsDestroyed) == 0)
            {
                outFaces.Add(inNode.face);
            }

            if (inNode.front != null)
            {
                FacesFromNodes(inNode.front, outFaces);
            }

            if (inNode.back != null)
            {
                FacesFromNodes(inNode.back, outFaces);
            }

            //
            inNode = inNode.planar;
        }
    }
Esempio n. 24
0
    //
    public BspNode GenerateBspTree(List <Face> inFaces)
    {
        if (inFaces == null)
        {
            Debug.Log("Not able to create Tree with no Faces");
            return(null);
        }

        Debug.Log("Building Bsp Tree for " + inFaces.Count + " Faces");

        // create root node
        BspNode root = new BspNode();

        // partition all faces
        Partition(root, inFaces);

        // copy bsp faces back to array list (resulting faces...)
        GetFaces(root, inFaces);

        Debug.Log("Resulting in " + inFaces.Count + " Faces");

        // result
        return(root);
    }
Esempio n. 25
0
 public static void Serialize(SerializingContainer2 sc, ref BspNode node)
 {
     if (sc.IsLoading)
     {
         node = new BspNode();
     }
     sc.Serialize(ref node.Plane);
     sc.Serialize(ref node.iVertPool);
     sc.Serialize(ref node.iSurf);
     sc.Serialize(ref node.iVertexIndex);
     sc.Serialize(ref node.ComponentIndex);
     sc.Serialize(ref node.ComponentNodeIndex);
     sc.Serialize(ref node.ComponentElementIndex);
     sc.Serialize(ref node.iBack);
     sc.Serialize(ref node.iFront);
     sc.Serialize(ref node.iPlane);
     sc.Serialize(ref node.iCollisionBound);
     sc.Serialize(ref node.iZone0);
     sc.Serialize(ref node.iZone1);
     sc.Serialize(ref node.NumVertices);
     sc.Serialize(ref node.NodeFlags);
     sc.Serialize(ref node.iLeaf0);
     sc.Serialize(ref node.iLeaf1);
 }
Esempio n. 26
0
	public static void MergeCoplanars( BspNode inNode )
	{
		// proceed front nodes
		if( inNode.front != null )
			MergeCoplanars( inNode.front );
		
		// proceed back nodes
		if( inNode.back != null )
			MergeCoplanars( inNode.back );
		
		// first try to merge other co planar nodes
		if( inNode.planar != null )
			MergeCoplanars( inNode.planar );
		
		// 
		bool tryToMerge = (inNode.flags & BspNode.BspFlags_IsDestroyed) == 0;
		
		while( tryToMerge )
		{
			// get planar node
			BspNode planarNode = inNode.planar;
			
			// assume we are done
			tryToMerge = false;
			
			// get through all planar nodes
			while( planarNode != null )
			{
				// if we are destroyed, proceed to next
				if( (planarNode.flags & BspNode.BspFlags_IsDestroyed) != 0 )
				{
					// proceed to next
					planarNode = planarNode.planar;
					continue;
				}
				
				
				Face thisFace = inNode.face;
				Face otherFace = planarNode.face;
				
				// are we facing the same direction
				if( Vector3.Dot( thisFace.GetPlane().normal, otherFace.GetPlane().normal ) > 0.995f )
				{
					// result
					Face merged;
					
					// 
					if( thisFace.Merge( otherFace, out merged ) )
					{
						// replace this face with merged
						thisFace = merged;
						
						// set other node as destroyed
						planarNode.flags |= BspNode.BspFlags_IsDestroyed;
						
						// retry to merge
						tryToMerge = true;
					}	
				}
				
				// proceed to next
				planarNode = planarNode.planar;				
			}
			
		}
		
		
	}
Esempio n. 27
0
 public BspNode(BspNode parent, Rectangle size)
 {
     Parent = parent;
     Size   = size;
 }
Esempio n. 28
0
	// 
	public static void GetFaces( BspNode inNode, List<Face> outFaces )
	{
		while( inNode != null )
		{
			// if we are not destroyed
			if( (inNode.flags & BspNode.BspFlags_IsDestroyed) == 0 )
			{
				// add to array list
				outFaces.Add( inNode.face );
			}
			
			
			if( inNode.front != null )
			{
				GetFaces( inNode.front, outFaces );	
			}
			
			if( inNode.back != null )
			{
				GetFaces( inNode.back, outFaces );	
			}
			
			// get to the next planar node
			inNode = inNode.planar;
		}
	}
Esempio n. 29
0
 /// <summary>
 /// When implemented, changes this mesh to be perfect representation of the given BSP tree.
 /// </summary>
 /// <param name="tree">BSP tree to convert to this mesh.</param>
 public abstract void SetBsp(BspNode <SplittableTriangle> tree);
Esempio n. 30
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. 31
0
        /// <summary>
        /// Combines two BSP trees using a specified CSG operation
        /// </summary>
        private static BspNode Combine( Operation op, BspNode set0, BspNode set1 )
        {
            IList< Edge > set0Edges = Flatten( set0 );
            IList< Edge > set1Edges = Flatten( set1 );

            List< Edge > sourceEdges = new List<Edge>( );

            switch ( op )
            {
                case Operation.Union :
                    Clip( true, false, set0, set1Edges, sourceEdges );
                    Clip( true, false, set1, set0Edges, sourceEdges );
                    break;

                case Operation.EdgeUnion :
                    Clip( false, true, set0, set1Edges, sourceEdges );

                    foreach ( Edge edge in sourceEdges )
                    {
                        edge.DoubleSided = true;
                    }
                    sourceEdges.AddRange( set0Edges );
                    break;

                case Operation.Intersection :
                    Clip( false, true, set0, set1Edges, sourceEdges );
                    Clip( false, true, set1, set0Edges, sourceEdges );
                    break;

                case Operation.Complement :
                    Clip( false, true, set0, set1Edges, sourceEdges );
                    Clip( false, true, set1, set0Edges, sourceEdges );
                    break;
            }

            sourceEdges = MergeEdges( sourceEdges );
            BspNode rootNode = BuildNode( null, sourceEdges );

            return rootNode;
        }
Esempio n. 32
0
        /// <summary>
        /// Builds a BSP node from a list of edges
        /// </summary>
        private static BspNode BuildNode( BspNode parentNode, IList< Edge > edges )
        {
            if ( edges.Count == 0 )
            {
                return null;
            }

            Edge splitter = edges[ 0 ]; // TODO: AP: Choose better splitter
            BspNode splitNode = new BspNode( parentNode, splitter );
            if ( edges.Count == 1 )
            {
                return splitNode;
            }

            //	Classify edges as left or right edges
            List< Edge > outsideEdges = new List< Edge >( );
            List< Edge > insideEdges = new List< Edge >( );
            for ( int edgeIndex = 1; edgeIndex < edges.Count; ++edgeIndex )
            {
                ClassifyEdge( splitter, edges[ edgeIndex ], outsideEdges, insideEdges );
            }

            //	Build BSP subtrees from left and right edges
            if ( outsideEdges.Count > 0 )
            {
                splitNode.Behind = BuildNode( splitNode, outsideEdges );
            }
            if ( insideEdges.Count > 0 )
            {
                splitNode.InFront = BuildNode( splitNode, insideEdges );
            }

            return splitNode;
        }
Esempio n. 33
0
 /// <summary>
 /// Flattens a BSP tree into a list of edges
 /// </summary>
 private static void Flatten( BspNode root, IList< Edge > edges )
 {
     if ( !root.Edge.Temporary )
     {
         edges.Add( root.Edge );
     }
     if ( root.Behind != null )
     {
         Flatten( root.Behind, edges );
     }
     if ( root.InFront != null )
     {
         Flatten( root.InFront, edges );
     }
 }
Esempio n. 34
0
        /// <summary>
        /// Sets this mesh to value based on given BSP tree.
        /// </summary>
        /// <param name="tree">Root node of the BSP tree.</param>
        public override void SetBsp(BspNode<SplittableTriangle> tree)
        {
            // Calculate capacities.

            // Create vertex pool.
            List<SplittableTriangle> triangles = tree.AllElements;
            List<MeshVertex> vertexes = new List<MeshVertex>(triangles.Count * 3);
            Action<MeshVertex> registerVertex = delegate(MeshVertex vertex)
            {
                int index = vertexes.BinarySearch(vertex);
                if (index < 0)
                {
                    vertexes.Insert(~index, vertex);
                }
            };
            for (int i = 0; i < triangles.Count; i++)
            {
                registerVertex(triangles[i].First);
                registerVertex(triangles[i].Second);
                registerVertex(triangles[i].Third);
            }
            // Assign faces.
            this.faces.Capacity = triangles.Count;
            for (int i = 0; i < triangles.Count; i++)
            {
                this.faces[i] = new IndexedTriangleFace
                {
                    Indices = new Int32Vector3
                    (
                        vertexes.BinarySearch(triangles[i].First),
                        vertexes.BinarySearch(triangles[i].Second),
                        vertexes.BinarySearch(triangles[i].Third)
                    )
                };
            }
            // Assign vertex-related data.
            this.positions.Capacity = vertexes.Count;
            for (int i = 0; i < vertexes.Count; i++)
            {
                MeshVertex vertex = vertexes[i];
                this.positions[i] = vertex.Position;
                this.normals[i] = vertex.Normal;
                this.texCoords[i] = vertex.UvMapPosition;
                this.colors0[i] = vertex.PrimaryColor;
                this.colors1[i] = vertex.SecondaryColor;
            }
        }
Esempio n. 35
0
	// 
	void Partition( BspNode inNode, List<Face> inFaces )
	{
		List<Face> frontFaces = new List<Face>();
		List<Face> backFaces = new List<Face>();
		Face 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
			Face face = inFaces[i] as Face;
			
			// do not process our self
			if( face == nodeFace )
				continue;
			
			
			Face.EPlaneSide side = face.Side( inNode.plane );
			
			switch( side )
			{
			case Face.EPlaneSide.Side_Front:
				frontFaces.Add( face );
				break;
			case Face.EPlaneSide.Side_Back:
				backFaces.Add( face );
				break;
			case Face.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 Face.EPlaneSide.Side_Split:
				// TODO...
				Face 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. 36
0
	/// <summary>
	/// Performs CSG Operation on this Object (Master) with given Slaves.
	/// </summary>
	/// <param name='inOper'>
	/// In oper.
	/// </param>
	/// <param name='inSlaves'>
	/// In slaves.
	/// </param>
	public void PerformCSG( CsgOperation.ECsgOperation inOper, GameObject[] inSlaves )
	{
		// 
		CreateFromMesh();
		
		// create bsp generator
		BspGen gen = new BspGen( GlobalSettings.BspOptimization );
				
		rootNode = gen.GenerateBspTree( faces );
		
		List<Face> savedFaces = new List<Face>();
		
		// 
  		foreach ( GameObject g in inSlaves )
  		{
			CSGObject slave = g.GetComponent<CSGObject>();
			
			// if we have a csg object and we are not our self
			// and intersecting
			if( slave && g != gameObject && intersect(slave) )
			{	
       			Debug.Log(g.name);
				
				// 
				slave.CreateFromMesh();
				
				// ....
				BspGen genSlave = new BspGen( GlobalSettings.BspOptimization );
				slave.rootNode = genSlave.GenerateBspTree( slave.faces );
				
				CsgVisitor visitor = null;
				
				switch( inOper )
				{
				case CsgOperation.ECsgOperation.CsgOper_Additive:
					visitor = new UnionVisitor();
					break;
				case CsgOperation.ECsgOperation.CsgOper_Subtractive:
					visitor = new SubtractiveVisitor();
					break;
				case CsgOperation.ECsgOperation.CsgOper_Intersect:
					visitor = new IntersectVisitor();
					break;
				case CsgOperation.ECsgOperation.CsgOper_DeIntersect:
					visitor = new DeIntersectVisitor();
					break;
				default:
					visitor = null;
					break;
				}
				
				
				CsgOperation oper = new CsgOperation( visitor );
				
				oper.Perform( inOper, this, slave );
				
				// save faces
				savedFaces.AddRange( faces );
			}
  		}
		
		
		// If we want to merge Coplanars after every Operation
		if( GlobalSettings.MergeCoplanars )
		{
			MergeFaces();	
		}
  		
		// for additive or subtracte operation, built faces list from bsp tree
		// for others, use faces directly
		if( inOper == CsgOperation.ECsgOperation.CsgOper_Additive || inOper == CsgOperation.ECsgOperation.CsgOper_Subtractive )
		{
		
			// create new face list
			List<Face> newFaces = new List<Face>();
			// create faces from bsp nodes
			BspHelper.FacesFromNodes( rootNode, newFaces );
			// copy to face list
			faces = newFaces;	
			
		}
		else
		{
			// copy saved faces
			faces = savedFaces;	
		}
		
		
	//	Face.MergeCoplanars( faces );
		
		// copy to unity structure
		TransferFacesToMesh();
		
		
		// dumb tree
//		BspHelper.DumpTree( rootNode );
		
	}
Esempio n. 37
0
	//
	private void PerformFaces( BspNode inRoot, List<Face> inFaces )
	{
		for( int i = 0; i < inFaces.Count; ++i )
		{
			OperationInfo info;
			InitializeOper( out info );
			
			PerformNode( inRoot, inFaces[i] as Face, SIDE_Outside, info );
		}
	}
Esempio n. 38
0
	private void PerformTree( BspNode inNode, BspNode inOtherRoot )
	{
		while( inNode != null )
		{
			// if we are new, stop processing our node...
			if( (inNode.flags & BspNode.BspFlags_IsNew) != 0 )
				return;
			
			// if we are not destroyed
			if( (inNode.flags & BspNode.BspFlags_IsDestroyed) == 0 )
			{
				OperationInfo info;
				InitializeOper( out info );
				
				// save current node
				currentNode = inNode;
				
				// find last coplanar node
				BspNode lastPlanar = inNode;
				while( lastPlanar.planar != null )
					lastPlanar = lastPlanar.planar;
				
				// perform nodes face with other tree
				PerformNode( inOtherRoot, inNode.face, SIDE_Outside, info );
				
				// nobody removed us
				if( (inNode.flags & BspNode.BspFlags_IsDestroyed) == 0 )
				{
					// remove all planar nodes added (if any)
					lastPlanar.planar = null;
				}
			}
			
			
			// process front node
			if( inNode.front != null )
			{
				PerformTree( inNode.front, inOtherRoot );	
			}
			
			// process back node
			if( inNode.back != null )
			{
				PerformTree( inNode.back, inOtherRoot );	
			}
			
			// process next planar node
			inNode = inNode.planar;
			
		}
	}
Esempio n. 39
0
 /// <summary>
 /// Combines a brush with the current geometry set
 /// </summary>
 /// <param name="op">CSG operation</param>
 /// <param name="brush">Brush to add to the level geometry</param>
 /// <exception cref="InvalidOperationException">Thrown by convex region builder if BSP tree is internally invalid</exception>
 public void Combine( Operation op, UiPolygon brush )
 {
     BspNode brushBsp = Build( brush, op == Operation.Complement );
     BspNode newRoot = null;
     if ( m_Root == null )
     {
         if ( op == Operation.Union || op == Operation.EdgeUnion )
         {
             newRoot = brushBsp;
         }
     }
     else
     {
         newRoot = Combine( op, m_Root, brushBsp );
     }
     if ( newRoot != null )
     {
         FixUpDoubleSidedNodes( newRoot );
         BuildConvexRegions( newRoot );
         m_Root = newRoot;
     }
     if ( GeometryChanged != null )
     {
         GeometryChanged( this, null );
     }
 }
Esempio n. 40
0
        /// <summary>
        /// Builds the convex regions for a root node and all its children
        /// </summary>
        private void BuildConvexRegions( BspNode node )
        {
            //	Find the bounding box for the tree
            float[] bounds = new float[ 4 ] { float.MaxValue, float.MaxValue, float.MinValue, float.MinValue };
            GetNodeBoundingRectangle( node, bounds );

            //	Expand bounds a bit
            float boundary = 1.0f;
            bounds[ 0 ] -= boundary;
            bounds[ 1 ] -= boundary;
            bounds[ 2 ] += boundary;
            bounds[ 3 ] += boundary;

            float width = bounds[ 2 ] - bounds[ 0 ];
            float height = bounds[ 3 ] - bounds[ 1 ];

            Tesselator tess = new Tesselator( );
            Tesselator.Polygon boundingPoly = tess.CreateBoundingPolygon( bounds[ 0 ], bounds[ 1 ], width, height );

            BuildConvexRegions( node, tess, boundingPoly );

            m_Points = tess.Points.ToArray( );
        }
Esempio n. 41
0
        /// <summary>
        /// Builds the convex region for a node and its children
        /// </summary>
        private static void BuildConvexRegions( BspNode node, Tesselator tess, Tesselator.Polygon poly )
        {
            Tesselator.Polygon behindPoly;
            Tesselator.Polygon inFrontPoly;
            tess.Split( node.Plane, poly, out behindPoly, out inFrontPoly );

            if ( node.Behind != null )
            {
                BuildConvexRegions( node.Behind, tess, behindPoly );
            }
            if ( node.InFront != null )
            {
                BuildConvexRegions( node.InFront, tess, inFrontPoly );
            }
            else
            {
                node.ConvexRegion = inFrontPoly.Indices;
            }
        }
Esempio n. 42
0
            /// <summary>
            /// Sets up the node
            /// </summary>
            /// <param name="parent">Node parent</param>
            /// <param name="edge">Node edge</param>
            public BspNode( BspNode parent, Edge edge )
            {
                m_Parent = parent;
                m_Edge = edge;

                m_Quad[ 0 ] = new Point3( edge.P0.X, 0, edge.P0.Y );
                m_Quad[ 1 ] = new Point3( edge.P1.X, 0, edge.P1.Y );
                m_Quad[ 2 ] = new Point3( edge.P1.X, 5, edge.P1.Y );
                m_Quad[ 3 ] = new Point3( edge.P0.X, 5, edge.P0.Y );
            }
Esempio n. 43
0
        /// <summary>
        /// Clips a set of edges against a BSP tree
        /// </summary>
        private static void Clip( bool keepOutsideEdges, bool keepInsideEdges, BspNode node, IEnumerable< Edge > edges, IList< Edge > outputEdges )
        {
            IList< Edge > outsideEdges = ( node.Behind != null ) ? new List< Edge >( ) : ( keepOutsideEdges ? outputEdges : null );
            IList< Edge > insideEdges = ( node.InFront != null ) ? new List< Edge >( ) : ( keepInsideEdges ? outputEdges : null );

            foreach ( Edge edge in edges )
            {
                ClassifyEdge( node.Edge, edge, outsideEdges, insideEdges );
            }
            if ( node.Behind != null )
            {
                Clip( keepOutsideEdges, keepInsideEdges, node.Behind, outsideEdges, outputEdges );
            }
            if ( node.InFront != null )
            {
                Clip( keepOutsideEdges, keepInsideEdges, node.InFront, insideEdges, outputEdges );
            }
        }
Esempio n. 44
0
	// 
	void RouteOper( BspNode inNode, Face inFace, EPolySide inSide, OperationInfo info )
	{
		if( processState == EProcessState.Process_Master )
		{
		 	csgVisitor.ProcessMaster( this, inFace, inSide, info );
		}
		else
		{
			csgVisitor.ProcessSlave( this, inFace, inSide, info );
		}
	}
Esempio n. 45
0
 /// <summary>
 /// Flattens a BSP tree into a list of edges
 /// </summary>
 private static IList<Edge> Flatten( BspNode root )
 {
     List< Edge > edges = new List< Edge >( );
     Flatten( root, edges );
     return edges;
 }
Esempio n. 46
0
	private void PerformNode( BspNode inNode, Face inFace, int nodeSide, OperationInfo info )
	{
		while( inNode != null )
		{
			Face.EPlaneSide side = inFace.Side( inNode.plane );			
			
			switch( side )
			{
			case Face.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 Face.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 Face.EPlaneSide.Side_Split:
				
				// split face and process front and back
				Face frontFace, backFace;
				
				// 
				inFace.Split( inNode.plane, out frontFace, out backFace );
				
				// TODO: set polygon cutted flags
				frontFace.flags |= Face.FaceFlags_WasCutted;
				backFace.flags |= Face.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 Face.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. 47
0
        /// <summary>
        /// Gets a bounding rectangle that encompasses a BSP node and its children
        /// </summary>
        private static void GetNodeBoundingRectangle( BspNode node, float[] rect )
        {
            if ( node == null )
            {
                return;
            }

            rect[ 0 ] 	= Utils.Min( rect[ 0 ], node.Edge.P0.X, node.Edge.P1.X );
            rect[ 1 ] 	= Utils.Min( rect[ 1 ], node.Edge.P0.Y, node.Edge.P1.Y );
            rect[ 2 ] 	= Utils.Max( rect[ 2 ], node.Edge.P0.X, node.Edge.P1.X );
            rect[ 3 ] 	= Utils.Max( rect[ 3 ], node.Edge.P0.Y, node.Edge.P1.Y );

            GetNodeBoundingRectangle( node.Behind, rect );
            GetNodeBoundingRectangle( node.InFront, rect );
        }
Esempio n. 48
0
	public static BspNode AddNode( BspNode inParent, BspNode.EBspLocation inLocation, Face inFace, int inFlags )
	{
		BspNode newNode = new BspNode();
		
		newNode.plane = inFace.GetPlane();
		newNode.face = inFace;
		newNode.front = newNode.back = newNode.planar = null;
		newNode.flags = inFlags;
		
		if( inLocation == BspNode.EBspLocation.BspLocation_Front )
		{
			// check that front node is null
			inParent.front = newNode;
			
		}
		else if( inLocation == BspNode.EBspLocation.BspLocation_Back )
		{
			// TODO: check that back node is null
			inParent.back = newNode;	
		}
		else if( inLocation == BspNode.EBspLocation.BspLocation_Planar )
		{
			// go to the last planar node
			BspNode lastPlanar = inParent;
			
			while( lastPlanar.planar != null )
				lastPlanar = lastPlanar.planar;
			
			// add planar node
			lastPlanar.planar = newNode;
		}
		
		return newNode;
	}
Esempio n. 49
0
        private void FixUpDoubleSidedNodes( BspNode node )
        {
            if ( node == null )
            {
                return;
            }
            FixUpDoubleSidedNodes( node.Behind );
            FixUpDoubleSidedNodes( node.InFront );

            if ( ( node.Edge.DoubleSided ) && ( node.Behind == null ) )
            {
                node.Behind = new BspNode( node, node.Edge.MakeTemporaryFlippedEdge( ) );
            }
        }
Esempio n. 50
0
    public static BspNode AddNodeRecursive(BspNode inNode, Face inFace, int inFlags)
    {
        while (inNode != null)
        {
            Face.EPlaneSide planeSide = inFace.Side(inNode.plane);

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

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

                inNode = inNode.front;
                break;

            case Face.EPlaneSide.Side_Back:

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

                inNode = inNode.back;
                break;

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

            case Face.EPlaneSide.Side_Split:

                Face 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. 51
0
	public static BspNode AddNodeRecursive( BspNode inNode, Face inFace, int inFlags )
	{
		while( inNode != null )
		{
			Face.EPlaneSide planeSide = inFace.Side( inNode.plane );	
			
			switch( planeSide )
			{
			case Face.EPlaneSide.Side_Front:
				
				if( inNode.front == null )
					return AddNode( inNode, BspNode.EBspLocation.BspLocation_Front, inFace, inFlags );
				
				inNode = inNode.front;
				break;
			case Face.EPlaneSide.Side_Back:
				
				if( inNode.back == null )
					return AddNode( inNode, BspNode.EBspLocation.BspLocation_Back, inFace, inFlags );
				
				inNode = inNode.back;
				break;
			case Face.EPlaneSide.Side_Planar:
				return AddNode( inNode, BspNode.EBspLocation.BspLocation_Planar, inFace, inFlags );
				
			case Face.EPlaneSide.Side_Split:
				
				Face 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. 52
0
    //
    void Partition(BspNode inNode, List <Face> inFaces)
    {
        List <Face> frontFaces = new List <Face>();
        List <Face> backFaces  = new List <Face>();
        Face        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
            Face face = inFaces[i] as Face;

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


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

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

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

            case Face.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 Face.EPlaneSide.Side_Split:
                // TODO...
                Face 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. 53
0
    public static void MergeCoplanars(BspNode inNode)
    {
        // proceed front nodes
        if (inNode.front != null)
        {
            MergeCoplanars(inNode.front);
        }

        // proceed back nodes
        if (inNode.back != null)
        {
            MergeCoplanars(inNode.back);
        }

        // first try to merge other co planar nodes
        if (inNode.planar != null)
        {
            MergeCoplanars(inNode.planar);
        }

        //
        bool tryToMerge = (inNode.flags & BspNode.BspFlags_IsDestroyed) == 0;

        while (tryToMerge)
        {
            // get planar node
            BspNode planarNode = inNode.planar;

            // assume we are done
            tryToMerge = false;

            // get through all planar nodes
            while (planarNode != null)
            {
                // if we are destroyed, proceed to next
                if ((planarNode.flags & BspNode.BspFlags_IsDestroyed) != 0)
                {
                    // proceed to next
                    planarNode = planarNode.planar;
                    continue;
                }


                CSGFace thisFace  = inNode.face;
                CSGFace otherFace = planarNode.face;

                // are we facing the same direction
                if (Vector3.Dot(thisFace.GetPlane().normal, otherFace.GetPlane().normal) > 0.995f)
                {
                    // result
                    CSGFace merged;

                    //
                    if (thisFace.Merge(otherFace, out merged))
                    {
                        // replace this face with merged
                        thisFace = merged;

                        // set other node as destroyed
                        planarNode.flags |= BspNode.BspFlags_IsDestroyed;

                        // retry to merge
                        tryToMerge = true;
                    }
                }

                // proceed to next
                planarNode = planarNode.planar;
            }
        }
    }
Esempio n. 54
0
        private void CreateRooms(BspNode node, Map map)
        {
            if (node.ChildA != null || node.ChildB != null)
            {
                CreateRooms(node.ChildA, map);
                CreateRooms(node.ChildB, map);

                if (node.ChildA != null && node.ChildB != null)
                {
                    var roomA = node.ChildA.GetRoom();
                    var roomB = node.ChildB.GetRoom();

                    if (roomA.Left == roomB.Left || roomA.Right == roomB.Right)
                    {
                        if (roomA.Width >= roomB.Width)
                        {
                            map.CreateVerticalTunnel(roomA.Center.Y, roomB.Center.Y, roomB.Center.X, Tile.Floor);
                        }
                        else
                        {
                            map.CreateVerticalTunnel(roomA.Center.Y, roomB.Center.Y, roomA.Center.X, Tile.Floor);
                        }
                    }
                    else if (roomA.Top == roomB.Top || roomA.Bottom == roomB.Bottom)
                    {
                        if (roomA.Height >= roomB.Height)
                        {
                            map.CreateHorizontalTunnel(roomA.Center.X, roomB.Center.X, roomB.Center.Y, Tile.Floor);
                        }
                        else
                        {
                            map.CreateHorizontalTunnel(roomA.Center.X, roomB.Center.X, roomA.Center.Y, Tile.Floor);
                        }
                    }
                    else
                    {
                        if (roomA.Width >= roomB.Width)
                        {
                            map.CreateVerticalTunnel(roomA.Center.Y, roomB.Center.Y, roomB.Center.X, Tile.Floor);
                        }
                        else
                        {
                            map.CreateVerticalTunnel(roomA.Center.Y, roomB.Center.Y, roomA.Center.X, Tile.Floor);
                        }

                        if (roomA.Height >= roomB.Height)
                        {
                            map.CreateHorizontalTunnel(roomA.Center.X, roomB.Center.X, roomB.Center.Y, Tile.Floor);
                        }
                        else
                        {
                            map.CreateHorizontalTunnel(roomA.Center.X, roomB.Center.X, roomA.Center.Y, Tile.Floor);
                        }
                    }
                }
            }
            else
            {
                var room = new Rectangle();

                int maxShrinkX = node.Size.Width - MinimumRoomSize;
                int maxShrinkY = node.Size.Height - MinimumRoomSize;

                room.Width  = node.Size.Width - Program.Game.Random.Next(maxShrinkX);
                room.Height = node.Size.Height - Program.Game.Random.Next(maxShrinkY);

                room.X = Program.Game.Random.Next(node.Size.Left, node.Size.Right - room.Width);
                room.Y = Program.Game.Random.Next(node.Size.Top, node.Size.Bottom - room.Height);

                node.Room = room;
                rooms.Add(room);

                map.CreateRoom(room, Tile.Floor);
            }
        }
Esempio n. 55
0
    /// <summary>
    /// Performs CSG Operation on this Object (Master) with given Slaves.
    /// </summary>
    /// <param name='inOper'>
    /// In oper.
    /// </param>
    /// <param name='inSlaves'>
    /// In slaves.
    /// </param>
    public void PerformCSG(CsgOperation.ECsgOperation inOper, GameObject[] inSlaves)
    {
        //
        CreateFromMesh();

        // create bsp generator
        BspGen gen = new BspGen(GlobalSettings.BspOptimization);

        rootNode = gen.GenerateBspTree(faces);

        List <CSGFace> savedFaces = new List <CSGFace>();

        //
        foreach (GameObject g in inSlaves)
        {
            CSGObject slave = g.GetComponent <CSGObject>();

            // if we have a csg object and we are not our self
            // and intersecting
            if (slave && g != gameObject && intersect(slave))
            {
                Debug.Log(g.name);

                //
                slave.CreateFromMesh();

                // ....
                BspGen genSlave = new BspGen(GlobalSettings.BspOptimization);
                slave.rootNode = genSlave.GenerateBspTree(slave.faces);

                CsgVisitor visitor = null;

                switch (inOper)
                {
                case CsgOperation.ECsgOperation.CsgOper_Additive:
                    visitor = new UnionVisitor();
                    break;

                case CsgOperation.ECsgOperation.CsgOper_Subtractive:
                    visitor = new SubtractiveVisitor();
                    break;

                case CsgOperation.ECsgOperation.CsgOper_Intersect:
                    visitor = new IntersectVisitor();
                    break;

                case CsgOperation.ECsgOperation.CsgOper_DeIntersect:
                    visitor = new DeIntersectVisitor();
                    break;

                default:
                    visitor = null;
                    break;
                }


                CsgOperation oper = new CsgOperation(visitor);

                oper.Perform(inOper, this, slave);

                // save faces
                savedFaces.AddRange(faces);
            }
        }


        // If we want to merge Coplanars after every Operation
        if (GlobalSettings.MergeCoplanars)
        {
            MergeFaces();
        }

        // for additive or subtracte operation, built faces list from bsp tree
        // for others, use faces directly
        if (inOper == CsgOperation.ECsgOperation.CsgOper_Additive || inOper == CsgOperation.ECsgOperation.CsgOper_Subtractive)
        {
            // create new face list
            List <CSGFace> newFaces = new List <CSGFace>();
            // create faces from bsp nodes
            BspHelper.FacesFromNodes(rootNode, newFaces);
            // copy to face list
            faces = newFaces;
        }
        else
        {
            // copy saved faces
            faces = savedFaces;
        }


        //	Face.MergeCoplanars( faces );

        // copy to unity structure
        TransferFacesToMesh();


        // dumb tree
//		BspHelper.DumpTree( rootNode );
    }
Esempio n. 56
0
 /// <summary>
 /// When implemented, changes this mesh to be perfect representation of the given BSP tree.
 /// </summary>
 /// <param name="tree">BSP tree to convert to this mesh.</param>
 public abstract void SetBsp(BspNode<SplittableTriangle> tree);