/// <summary> /// Starts tree building process with given settings. /// </summary> public static void BuildNodeTree(TreeImportSettings settings) { var processors = new List <PointProcessor>(); foreach (var inputFile in settings.inputFiles) { var processor = CreateProcessor(inputFile); if (processor != null) { processors.Add(processor); } } if (processors.Count == 0) { Debug.LogError("All of given point cloud files are invalid or unsupported."); return; } var bounds = CalculateBounds(processors); var transformationData = new TransformationData(bounds, settings); var unityBounds = bounds.GetUnityBounds(settings); var transform = transformationData.TransformationMatrix; unityBounds.center = transform.MultiplyPoint3x4(unityBounds.center); unityBounds.extents = transform.MultiplyVector(unityBounds.extents); NodeProcessorDispatcher dispatcher; try { EditorUtility.DisplayProgressBar("Creating dispatcher", "Preparing target directory...", 0f); dispatcher = new NodeProcessorDispatcher(settings.outputPath, settings); } finally { EditorUtility.ClearProgressBar(); } foreach (var processor in processors) { if (!processor.ConvertPoints(dispatcher, transformationData)) { Debug.Log("Import cancelled."); return; } } if (dispatcher.ProcessPoints(unityBounds)) { Debug.Log("Octree build finished successfully."); } else { Debug.Log("Octree build failed."); } }
protected TreeNodeProcessor(string dataPath, TreeImportSettings settings) { Settings = settings; this.dataPath = dataPath; tmpFolderPath = Path.Combine(dataPath, "tmp"); stride = UnsafeUtility.SizeOf <PointCloudPoint>(); ChildNodeRecords = new List <NodeRecord>(); inputBuffer = new PointCloudPoint[settings.chunkSize]; }
public OctreeNodeProcessor(string dataPath, TreeImportSettings settings, TreeImportData importData) : base(dataPath, settings, importData) { ChildBuffers = new PointCloudPoint[ChildCount][]; for (var i = 0; i < ChildCount; ++i) { ChildBuffers[i] = new PointCloudPoint[settings.chunkSize]; } ChildCounts = new int[ChildCount]; ChildFileCounts = new int[ChildCount]; }
public static float GetStepAtTreeLevel(Bounds rootBounds, TreeImportSettings settings, int level) { var step = Mathf.Min(rootBounds.size.x, rootBounds.size.z) / settings.rootNodeSubdivision; for (var i = 0; i < level - 1; ++i) { step *= 0.5f; } return(step); }
public MeshBuilder(string dataPath, TreeImportSettings settings, TreeImportData importData) { this.dataPath = dataPath; this.importData = importData; this.settings = settings; tmpDataPath = Path.Combine(dataPath, "tmp"); voxelData = new MeshGenerationData(); for (var i = 1; i < LutOffsets.Length; ++i) { neighborData.Add(LutOffsets[i], new MeshGenerationData()); } }
private static Matrix4x4 GetTransformationMatrix(TreeImportSettings settings) { switch (settings.axes) { case PointCloudImportAxes.X_Right_Y_Up_Z_Forward: return(Matrix4x4.identity); case PointCloudImportAxes.X_Right_Z_Up_Y_Forward: return(new Matrix4x4(new Vector4(1, 0, 0), new Vector4(0, 0, 1), new Vector4(0, 1, 0), Vector4.zero)); default: Debug.Assert(false); return(Matrix4x4.identity); } }
public Bounds AlignBounds(TreeImportSettings settings, Bounds bounds) { var origin = bounds.min.y; var step = EditorTreeUtility.GetStepAtTreeLevel(bounds, settings, settings.meshDetailLevel); var alignedBounds = TreeUtility.GetRoundedAlignedBounds(bounds, bounds.min, step); var alignedOrigin = alignedBounds.min.y; var peak = FindPeak(); var targetCenter = origin + (bounds.size.y / Resolution) * (peak + 0.5f); var tmpDst = float.MaxValue; var actualCenter = 0f; for (var i = 0; i < (int)(alignedBounds.size.y / step); ++i) { var pos = alignedOrigin + (i + 0.5f) * step; var dst = Mathf.Abs(targetCenter - pos); if (dst < tmpDst) { actualCenter = pos; tmpDst = dst; } else { Debug.Log($"Break at i ({actualCenter:F4})"); break; } } var diff = targetCenter - actualCenter; if (diff > 0) { diff -= step; } var height = bounds.max.y - bounds.min.y; var alignedMin = alignedBounds.min; alignedMin.y += diff; alignedBounds.min = alignedMin; Debug.Log($"origin: {origin:F4}, AO: {alignedBounds.min.y:F4}, height: {height:F4}, step: {step:F4}, TC: {targetCenter:F4}, AC: {actualCenter:F4}"); return(alignedBounds); }
public NodeProcessorDispatcher(string outputPath, TreeImportSettings settings) { this.outputPath = outputPath; Settings = settings; if (Directory.Exists(outputPath)) { Directory.Delete(outputPath, true); } Directory.CreateDirectory(outputPath); outputTmpPath = Path.Combine(outputPath, "tmp"); Directory.CreateDirectory(outputTmpPath); points = new PointCloudPoint[settings.chunkSize]; PublicMaxSizeBuffer = new PointCloudPoint[TreeUtility.MaxPointCountPerArray]; }
public QuadtreeNodeProcessor(string dataPath, TreeImportSettings settings) : base(dataPath, settings) { ChildBuffers = new PointCloudPoint[ChildCount][]; for (var i = 0; i < ChildCount; ++i) { ChildBuffers[i] = new PointCloudPoint[settings.chunkSize]; } ChildCounts = new int[ChildCount]; ChildFileCounts = new int[ChildCount]; if (settings.sampling == TreeImportSettings.SamplingMethod.CellCenter) { PointCollection = new CellCenterPointCollection(); } else { PointCollection = new PoissonDiskPointCollection(); } PointCollection.Initialize(settings); }
public NodeProcessorDispatcher(string outputPath, TreeImportSettings settings) { this.outputPath = outputPath; Settings = settings; var pcExtensions = new List <string> { TreeUtility.NodeFileExtension, TreeUtility.IndexFileExtension, TreeUtility.MeshFileExtension }; if (Directory.Exists(outputPath)) { var matchingFiles = Directory .EnumerateFiles(outputPath, "*.*", SearchOption.TopDirectoryOnly) .Where(x => Path.GetExtension(x) != null && pcExtensions.Contains(Path.GetExtension(x).ToLowerInvariant())) .ToList(); foreach (var file in matchingFiles) { File.Delete(file); } } Directory.CreateDirectory(outputPath); outputTmpPath = Path.Combine(outputPath, "tmp"); if (Directory.Exists(outputTmpPath)) { Directory.Delete(outputTmpPath, true); } Directory.CreateDirectory(outputTmpPath); points = new PointCloudPoint[settings.chunkSize]; var maxArraySize = TreeUtility.CalculateMaxArraySize(UnsafeUtility.SizeOf <PointCloudPoint>()); PublicMaxSizeBuffer = new PointCloudPoint[maxArraySize]; }
/// <summary> /// Starts tree building process with given settings. /// </summary> public static bool BuildNodeTree(TreeImportSettings settings) { var processors = new List <PointProcessor>(); foreach (var inputFile in settings.inputFiles) { var processor = CreateProcessor(Utility.GetFullPath(inputFile)); if (processor != null) { processors.Add(processor); } } if (processors.Count == 0) { Debug.LogError("All of given point cloud files are invalid or unsupported."); return(false); } var bounds = CalculateBounds(processors); var transformationData = new TransformationData(bounds, settings); var unityBounds = bounds.GetUnityBounds(settings); var transform = transformationData.TransformationMatrix; unityBounds.center = transform.MultiplyPoint3x4(unityBounds.center); unityBounds.extents = transform.MultiplyVector(unityBounds.extents); TreeImportData importData = null; if (settings.generateMesh && settings.roadOnlyMesh) { var histogram = GenerateHistogram(processors, bounds); importData = new TreeImportData(unityBounds, histogram); } else { importData = new TreeImportData(unityBounds); } NodeProcessorDispatcher dispatcher; var fullOutputPath = Utility.GetFullPath(settings.outputPath); try { EditorUtility.DisplayProgressBar("Creating dispatcher", "Preparing target directory...", 0f); dispatcher = new NodeProcessorDispatcher(fullOutputPath, settings); } finally { EditorUtility.ClearProgressBar(); } foreach (var processor in processors) { if (!processor.ConvertPoints(dispatcher, transformationData)) { Debug.Log("Import cancelled."); return(false); } } if (dispatcher.ProcessPoints(importData)) { dispatcher.GetPointCountResults(out var total, out var used, out var discarded); Debug.Log($"Octree build finished successfully.\n" + $"Used points: {used}/{total} ({discarded} discarded on low tree levels)"); return(true); } else { Debug.Log("Octree build failed."); return(false); } }
///<inheritdoc/> public void Initialize(TreeImportSettings treeSettings, TreeImportData importData) { rootBounds = importData.Bounds; settings = treeSettings; cellsPerAxis = new int[3]; }
///<inheritdoc/> public void Initialize(TreeImportSettings treeSettings) { settings = treeSettings; cellsPerAxis = new int[3]; }