/// <summary> /// Deletes *.dds in an opc directory. /// </summary> public static int DeleteNormals(OpcPaths opcPaths, IProgress <float> progress = null) { var files = StorageConfig.GetDirectories(opcPaths.PatchesSubDir) .SelectMany(x => StorageConfig.GetFiles(x)) .Where(fileWpath => fileWpath.EndsWith("Normals.aara", StringComparison.OrdinalIgnoreCase)); if (files.IsEmptyOrNull()) { if (progress != null) { progress.Report(1f); } return(0); } var inc = 1f / files.Count(); foreach (var f in files) { File.Delete(f); if (progress != null) { progress.Report(inc); } } return(files.Count()); }
public static bool HasNormals(OpcPaths opcPaths) { var normalFileName = "Normals.aara"; return(StorageConfig.GetDirectories(opcPaths.PatchesSubDir) .All(dir => StorageConfig.FileExists(dir + "\\" + normalFileName))); }
/// <summary> /// Creates normals for the OPC in opcBasePath and saves them as Normals.aara. /// </summary> public static void BuildNormals(OpcPaths opcPaths, bool overrideExisting, IProgress <Tup <float, string> > progress, CancellationToken cancelToken = default(CancellationToken)) { var sub = new Subject <Tup <float, string> >(); sub.Subscribe(tup => progress.Report(tup)); BuildNormals(opcPaths, overrideExisting, sub, cancelToken); }
public static bool HasKdTreeForGeoResolution(OpcPaths opcPaths, double minGeometricResolution, PositionsType posType) { var hierarchyInfo = PatchHierarchyInfo.BuildOrLoadCache(opcPaths); var level = GetLevelFromResolution(hierarchyInfo.AvgGeometrySizes, minGeometricResolution); return(HasKdTreeForLevel(opcPaths, level, posType, hierarchyInfo)); }
/// <param name="level">Selects hierarchy Level the kdtree is built of (-1 shouldn't be used, use BuildKdtreeN instead).</param> /// <param name="progressObserver">Reports progress in increments which sum up to 1.</param> public static void BuildKdTreeForLevel( OpcPaths opcPaths, int level, PositionsType posType, bool lazy = true, bool overrideExisting = false, IObserver <float> progressObserver = null, CancellationToken cancelToken = default(CancellationToken), PatchHierarchyInfo hierarchyInfo = null, float maxTriangleSize = float.PositiveInfinity) { #region Preconditions if (hierarchyInfo == null) { hierarchyInfo = PatchHierarchyInfo.BuildOrLoadCache(opcPaths); } if (posType == PositionsType.V2dPositions && !hierarchyInfo.PatchTree.Info.Has2dData) { Report.Warn("KdTreeUtils: 2d KdTree needs 2d data to be able to get built."); progressObserver.OnNext(1f); progressObserver.OnCompleted(); return; } opcPaths.SetRootPatchName(hierarchyInfo.RootPatch); var kdTreeSetPath = opcPaths.GetAggKdTreePath(level, posType); if (!overrideExisting && StorageConfig.FileExists(kdTreeSetPath)) { progressObserver.OnNext(1f); progressObserver.OnCompleted(); return; } #endregion hierarchyInfo.PatchTree.CreatePatchPaths(opcPaths.PatchesSubDir); // Get geometry patchinformations for certain level with a valid boundingbox var patchTrees = hierarchyInfo.RetrievePatchTreesOfLevel(level) .Where(x => !x.Info.GlobalBoundingBox.IsInvalid); IIntersectableObjectSet kdTree; var buildFlags = KdIntersectionTree.BuildFlags.Hierarchical | KdIntersectionTree.BuildFlags.EmptySpaceOptimization; // Decide lazy or eager if (lazy) { kdTree = BuildLazyKdTreeSet(patchTrees, opcPaths, level, posType, overrideExisting, progressObserver, cancelToken, maxTriangleSize); buildFlags |= KdIntersectionTree.BuildFlags.OptimalRaytracing; } else { kdTree = BuildConcreteKdTreeSet(patchTrees, opcPaths, level, posType, overrideExisting, progressObserver, cancelToken, maxTriangleSize); buildFlags |= KdIntersectionTree.BuildFlags.MediumIntersection; } // Save Kd-Tree var aggrTree = new KdIntersectionTree(kdTree, buildFlags); aggrTree.Save(kdTreeSetPath, waitMode: WaitMode.WaitUntilFinished); }
/// <param name="minGeometricResolution">Used to select an appropriate level in the hierarchy to meet the specified minimum resolution criterion.</param> /// <param name="progressObserver">Reports progress in increments which sum up to 1.</param> public static void BuildKdTreeForGeoResolution( OpcPaths opcPaths, double minGeometricResolution, PositionsType posType, bool lazy = true, bool overrideExisting = false, IObserver <float> progressObserver = null, CancellationToken cancelToken = default(CancellationToken)) { var hierarchyInfo = PatchHierarchyInfo.BuildOrLoadCache(opcPaths); var level = GetLevelFromResolution(hierarchyInfo.AvgGeometrySizes, minGeometricResolution); BuildKdTreeForLevel(opcPaths, level, posType, lazy, overrideExisting, progressObserver, cancelToken, hierarchyInfo); }
public static bool HasKdTreeForLevel(OpcPaths opcPaths, int level, PositionsType posType, PatchHierarchyInfo hierarchyInfo = null) { if (hierarchyInfo == null) { hierarchyInfo = PatchHierarchyInfo.BuildOrLoadCache(opcPaths); } opcPaths.SetRootPatchName(hierarchyInfo.RootPatch); var kdTreeSetPath = opcPaths.GetAggKdTreePath(level, posType); return(StorageConfig.FileExists(kdTreeSetPath)); }
/// <summary> /// Creates normals for the OPC in opcBasePath and saves them as Normals.aara. /// </summary> public static void BuildNormals(OpcPaths opcPaths, bool overrideExisting = false, IObserver <Tup <float, string> > progress = null, CancellationToken cancelToken = default(CancellationToken)) { var normalFileName = "Normals.aara"; var posFiles = StorageConfig.GetDirectories(opcPaths.PatchesSubDir) .SelectMany(x => StorageConfig.GetFiles(x)) .Where(fileWpath => fileWpath.EndsWith("Positions.aara", StringComparison.OrdinalIgnoreCase)); foreach (var file in posFiles) { if (cancelToken.IsCancellationRequested) { if (progress != null) { progress.OnNext(Tup.Create(0f, "Building normals cancelled.")); progress.OnCompleted(); } cancelToken.ThrowIfCancellationRequested(); } var normalsFilePath = Path.Combine(Path.GetDirectoryName(file), normalFileName); if (overrideExisting || !StorageConfig.FileExists(normalsFilePath)) { var posAara = AaraData.FromFile(file); var tileSize = new V2i(posAara.Size[0], posAara.Size[1]); var posArray = AaraData.ConvertArrayToV3ds[posAara.DataTypeAsSymbol](posAara.LoadElements()); var invalidPoints = OpcIndices.GetInvalidPositions(posArray); var indices = OpcIndices.ComputeIndexArray(tileSize, invalidPoints); var normals = OpcIndices.GenerateVertexNormals(indices, posArray) .Select(p => p.ToV3f()).ToArray(); WriteV3fArrayAsAara(normalsFilePath, normals, tileSize); } if (progress != null) { progress.OnNext(Tup.Create(1f / posFiles.Count(), "")); } } if (progress != null) { progress.OnCompleted(); } }
/// <summary> /// Loads level N kdtree. If level N kdtree does not exist it is built from rootpatch. /// </summary> public static KdIntersectionTree BuildOrLoadKdTreeN(OpcPaths opcPaths, PositionsType posType, PatchFileInfo patchFileInfo) { KdIntersectionTree kdiTree = null; var kdTreeNPatch = opcPaths.GetKdTreeNPath(posType); if (!StorageConfig.FileExists(kdTreeNPatch)) { kdiTree = KdTreeUtils.BuildKdTreeForPatch(opcPaths.RootPatchName, -1, patchFileInfo, opcPaths, posType, saveTriangles: true); kdiTree.Save(opcPaths.RootPatchName); } else { kdiTree = Load.As <KdIntersectionTree>(opcPaths.GetKdTreeNPath(posType)); } return(kdiTree); }
public static Subject <float> GetKdTreeProgressObserver(OpcPaths opcPaths, int level, PositionsType posType) { var opcName = Path.GetFileName(opcPaths.BasePath); float totalProgress = 0f; var progress = new Subject <float>(); progress.Sample(TimeSpan.FromSeconds(1.0)).Subscribe(inc => { totalProgress += inc; Report.Line("{0} - {1} - {2} - Progress {3:0.0}%", opcName, level, posType.ToString(), totalProgress * 100.0); //Report.ProgressDelta(tup.E1); }); return(progress); }
public static void BuildKdtreeN(OpcPaths opcPaths, PositionsType posType, bool overrideExisting = false, float maxTriangleSize = float.PositiveInfinity) { var hierarchyInfo = PatchHierarchyInfo.BuildOrLoadCache(opcPaths); var patchInfo = hierarchyInfo.PatchTree.Info; opcPaths.SetRootPatchName(hierarchyInfo.RootPatch); if (posType == PositionsType.V2dPositions && !patchInfo.Has2dData) { Report.Warn("KdTreeUtils: 2d KdTreeN needs 2d data to be able to get built."); return; } if (overrideExisting || !StorageConfig.FileExists(opcPaths.GetKdTreeNPath(posType))) { BuildKdTreeForPatch(opcPaths.RootPatchName, -1, patchInfo, opcPaths, posType, true, true, maxTriangleSize); } }
/// <summary> /// Deletes *.dds in an opc directory (if *.tif exists). /// </summary> public static int DeleteDDSs(OpcPaths opcPaths, IProgress <Tup <float, string> > progress = null) { int deleteCounter = 0; var files = StorageConfig.GetDirectories(opcPaths.ImagesSubDir) .SelectMany(x => StorageConfig.GetFiles(x)) .Where(x => Path.GetExtension(x) == ".dds"); if (files.IsEmptyOrNull()) { if (progress != null) { progress.Report(Tup.Create(1f, "No dds images found.")); } return(0); } var inc = 1f / files.Count(); foreach (var f in files) { string tifPath = Path.ChangeExtension(f, ".tif"); var msg = ""; if (StorageConfig.FileExists(tifPath)) { File.Delete(f); deleteCounter++; } else { msg = "dds file not deleted, because it doesn't have a coresponding tif file (" + f + ")"; } if (progress != null) { progress.Report(Tup.Create(inc, msg)); } } return(deleteCounter); }
/// <summary> /// Converts .tif to .dds files in an opc directory for straight to gpu uploads of textures. /// tiffs are convert asynchrounos in parallel /// </summary> public static Task <int> ConvertTiffsToDDSsAsync(OpcPaths opcPaths, bool overrideExisting = false, IProgress <float> progress = null, CancellationToken cancelToken = default(CancellationToken)) { var taskSource = new TaskCompletionSource <int>(); var tiffs = StorageConfig.GetDirectories(opcPaths.ImagesSubDir) .SelectMany(x => StorageConfig.GetFiles(x)) .Where(x => Path.GetExtension(x) == ".tif"); if (tiffs.IsEmptyOrNull()) { if (progress != null) { progress.Report(1f); } taskSource.SetResult(0); return(taskSource.Task); } var inc = 1f / tiffs.Count(); var tasks = new List <Task>(); foreach (var f in tiffs) { cancelToken.ThrowIfCancellationRequested(); var task = Task.Run(() => { ConvertTiffToDDS3(f, overrideExisting); if (progress != null) { progress.Report(inc); } }); tasks.Add(task); } Task.WhenAll(tasks).ContinueWith(_ => taskSource.SetResult(tiffs.Count())); return(taskSource.Task); }
//private static SlimDX.Direct3D11.Device d = new SlimDX.Direct3D11.Device(SlimDX.Direct3D11.DriverType.Reference, SlimDX.Direct3D11.DeviceCreationFlags.None, new SlimDX.Direct3D11.FeatureLevel[] { SlimDX.Direct3D11.FeatureLevel.Level_9_1 }); /// <summary> /// Converts .tif to .dds files in an opc directory for straight to gpu uploads of textures. /// </summary> public static int ConvertTiffsToDDSs(OpcPaths opcPaths, bool overrideExisting = false, IObserver <float> progress = null, CancellationToken cancelToken = default(CancellationToken)) { var tiffs = StorageConfig.GetDirectories(opcPaths.ImagesSubDir) .SelectMany(x => StorageConfig.GetFiles(x)) .Where(x => Path.GetExtension(x) == ".tif"); if (tiffs.IsEmptyOrNull()) { if (progress != null) { progress.OnNext(1f); progress.OnCompleted(); } return(0); } var inc = 1f / tiffs.Count(); foreach (var f in tiffs) { cancelToken.ThrowIfCancellationRequested(); // ConvertTiffToDDS2(f, overrideExisting); // ConvertTiffToDDS(f, overrideExisting); ConvertTiffToDDS3(f, overrideExisting); if (progress != null) { progress.OnNext(inc); } } if (progress != null) { progress.OnCompleted(); } return(tiffs.Count()); }
/// <summary> /// Builds kdtree for specific patch. /// Kdtree is built according to specified positions type and hierarchy level. /// </summary> private static KdIntersectionTree BuildKdTreeForPatch( string patchName, int level, PatchFileInfo info, OpcPaths paths, PositionsType posType, bool saveTriangles = false, bool saveKdTree = true, float maxTriangleSize = float.PositiveInfinity) { var path = Path.Combine(paths.PatchesSubDir, patchName); var patchGeometry = new TriangleSet(); //var patchGeometryTest = new TriangleSet(); if ((maxTriangleSize < float.PositiveInfinity) && (maxTriangleSize > 0.000001f)) { patchGeometry = PatchLoadingStrategy.LoadPatchTriangleSetWithoutOversizedTriangles(info, path, posType, maxTriangleSize); //patchGeometryTest = PatchLoadingStrategy.LoadPatchTriangleSet(info, path, posType); } else { patchGeometry = PatchLoadingStrategy.LoadPatchTriangleSet(info, path, posType); } KdIntersectionTree kdIntTree = new KdIntersectionTree(patchGeometry, KdIntersectionTree.BuildFlags.MediumIntersection | KdIntersectionTree.BuildFlags.Hierarchical); if (!saveTriangles) { kdIntTree.ObjectSet = null; } if (saveKdTree) { var kdTreePath = paths.GetKdTreePath(patchName, level, posType); kdIntTree.Save(kdTreePath); } return(kdIntTree); }
/// <summary> /// NOT TESTED /// </summary> private static KdTreeSet BuildConcreteKdTreeSet(IEnumerable <PatchTree> patches, OpcPaths opcPaths, int level, PositionsType posType, bool overrideExisting, IObserver <float> progressObserver, CancellationToken cancelToken = default(CancellationToken), float maxTriangleSize = float.PositiveInfinity) { var kdTrees = new List <ConcreteKdIntersectionTree>(); var progressInc = 1f / patches.Count(); foreach (var p in patches) { cancelToken.ThrowIfCancellationRequested(); KdIntersectionTree tree; var kdtreePath = opcPaths.GetKdTreePath(p.Id, level, posType); if (overrideExisting || !StorageConfig.FileExists(kdtreePath)) { tree = BuildKdTreeForPatch(p.Id, level, p.Info, opcPaths, posType, saveTriangles: true, saveKdTree: false, maxTriangleSize: maxTriangleSize); } else { tree = Load.As <KdIntersectionTree>(kdtreePath); } kdTrees.Add(tree.ToConcreteKdIntersectionTree()); if (progressObserver != null) { progressObserver.OnNext(progressInc); } } if (progressObserver != null) { progressObserver.OnCompleted(); } return(new KdTreeSet(kdTrees)); }
private static LazyKdTreeSet BuildLazyKdTreeSet(IEnumerable <PatchTree> patches, OpcPaths opcPaths, int level, PositionsType posType, bool overrideExisting, IObserver <float> progressObserver, CancellationToken cancelToken = default(CancellationToken), float maxTriangleSize = float.PositiveInfinity) { var placeHolders = new List <LazyKdTreeSet.KdTreePlaceHolder>(); var progressInc = 1f / patches.Count(); foreach (var p in patches) { cancelToken.ThrowIfCancellationRequested(); var kdtreePath = opcPaths.GetKdTreePath(p.Id, level, posType); if (overrideExisting || !StorageConfig.FileExists(kdtreePath)) { BuildKdTreeForPatch(p.Id, level, p.Info, opcPaths, posType, saveTriangles: false, saveKdTree: true, maxTriangleSize: maxTriangleSize); } // Create place holders placeHolders.Add(new LazyKdTreeSet.KdTreePlaceHolder() { BoundingBox = p.Info.GetGlobalBoundingBox(posType), Affine = p.Info.GetLocal2Global(posType), Path = opcPaths.GetKdTreePath(p.Id, level, posType), ObjectSetPath = p.GetPositionPath(posType) }); if (progressObserver != null) { progressObserver.OnNext(progressInc); } } if (progressObserver != null) { progressObserver.OnCompleted(); } return(new LazyKdTreeSet(placeHolders)); }
/// <summary> /// Builds look up table for profile "intersection" in 2d data. /// </summary> public static void BuildLookUpTable(OpcPaths opcPaths, bool overrideExisting = false, IObserver <Tup <float, string> > progress = null, CancellationToken cancelToken = default(CancellationToken)) { if (!overrideExisting && StorageConfig.FileExists(opcPaths.ProfileLutPath)) { if (progress != null) { progress.OnNext(Tup.Create(1f, "")); progress.OnCompleted(); } Report.Line("LookUpTable already exists at {0}", opcPaths.ProfileLutPath); } // PatchHierarchyInfo var info = PatchHierarchyInfo.BuildOrLoadCache(opcPaths); info.PatchTree.CreatePatchPaths(opcPaths.PatchesSubDir); // Level 0 Patches var lvl0Patches = info.RetrievePatchTreesOfLevel(0); if (progress != null) { progress.OnNext(Tup.Create(.1f, "")); } // group by BB-2d: Min-X, Max-X var patchesGroupedByBB = lvl0Patches .GroupBy(patchTree => Tup.Create(patchTree.Info.GlobalBoundingBox2d.Min.X, patchTree.Info.GlobalBoundingBox2d.Max.X)).ToArray(); var entries = new List <ProfileLookUpTableEntry>(); #region Create ProfileLookUpTableEntries for (int index = 0; index < patchesGroupedByBB.Count(); index++) { if (cancelToken.IsCancellationRequested) { if (progress != null) { progress.OnNext(Tup.Create(0f, "Building LookUpTabele cancelled.")); } cancelToken.ThrowIfCancellationRequested(); } //sort patches according to their b (sv_b_r) value var patchesGroupedBySvBR = patchesGroupedByBB[index] .OrderBy(k => k.Info.GlobalBoundingBox2d.Min.Y); var fileHandleList = new List <PatchFileHandle>(); #region build PatchFileHandles foreach (var patchTree in patchesGroupedBySvBR) { if (patchTree.Info.Positions2d.IsNullOrEmpty()) { Report.Warn("ProfileLutCreation: Skipping Patchtree {0}, because of missing 2d positions.", patchTree.Id); if (progress != null) { progress.OnNext(Tup.Create(0f, "ProfileLutCreation: Skipping Patchtree " + patchTree.Id + ", because of missing 2d positions.")); } continue; } var pos2dPath = patchTree.GetPositionPath(PositionsType.V2dPositions); //CAUTION absolute path needs to be repaired during loading var file = AaraData.FromFile(pos2dPath); file.SourceFileName = string.Empty; fileHandleList.Add(new PatchFileHandle() { PatchTree = patchTree, FileLoader = file, }); } #endregion // Create ProfileLookupTableEntries var firstPatchBB = patchesGroupedBySvBR.First().Info.GlobalBoundingBox2d; entries.Add(new ProfileLookUpTableEntry() { Index = index, SvRange = new Range1d(firstPatchBB.Min.X, firstPatchBB.Max.X), FileHandles = fileHandleList, }); var progressInc = 0.8f / patchesGroupedByBB.Count(); if (progress != null) { progress.OnNext(Tup.Create(progressInc, "")); } } entries.Reverse(); #endregion #region Save LUT var lut = new ProfileLookUpTable() { SvRange = new Range1d(info.PatchTree.Info.GlobalBoundingBox2d.Min.X, info.PatchTree.Info.GlobalBoundingBox2d.Max.X), Entries = entries, AvgGeomtrySize = info.AvgGeometrySizes.First() }; lut.Save(opcPaths.ProfileLutPath); #endregion if (progress != null) { progress.OnNext(Tup.Create(0.1f, "")); progress.OnCompleted(); } }