/// <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(); } }
public static IPointSampleGrid2d PointSampleGrid2dFromAaraFile(string fileName) { if (fileName == null) { throw new ArgumentNullException(); } var aara = AaraData.FromFile(fileName); // extract grid resolution var res = aara.Size; if (res.Length != 2) { throw new ArgumentException("encountered aara file of unexpected dimensions - 2 expected"); } // extract points var elements = aara.LoadElements(); V3d[] points = elements as V3d[]; if (points == null) { if (elements is V3f[]) { points = elements.CopyAndConvert(V3d.FromV3f); } else { throw new ArgumentException(".aara contains unexpected type - V3d or V3f expected"); } } return(new PointSampleGrid2d(new PointSampleSet(points), new V2i(res[0], res[1]))); }
public PatchFileHandle(PatchFileHandle pfh) : this() { PatchTree = pfh.PatchTree; FileLoader = new AaraData(pfh.FileLoader); }
/// <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(); } }
/// <summary> /// Loads VertexGeometry from aara files. Beware: add Local2Global node for global space. /// </summary> /// <param name="positions">Raw positions, read from aara files for possible further processing.</param> /// <param name="dataType">DataType of positions.</param> /// <returns>Vertex Geometry in local OPC space.</returns> public static VertexGeometry LoadPatch(PatchFileInfo info, string basePath, PositionsType posType, out Array positions, out Symbol dataType, bool loadNormals = true, bool loadTexCoords = true, bool loadDiffTex = true, bool loadHueTex = true, float maxTriangleSize = float.PositiveInfinity, bool loadAsDoubles = false) { var vg = new VertexGeometry(GeometryMode.TriangleList); positions = null; // load metadata var aara3dPos = AaraData.FromFile( Path.Combine(basePath, posType == PositionsType.V3dPositions ? info.Positions : info.Positions2d)); dataType = aara3dPos.DataTypeAsSymbol; var resolution = new V2i(aara3dPos.Size); if (resolution.AnySmaller(2)) { Report.Warn("ignoring patch {0} due to invalid gridresolution {1}", basePath, resolution); return(null); } // load positions positions = aara3dPos.LoadElements(); var positions3d = loadAsDoubles ? positions : AaraData.ConvertArrayToV3fs[aara3dPos.DataTypeAsSymbol](positions); //var positionsV3 = loadAsDoubles ? // (Array)AaraData.ConvertArrayToV3ds[aara3dPos.DataTypeAsSymbol](positions) : // (Array); vg.Positions = positions3d; var p = AaraData.ConvertArrayToV3fs[aara3dPos.DataTypeAsSymbol](positions); // calculate indices var invalidPoints = OpcIndices.GetInvalidPositions(p); // limit triangle size if ((maxTriangleSize < float.PositiveInfinity) && (maxTriangleSize > 0.000001f)) { vg.Indices = OpcIndices.ComputeIndexArray(resolution, invalidPoints.ToList(), p, maxTriangleSize); } else { vg.Indices = OpcIndices.ComputeIndexArray(resolution, invalidPoints.ToList()); } // load normals if (loadNormals) { var normalPath = Path.Combine(basePath, "Normals.aara"); if (StorageConfig.FileExists(normalPath)) { var normals = AaraData.FromFile(normalPath); var normals3d = AaraData.ConvertArrayToV3fs[normals.DataTypeAsSymbol](normals.LoadElements()); vg.Normals = normals3d; } } // load coordinates vg.Coordinates = new CoordinatesMap(); if (loadTexCoords) { var coordPath = Path.Combine(basePath, info.Coordinates.First()); var coordinates = AaraData.FromFile(coordPath).LoadElements() as V2f[]; vg.Coordinates[VertexGeometry.Property.DiffuseColorCoordinates] = coordinates; } // load textures vg.Textures = new TexturesMap(); if (loadDiffTex) { var texFile = Path.ChangeExtension(info.Textures.First(), ".dds"); var texPath = Path.GetFullPath(Path.Combine(basePath, @"..\..\images", texFile)); if (StorageConfig.FileExists(texPath)) { var img = Convertible.FromFile(texPath); vg.Textures[VertexGeometry.Property.DiffuseColorTexture] = new Aardvark.Rendering.Texture(img) { ForceImmediateUpload = false }; } } if (loadHueTex) { vg.Textures[VertexGeometry.Property.LightMapTexture] = new Aardvark.Rendering.Texture(Resources.HueColorMap.Convertible()); } return(vg); }