/// <summary> /// Takes a VRML97 parse tree (see also <seealso cref="Parser"/>) /// and resolves all DEF and USE nodes. /// </summary> /// <param name="root">Parse tree.</param> /// <param name="duplicateMaps"></param> /// <param name="namedNodes"></param> /// <returns>Parse tree without DEF and USE nodes.</returns> public Vrml97Scene Perform(Vrml97Scene root, out Dictionary <string, SymMapBase> namedNodes, bool duplicateMaps) { root.ParseTree["DefUseResolver.Performed"] = true; // leave hint m_defs = new Dictionary <string, SymMapBase>(); SymMapBaseTraversal trav = new SymMapBaseTraversal(); trav.PerNameVisitors["USE"] = (map, visit) => { // Lookup USE name and return associated node. var name = map.Get <string>(Vrml97Sym.name); SymMapBase node; if (!m_defs.TryGetValue(name, out node)) { Report.Warn("DefUseResolver: USE " + name + ": Unknown!"); return(map); // keep "USE" ref node in SymMap-Tree //throw new Exception("DefUseResolver: USE " + name + ": Unknown!"); } return(duplicateMaps ? new SymMapBase(node) : node); }; trav.PerNameVisitors["DEF"] = (map, visit) => { // Register name/node pair. string defName = map.Get <string>(Vrml97Sym.name); SymMapBase node = map.Get <SymMapBase>(Vrml97Sym.node); m_defs[defName] = node; node["DEFname"] = defName; return(node); }; trav.Traverse(root.ParseTree); namedNodes = m_defs; return(root); }
/// <summary> /// Takes a Vrml97 parse tree (see also <seealso cref="Parser"/>) /// and replaces the file extension of all image texture URLs to /// the specified extension. /// </summary> /// <param name="root">Parse tree.</param> /// <param name="newExtension"></param> internal Vrml97Scene Perform(Vrml97Scene root, string newExtension) { SymMapBaseTraversal trav = new SymMapBaseTraversal(SymMapBaseTraversal.Visit.Post); trav.PerNameVisitors["ImageTexture"] = delegate(SymMapBase m, SymMapBaseTraversal.Visit visit) { List <string> urls = m.Get <List <string> >(Vrml97Sym.url); if (urls == null) { return(m); } for (int i = 0; i < urls.Count; i++) { int p = urls[i].LastIndexOf('.'); urls[i] = urls[i].Substring(0, p) + "." + newExtension; } return(m); }; trav.Traverse(root.ParseTree); return(root); }
/// <summary> /// Takes a Vrml97 parse tree (see also <seealso cref="Parser"/>) /// and augments all geometry nodes with material and /// transform attributes. /// </summary> /// <param name="root">Parse tree.</param> /// <returns>Augmented parse tree.</returns> public Vrml97Scene Perform(Vrml97Scene root) { root.ParseTree["AttributeAnnotator.Performed"] = true; // leave hint if (root.ParseTree.TypeName == "Vrml97") { string filename = root.ParseTree.Get <string>(Vrml97Sym.filename); m_path = Path.GetDirectoryName(filename); } m_material = new Stack <SymMapBase>(); m_texture = new Stack <SymMapBase>(); m_textureTransform = new Stack <SymMapBase>(); m_transform = new Stack <Trafo3d>(); m_transform.Push(Trafo3d.Identity); SymMapBaseTraversal trav = new SymMapBaseTraversal(SymMapBaseTraversal.Mode.Modifying, SymMapBaseTraversal.Visit.PreAndPost); trav.PerNameVisitors["ImageTexture"] = delegate(SymMapBase m, SymMapBaseTraversal.Visit visit) { if (visit == SymMapBaseTraversal.Visit.Pre) { if (m_visited.ContainsKey(m)) { return(m); } List <string> urls = m.Get <List <string> >(Vrml97Sym.url); if (urls != null) { for (int i = 0; i < urls.Count; i++) { urls[i] = Path.Combine(m_path, urls[i]); } } m_visited[m] = m; } return(m); }; // geometry nodes SymMapBaseVisitor foo = (SymMapBase m, SymMapBaseTraversal.Visit visit) => { if (visit == SymMapBaseTraversal.Visit.Post) { return(m); } if (m_material.Count == 0 && m_texture.Count == 0 && m_textureTransform.Count == 0 && m_transform.Count == 0) { return(m); } var map = new SymMapBase(m); if (m_material.Count > 0) { string key = "material"; // while (m.Contains(key)) key += "X"; map[key] = m_material.Peek(); } if (m_texture.Count > 0) { string key = "texture"; // while (m.Contains(key)) key += "X"; map[key] = m_texture.Peek(); } if (m_textureTransform.Count > 0) { string key = "textureTransform"; // while (m.Contains(key)) key += "X"; var tt = m_textureTransform.Peek(); map[key] = tt.ExtractVrmlTextureTrafo(); } if (m_transform.Count > 1) // [0] contains initial identity { string key = "transform"; // while (m.Contains(key)) key += "X"; if (m.Contains(key)) { Console.WriteLine("WARNING: trying to annotate annotated node!"); } map[key] = m_transform.Peek(); } return(map); }; trav.PerNameVisitors["IndexedFaceSet"] = foo; trav.PerNameVisitors["IndexedLineSet"] = foo; // attributes trav.PerNameVisitors["Shape"] = delegate(SymMapBase m, SymMapBaseTraversal.Visit visit) { bool hasMaterial = false; bool hasTexture = false; bool hasTextureTransform = false; SymMapBase app = null; if (m.Contains("appearance")) { app = m.Get <SymMapBase>(Vrml97Sym.appearance); hasMaterial = app.Contains(Vrml97Sym.material); hasTexture = app.Contains(Vrml97Sym.texture); hasTextureTransform = app.Contains(Vrml97Sym.textureTransform); } if (visit == SymMapBaseTraversal.Visit.Pre) { if (hasMaterial) { m_material.Push(app.Get <SymMapBase>(Vrml97Sym.material)); } if (hasTexture) { m_texture.Push(app.Get <SymMapBase>(Vrml97Sym.texture)); } if (hasTextureTransform) { m_textureTransform.Push(app.Get <SymMapBase>(Vrml97Sym.textureTransform)); } } else if (visit == SymMapBaseTraversal.Visit.Post) { if (hasMaterial) { m_material.Pop(); } if (hasTexture) { m_texture.Pop(); } if (hasTextureTransform) { m_textureTransform.Pop(); } } return(m); }; trav.PerNameVisitors["Transform"] = delegate(SymMapBase m, SymMapBaseTraversal.Visit visit) { if (visit == SymMapBaseTraversal.Visit.Pre) { var trafo = m.ExtractVrmlGeometryTrafo(); m["trafo"] = trafo; m_transform.Push(trafo * m_transform.Peek()); } else if (visit == SymMapBaseTraversal.Visit.Post) { m_transform.Pop(); } return(m); }; root.ParseTree = trav.Traverse(root.ParseTree); return(root); }