예제 #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="nodeCell"></param>
        /// <param name="node"></param>
        /// <returns></returns>
        private void ProcessNodeMultithreaded(IVoxelizable obj, AACell nodeCell, OctreeNode node)
        {
            var center        = nodeCell.Center;
            var childNodeSize = (nodeCell.Max.X - nodeCell.Min.X) * .5f;

            var nodeInfo = OctreeNodeInfo.Empty;

            var childCell = nodeCell;

            if (childNodeSize > voxelSizeThreshold && maxDepth > 0)
            {
                #region check child nodes

                // xyz
                childCell.Max = center;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x0y0z0;
                }

                // Xyz
                childCell.Min.X += childNodeSize;
                childCell.Max.X += childNodeSize;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x1y0z0;
                }

                // XYz
                childCell.Min.Y += childNodeSize;
                childCell.Max.Y += childNodeSize;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x1y1z0;
                }

                // xYz
                childCell.Min.X -= childNodeSize;
                childCell.Max.X -= childNodeSize;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x0y1z0;
                }

                // xyZ
                childCell.Min.Y -= childNodeSize;
                childCell.Max.Y -= childNodeSize;
                childCell.Min.Z += childNodeSize;
                childCell.Max.Z += childNodeSize;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x0y0z1;
                }

                // XyZ
                childCell.Min.X += childNodeSize;
                childCell.Max.X += childNodeSize;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x1y0z1;
                }

                // XYZ
                childCell.Min.Y += childNodeSize;
                childCell.Max.Y += childNodeSize;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x1y1z1;
                }

                // xYZ
                childCell.Min.X -= childNodeSize;
                childCell.Max.X -= childNodeSize;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x0y1z1;
                }

                #endregion
            }

            node.Info = nodeInfo;
            if (nodeInfo == OctreeNodeInfo.Empty)
            {
                node.Voxel = GetVoxel(obj, nodeCell);
            }
            else
            {
                var childNodes             = new OctreeNode[8];
                var childNodesProcessEvent = new CountdownEvent(8);

                #region process child nodes

                // xyz
                childCell.Min = nodeCell.Min;
                childCell.Max = center;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x0y0z0))
                {
                    childNodes[0] = new OctreeNode();
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessNodeOnThread), new ProessNodeInfo(obj, childCell, childNodes[0], childNodesProcessEvent));
                }

                // Xyz
                childCell.Min.X += childNodeSize;
                childCell.Max.X += childNodeSize;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x1y0z0))
                {
                    childNodes[1] = new OctreeNode();
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessNodeOnThread), new ProessNodeInfo(obj, childCell, childNodes[1], childNodesProcessEvent));
                }

                // XYz
                childCell.Min.Y += childNodeSize;
                childCell.Max.Y += childNodeSize;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x1y1z0))
                {
                    childNodes[2] = new OctreeNode();
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessNodeOnThread), new ProessNodeInfo(obj, childCell, childNodes[2], childNodesProcessEvent));
                }

                // xYz
                childCell.Min.X -= childNodeSize;
                childCell.Max.X -= childNodeSize;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x0y1z0))
                {
                    childNodes[3] = new OctreeNode();
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessNodeOnThread), new ProessNodeInfo(obj, childCell, childNodes[3], childNodesProcessEvent));
                }

                // xyZ
                childCell.Min.Y -= childNodeSize;
                childCell.Max.Y -= childNodeSize;
                childCell.Min.Z += childNodeSize;
                childCell.Max.Z += childNodeSize;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x0y0z1))
                {
                    childNodes[4] = new OctreeNode();
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessNodeOnThread), new ProessNodeInfo(obj, childCell, childNodes[4], childNodesProcessEvent));
                }

                // XyZ
                childCell.Min.X += childNodeSize;
                childCell.Max.X += childNodeSize;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x1y0z1))
                {
                    childNodes[5] = new OctreeNode();
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessNodeOnThread), new ProessNodeInfo(obj, childCell, childNodes[5], childNodesProcessEvent));
                }

                // XYZ
                childCell.Min.Y += childNodeSize;
                childCell.Max.Y += childNodeSize;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x1y1z1))
                {
                    childNodes[6] = new OctreeNode();
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessNodeOnThread), new ProessNodeInfo(obj, childCell, childNodes[6], childNodesProcessEvent));
                }

                // xYZ
                childCell.Min.X -= childNodeSize;
                childCell.Max.X -= childNodeSize;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x0y1z1))
                {
                    childNodes[7] = new OctreeNode();
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessNodeOnThread), new ProessNodeInfo(obj, childCell, childNodes[7], childNodesProcessEvent));
                }

                #endregion

                // wait for threads to end
                childNodesProcessEvent.Wait();

                node.OctreeNodes = (from n in childNodes where n != null select n).ToList();
                node.SetVoxelAsAverage();
            }
        }
