Пример #1
0
		/// <summary>
		/// Get an ordered list of the faces to render based on the camera position.
		/// </summary>
		/// <param name="node"></param>
		/// <param name="meshToViewTransform"></param>
		/// <param name="invMeshToViewTransform"></param>
		/// <param name="faceRenderOrder"></param>
		public static IEnumerable<int> GetFacesInVisibiltyOrder(Mesh mesh, BspNode root, Matrix4X4 meshToViewTransform, Matrix4X4 invMeshToViewTransform)
		{
			var renderOrder = new Stack<BspNode>(new BspNode[] { root.RenderOrder(mesh, meshToViewTransform, invMeshToViewTransform) });

			do
			{
				var lastBack = renderOrder.Peek().BackNode;
				while (lastBack != null
					&& lastBack.Index != -1)
				{
					renderOrder.Peek().BackNode = null;
					renderOrder.Push(lastBack.RenderOrder(mesh, meshToViewTransform, invMeshToViewTransform));
					lastBack = renderOrder.Peek().BackNode;
				}

				var node = renderOrder.Pop();
				if (node.Index != -1)
				{
					yield return node.Index;
				}

				var lastFront = node.FrontNode;
				if (lastFront != null && lastFront.Index != -1)
				{
					renderOrder.Push(lastFront.RenderOrder(mesh, meshToViewTransform, invMeshToViewTransform));
				}
			}
			while (renderOrder.Any());
		}
Пример #2
0
		public static BspNode RenderOrder(this BspNode node, Mesh mesh, Matrix4X4 meshToViewTransform, Matrix4X4 invMeshToViewTransform)
		{
			var faceNormalInViewSpace = mesh.Faces[node.Index].normal.TransformNormalInverse(invMeshToViewTransform);
			var pointOnFaceInViewSpace = mesh.Vertices[mesh.Faces[node.Index].v0].Transform(meshToViewTransform);
			var infrontOfFace = faceNormalInViewSpace.Dot(pointOnFaceInViewSpace) < 0;

			if (infrontOfFace)
			{
				return new BspNode()
				{
					Index = node.Index,
					BackNode = node.BackNode,
					FrontNode = node.FrontNode
				};
			}
			else
			{
				return new BspNode()
				{
					Index = node.Index,
					BackNode = node.FrontNode,
					FrontNode = node.BackNode
				};
			}
		}
Пример #3
0
        public static BspNode RenderOrder(this BspNode node, List <Face> meshFaces, Matrix4X4 meshToViewTransform, Matrix4X4 invMeshToViewTransform)
        {
            var faceNormalInViewSpace  = Vector3.TransformNormalInverse(meshFaces[node.Index].Normal, invMeshToViewTransform);
            var pointOnFaceInViewSpace = Vector3.Transform(meshFaces[node.Index].firstFaceEdge.FirstVertex.Position, meshToViewTransform);
            var infrontOfFace          = Vector3.Dot(faceNormalInViewSpace, pointOnFaceInViewSpace) < 0;

            if (infrontOfFace)
            {
                return(new BspNode()
                {
                    Index = node.Index,
                    BackNode = node.BackNode,
                    FrontNode = node.FrontNode
                });
            }
            else
            {
                return(new BspNode()
                {
                    Index = node.Index,
                    BackNode = node.FrontNode,
                    FrontNode = node.BackNode
                });
            }
        }
Пример #4
0
        /// <summary>
        /// This function will search for the first face that produces no polygon cuts
        /// and split the tree on it. If it can't find a non-cutting face,
        /// it will split on the face that minimizes the area that it divides.
        /// </summary>
        /// <param name="mesh"></param>
        /// <returns></returns>
        public static BspNode Create(Mesh mesh, int maxFacesToTest = 10, bool tryToBalanceTree = false)
        {
            BspNode root = new BspNode();

            var faces = new List <Face>(mesh.Faces);

            CreateNoSplitingFast(mesh.Faces, root, faces, maxFacesToTest, tryToBalanceTree);

            return(root);
        }
Пример #5
0
		/// <summary>
		/// This function will search for the first face that produces no polygon cuts
		/// and split the tree on it. If it can't find a non-cutting face,
		/// it will split on the face that minimizes the area that it divides.
		/// </summary>
		/// <param name="mesh"></param>
		/// <returns></returns>
		public static BspNode Create(Mesh mesh, int maxFacesToTest = 10, bool tryToBalanceTree = false)
		{
			BspNode root = new BspNode();

			var sourceFaces = Enumerable.Range(0, mesh.Faces.Count).ToList();
			var faces = Enumerable.Range(0, mesh.Faces.Count).ToList();

			CreateNoSplittingFast(mesh, sourceFaces, root, faces, maxFacesToTest, tryToBalanceTree);

			return root;
		}
Пример #6
0
        private static void CreateNoSplittingFast(Mesh mesh, List <int> sourceFaces, BspNode node, List <int> faces, int maxFacesToTest, bool tryToBalanceTree)
        {
            if (faces.Count == 0)
            {
                return;
            }

            int    bestFaceIndex         = -1;
            double smallestCrossingArrea = double.MaxValue;
            int    bestBalance           = int.MaxValue;

            // find the first face that does not split anything
            int step = Math.Max(1, faces.Count / maxFacesToTest);

            for (int i = 0; i < faces.Count; i += step)
            {
                // calculate how much of polygons cross this face
                (double crossingArrea, int balance) = CalculateCrossingArea(mesh, i, faces, smallestCrossingArrea);
                // keep track of the best face so far
                if (crossingArrea < smallestCrossingArrea)
                {
                    smallestCrossingArrea = crossingArrea;
                    bestBalance           = balance;
                    bestFaceIndex         = i;
                    if (crossingArrea == 0 &&
                        !tryToBalanceTree)
                    {
                        break;
                    }
                }
                else if (crossingArrea == smallestCrossingArrea &&
                         balance < bestBalance)
                {
                    // the crossing area is the same but the tree balance is better
                    bestBalance   = balance;
                    bestFaceIndex = i;
                }
            }

            node.Index = sourceFaces.IndexOf(faces[bestFaceIndex]);

            // put the behind stuff in a list
            var backFaces  = new List <int>();
            var frontFaces = new List <int>();

            CreateBackAndFrontFaceLists(mesh, bestFaceIndex, faces, backFaces, frontFaces);

            CreateNoSplittingFast(mesh, sourceFaces, node.BackNode  = new BspNode(), backFaces, maxFacesToTest, tryToBalanceTree);
            CreateNoSplittingFast(mesh, sourceFaces, node.FrontNode = new BspNode(), frontFaces, maxFacesToTest, tryToBalanceTree);
        }