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