/// <summary> /// Recursively traverses supplied subPatchMap dictionary and build up a PatchTree. /// </summary> /// <param name="subPatchMap">form of [patchName, List[subPatchName]]</param> private static PatchTree PatchTreeFromPatchName(string patchName, string patchesSubdir, Dictionary <string, IEnumerable <string> > subPatchMap) { IEnumerable <string> subPatches = null; var path = Path.Combine(patchesSubdir, patchName); //read patchfileinfo var info = new PatchFileInfo(); try { info = PatchFileInfo.FromFile(path); info.IsValid = true; } catch (Exception e) { Report.Warn("PatchHierarchyXML: Parsing of patch.xml of path {0} threw an exception {1}", path, e.Message.ToString()); info.IsValid = false; } //if name does not exist in subPatchMap a leaf is reached if (!subPatchMap.TryGetValue(patchName, out subPatches)) { return(new PatchTree(patchName, info)); } //if subnodes exist recurse return(new PatchTree(patchName, info, subPatches.Select(x => PatchTreeFromPatchName(x, patchesSubdir, subPatchMap)) .Where(x => x.Info.IsValid) .ToList())); }
/// <summary> /// Takes first OPC in opcDirectory and returns its root patch info. This /// is typically needed to retrieve rendering offsets to prevent rounding errors. /// </summary> public static PatchFileInfo GetFirstPatchFileInfo(string opcDirectory, PositionsType posType) { var paths = OpcFileUtils.OpcPathsFromFolder(opcDirectory); var rootPatchPath = OpcFileUtils.GetRootPatchPath(paths.First()); return(PatchFileInfo.FromFile(rootPatchPath)); }
/// <summary> /// Loads VertexGeometry from aara files. Beware: add Local2Global node for global space. /// </summary> /// <returns>Vertex Geometry in local OPC space.</returns> public static VertexGeometry LoadPatch(PatchFileInfo info, string basePath, PositionsType posType, bool loadNormals = true, bool loadTexCoords = true, bool loadDiffTex = true, bool loadHueTex = true, float maxTriangleSize = float.PositiveInfinity, bool loadAsDoubles = false) { Array positions; Symbol dataType; return(LoadPatch(info, basePath, posType, out positions, out dataType, loadNormals, loadTexCoords, loadDiffTex, loadHueTex, maxTriangleSize, loadAsDoubles)); }
public VertexGeometry Load(PatchFileInfo info, string basePath, PositionsType posType, bool loadTextures = true, bool loadNormals = true, bool loadTexCoords = true, float maxTriangleSize = float.PositiveInfinity) { //Array positions; //Symbol dataType; bool loadDiffTex = loadTextures ? LoadDiffTex : false; bool loadHueTex = loadTextures ? LoadHueTex : false; return(LoadPatch(info, basePath, posType, //out positions, out dataType, loadNormals, loadTexCoords, loadDiffTex, loadHueTex, maxTriangleSize)); }
public PatchTree(string id, PatchFileInfo info, List <PatchTree> subNodes = null) { if (subNodes == null) { subNodes = new List <PatchTree>(); } m_id = id; m_subNodes = subNodes; m_info = info; }
/// <summary> /// Reads full patch.xml into and returns a PatchFileInfo /// </summary> public static PatchFileInfo FromFile(string patchFilePath) { if (Path.GetFileName(patchFilePath) != "patch.xml") { patchFilePath = Path.Combine(patchFilePath, "patch.xml"); } //var patch = XElement.Load(patchFilePath, LoadOptions.None).Element("Patch"); var patch = XElement.Load(Load.AsMemoryStream(patchFilePath)).Element("Patch"); var info = new PatchFileInfo() { TagList = ReadStringList(patch, "TagList"), GeometryType = ReadString(patch, "GeometryType"), QuadVertexSortOrder = ReadString(patch, "QuadVertexSortOrder", PatchFileInfo.QuadVertexSortOrderType.ColumnMajor), Local2Global = ReadM44d(patch, "Local2Global"), GlobalBoundingBox = ReadBox3d(patch, "GlobalBoundingBox"), LocalBoundingBox = ReadBox3d(patch, "LocalBoundingBox"), Positions = ReadString(patch, "Positions"), Coordinates = ReadStringList(patch, "Coordinates"), Textures = ReadStringList(patch, "Textures"), }; if (HasNormalsAndOffsets(patch)) { info.Normals = ReadString(patch, "Normals"); info.Offsets = ReadString(patch, "Offsets"); } //var x = patch.Element("Local2Global2D"); //Report.Line(x.ToString()); // //e.Element("GlobalBoundingBox2d") != null && // //e.Element("LocalBoundingBox2d") != null && // //e.Element("Positions2d") != null; if (XmlHas2dData(patch)) { info.Local2Global2d = ReadM44d(patch, "Local2Global2D"); info.GlobalBoundingBox2d = ReadBox3d(patch, "GlobalBoundingBox2D"); info.LocalBoundingBox2d = ReadBox3d(patch, "LocalBoundingBox2D"); info.Positions2d = ReadString(patch, "Positions2D"); } if (!info.LocalBoundingBox2d.IsValid) { Report.Warn("LocalBoundingBox2d is not valid"); } return(info); }
//static volatile int patchCounter = 0; /// <summary> /// Represents a single patch of ordered positions including coords, textures, etc. /// </summary> public Patch(PatchFileInfo info, string patchPath, int level, int maxLevel, PositionsType posType, bool invertZ = false, float maxTriangleSize = float.PositiveInfinity) : base(Identifier) { PatchFilePath = patchPath; Level = level; PatchFileInfo = info; MaxLevel = maxLevel; PositionsType = posType; InvertZ = invertZ; MaxTriangleSize = maxTriangleSize; //patchCounter++; //Report.Line("++" + patchCounter); }
/// <summary> /// Gets Triangle Set loaded from AaraData and transformed to global space. /// </summary> public static TriangleSet LoadPatchTriangleSet(PatchFileInfo info, string basePath, PositionsType posType) { var vg = LoadPatch(info, basePath, posType, false, false, false, false, loadAsDoubles: false); if (vg == null) { return(new TriangleSet()); } var trafo = posType == PositionsType.V3dPositions ? info.Local2Global : info.Local2Global2d; vg.TransformV3d(trafo); var triangles = vg.Triangles .Where(x => !x.Point0.Position.IsNaN && !x.Point1.Position.IsNaN && !x.Point2.Position.IsNaN) .Select(x => x.ToTriangle3d()); return(new TriangleSet(triangles)); }
/// <summary> /// Gets Triangle Set loaded from AaraData and transformed to global space. /// Triangles side length < maxTriiangleSize /// </summary> public static TriangleSet LoadPatchTriangleSetWithoutOversizedTriangles(PatchFileInfo info, string basePath, PositionsType posType, float maxTriangleSize = float.PositiveInfinity) { var vg = LoadPatch(info, basePath, posType, false, false, false, false); if (vg == null) { return(new TriangleSet()); } vg.Transform( posType == PositionsType.V3dPositions ? info.Local2Global : info.Local2Global2d); var triangles = vg.Triangles .Where(x => !x.Point0.Position.IsNaN && !x.Point1.Position.IsNaN && !x.Point2.Position.IsNaN && (V3d.Distance(x.Point0.Position, x.Point1.Position) < maxTriangleSize) && (V3d.Distance(x.Point0.Position, x.Point2.Position) < maxTriangleSize) && (V3d.Distance(x.Point1.Position, x.Point2.Position) < maxTriangleSize)) .Select(x => x.ToTriangle3d()); return(new TriangleSet(triangles)); }
//~Patch() //{ // patchCounter--; // Report.Line("--" + patchCounter); //} public static Patch FromFile(string patchXmlPath, int level, int maxLevel, PositionsType posType) { return(new Patch(PatchFileInfo.FromFile(patchXmlPath), patchXmlPath, level, maxLevel, posType)); }
/// <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); }