예제 #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="mesh"></param>
        /// <param name="nodeCell"></param>
        /// <param name="node"></param>
        /// <returns></returns>
        private void ProcessNode(IVoxelizable obj, AACell nodeCell, OctreeNode node, int nodeDepth)
        {
            var center        = nodeCell.Center;
            var childNodeSize = (nodeCell.Max.X - nodeCell.Min.X) * .5f;

            var nodeInfo = OctreeNodeInfo.Empty;

            var childCell = nodeCell;

            if (childNodeSize > voxelSizeThreshold && maxDepth > nodeDepth)
            {
                #region check child nodes

                // xyz
                childCell.Max = center;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x0y0z0;
                }

                // Xyz
                childCell.Min.X += childNodeSize;
                childCell.Max.X += childNodeSize;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x1y0z0;
                }

                // XYz
                childCell.Min.Y += childNodeSize;
                childCell.Max.Y += childNodeSize;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x1y1z0;
                }

                // xYz
                childCell.Min.X -= childNodeSize;
                childCell.Max.X -= childNodeSize;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x0y1z0;
                }

                // xyZ
                childCell.Min.Y -= childNodeSize;
                childCell.Max.Y -= childNodeSize;
                childCell.Min.Z += childNodeSize;
                childCell.Max.Z += childNodeSize;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x0y0z1;
                }

                // XyZ
                childCell.Min.X += childNodeSize;
                childCell.Max.X += childNodeSize;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x1y0z1;
                }

                // XYZ
                childCell.Min.Y += childNodeSize;
                childCell.Max.Y += childNodeSize;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x1y1z1;
                }

                // xYZ
                childCell.Min.X -= childNodeSize;
                childCell.Max.X -= childNodeSize;
                if (!IsNodeEmpty(obj, childCell))
                {
                    nodeInfo |= OctreeNodeInfo.x0y1z1;
                }

                #endregion
            }

            node.Info = nodeInfo;
            if (nodeInfo == OctreeNodeInfo.Empty)
            {
                node.Voxel = GetVoxel(obj, nodeCell);
            }
            else
            {
                nodeDepth++;

                var childNodes = new OctreeNode[8];

                #region process child nodes

                // xyz
                childCell.Min = nodeCell.Min;
                childCell.Max = center;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x0y0z0))
                {
                    childNodes[0] = new OctreeNode();
                    ProcessNode(obj, childCell, childNodes[0], nodeDepth);
                }

                // Xyz
                childCell.Min.X += childNodeSize;
                childCell.Max.X += childNodeSize;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x1y0z0))
                {
                    childNodes[1] = new OctreeNode();
                    ProcessNode(obj, childCell, childNodes[1], nodeDepth);
                }

                // XYz
                childCell.Min.Y += childNodeSize;
                childCell.Max.Y += childNodeSize;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x1y1z0))
                {
                    childNodes[2] = new OctreeNode();
                    ProcessNode(obj, childCell, childNodes[2], nodeDepth);
                }

                // xYz
                childCell.Min.X -= childNodeSize;
                childCell.Max.X -= childNodeSize;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x0y1z0))
                {
                    childNodes[3] = new OctreeNode();
                    ProcessNode(obj, childCell, childNodes[3], nodeDepth);
                }

                // xyZ
                childCell.Min.Y -= childNodeSize;
                childCell.Max.Y -= childNodeSize;
                childCell.Min.Z += childNodeSize;
                childCell.Max.Z += childNodeSize;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x0y0z1))
                {
                    childNodes[4] = new OctreeNode();
                    ProcessNode(obj, childCell, childNodes[4], nodeDepth);
                }

                // XyZ
                childCell.Min.X += childNodeSize;
                childCell.Max.X += childNodeSize;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x1y0z1))
                {
                    childNodes[5] = new OctreeNode();
                    ProcessNode(obj, childCell, childNodes[5], nodeDepth);
                }

                // XYZ
                childCell.Min.Y += childNodeSize;
                childCell.Max.Y += childNodeSize;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x1y1z1))
                {
                    childNodes[6] = new OctreeNode();
                    ProcessNode(obj, childCell, childNodes[6], nodeDepth);
                }

                // xYZ
                childCell.Min.X -= childNodeSize;
                childCell.Max.X -= childNodeSize;
                if (nodeInfo.HasFlag(OctreeNodeInfo.x0y1z1))
                {
                    childNodes[7] = new OctreeNode();
                    ProcessNode(obj, childCell, childNodes[7], nodeDepth);
                }

                #endregion

                node.OctreeNodes = (from n in childNodes where n != null select n).ToList();
                node.SetVoxelAsAverage();
            }
        }