Exemplo n.º 1
0
        /// <summary>
        /// Reads data from the aara file.
        /// </summary>
        /// <param name="count">Number of elements to read.</param>
        /// <param name="startPos">Position of first element to read in the data block (header will be skipped).</param>
        /// <returns></returns>
        public Array LoadElements(int count, int startPos = 0)
        {
            using (s_cpu_AaraDataReadMemoryStream.Timer)
            {
                if ((count + startPos) > ElementCount)
                {
                    Report.Warn("AaraData tried reading over end of file '" + SourceFileName + "'");
                    return(CreateEmptyArray[DataTypeAsSymbol]());
                }
                else if (startPos < 0)
                {
                    Report.Warn("AaraData tried indexing < 0 in file '" + SourceFileName + "'");
                    return(CreateEmptyArray[DataTypeAsSymbol]());
                }

                var countInByte    = count * s_sizeTable[DataTypeAsSymbol];
                var startPosInByte = startPos * s_sizeTable[DataTypeAsSymbol];
                var readFun        = s_readBigFuncs[DataTypeAsSymbol];

                // load from file to memory
                var memStream = Load.AsMemoryStream(SourceFileName, HeaderSize + startPosInByte, countInByte);

                // convert from memory stream to actual data
                return(readFun(new StreamCodeReader(memStream), count));
            }
        }
Exemplo n.º 2
0
        public override NDArrayOrSymbol Forward(NDArrayOrSymbol x, NDArrayOrSymbol[] args)
        {
            if (x.IsNDArray)
            {
                return(CallCachedOp(args.ToList().ToNDArrays())[0]);
            }

            int[] in_fmt = null;
            var   inputs = new List <NDArrayOrSymbol>();

            inputs.Add(x);
            inputs.AddRange(args);

            (args, in_fmt) = Flatten(inputs.ToArray(), "input");
            if (in_fmt != _in_format.ToArray())
            {
                throw new Exception("Invalid input format");
            }

            var        ret         = _cached_graph.Value.Item2.Shallowcopy();
            SymbolDict composeArgs = new SymbolDict();

            for (int i = 0; i < _cached_graph.Value.Item1.Length; i++)
            {
                composeArgs.Add(_cached_graph.Value.Item1[0].Name, args[i]);
            }

            ret.Compose(composeArgs);

            return(Regroup(new List <NDArrayOrSymbol[]>()
            {
                new NDArrayOrSymbol[] { ret }
            }, _out_format.ToList()).Item1[0]);
        }
Exemplo n.º 3
0
 public NodeParseInfo(
     NodeParser parseFunction,
     SymbolDict <Tup <FieldParser, object> > fields)
 {
     m_parseFunction = parseFunction;
     FieldDefs       = fields;
 }
Exemplo n.º 4
0
        public void SymbolDictInitializationTest()
        {
            var map = new SymbolDict <int>()
            {
                { "zero", 0 },
                { "one", 1 },
                { "two", 2 },
                { "three", 3 },
                { "four", 4 },
                { "five", 5 },
                { "six", 6 },
                { "seven", 7 },
                { "eight", 8 },
                { "nine", 9 },
                { "ten", 10 },
            };

            foreach (var kvp in map)
            {
                Report.Line("{0}: {1}", kvp.Key, kvp.Value);
            }

            var set = new SymbolSet()
            {
                "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
                "nine", "ten",
            };

            foreach (var item in set)
            {
                Report.Line("{0}, ", item);
            }
        }
Exemplo n.º 5
0
        static void Main(string[] args)
        {
            Ag.initialize();
            Aardvark.Base.Aardvark.Init();

            using (var app = new OpenGlApplication())
            {
                var win = app.CreateSimpleRenderWindow(1);

                var view = CameraView.LookAt(new V3d(2.0, 2.0, 2.0), V3d.Zero, V3d.OOI);
                var perspective =
                    win.Sizes.Select(s => FrustumModule.perspective(60.0,0.1,10.0,((float) s.X / (float) s.Y)));


                var viewTrafo = DefaultCameraController.control(win.Mouse, win.Keyboard, win.Time, view);

                var index = new[] { 0, 1, 2, 0, 2, 3 };
                var positions = new[] { new V3f(-1, -1, 0), new V3f(1, -1, 0), new V3f(1, 1, 0), new V3f(-1, 1, 0) };

                var attributes = new SymbolDict<Array>()
                {
                    { DefaultSemantic.Positions, positions }
                };

                var quad = new IndexedGeometry(IndexedGeometryMode.TriangleList, 
                        (Array)index, 
                        attributes, 
                        new SymbolDict<Object>());

                var quadSg = quad.ToSg();

                // This is one of the hardest parts in C#. Our FShade interface is rather generic and
                // works super awesome in F#. In C# however, without proper type inference doing simple function
                // calls suddenly requires a Phd in CS. Therefore, and especially since shaders cannot be written
                // in C# anyways, write application setup and shader code in F# ;)
                // Or don't use FShade. FShade simply does not work in without functional language 
                // features such as type inference and function currying.
                Func<DefaultSurfaces.Vertex, FSharpExpr<V4d>> whiteShader =
                        HighFun.ApplyArg0<C4f, DefaultSurfaces.Vertex, FSharpExpr<V4d>>(
                            DefaultSurfaces.constantColor, C4f.White);
                Func<DefaultSurfaces.Vertex, FSharpExpr<DefaultSurfaces.Vertex>> trafo = c => DefaultSurfaces.trafo(c);

                var sg = 
                    quadSg
                    .WithEffects(new[] {
                        FShadeSceneGraph.toEffect(FSharpFuncUtil.Create(trafo)),
                        FShadeSceneGraph.toEffect(FSharpFuncUtil.Create(whiteShader)),
                    })
                    .ViewTrafo(viewTrafo.Select(t => t.ViewTrafo))
                    .ProjTrafo(perspective.Select(t => t.ProjTrafo()));

                var task = app.Runtime.CompileRender(win.FramebufferSignature, sg);

                win.RenderTask = DefaultOverlays.withStatistics(task);
                win.Run();
             }
        }
Exemplo n.º 6
0
        static void Main(string[] args)
        {
            Ag.initialize();
            Aardvark.Base.Aardvark.Init();

            using (var app = new OpenGlApplication())
            {
                var win = app.CreateSimpleRenderWindow(1);

                var view        = CameraView.LookAt(new V3d(2.0, 2.0, 2.0), V3d.Zero, V3d.OOI);
                var perspective =
                    win.Sizes.Select(s => FrustumModule.perspective(60.0, 0.1, 10.0, ((float)s.X / (float)s.Y)));


                var viewTrafo = DefaultCameraController.control(win.Mouse, win.Keyboard, win.Time, view);

                var index     = new[] { 0, 1, 2, 0, 2, 3 };
                var positions = new[] { new V3f(-1, -1, 0), new V3f(1, -1, 0), new V3f(1, 1, 0), new V3f(-1, 1, 0) };

                var attributes = new SymbolDict <Array>()
                {
                    { DefaultSemantic.Positions, positions }
                };

                var quad = new IndexedGeometry(IndexedGeometryMode.TriangleList,
                                               (Array)index,
                                               attributes,
                                               new SymbolDict <Object>());

                var quadSg = quad.ToSg();

                // This is one of the hardest parts in C#. Our FShade interface is rather generic and
                // works super awesome in F#. In C# however, without proper type inference doing simple function
                // calls suddenly requires a Phd in CS. Therefore, and especially since shaders cannot be written
                // in C# anyways, write application setup and shader code in F# ;)
                // Or don't use FShade. FShade simply does not work in without functional language
                // features such as type inference and function currying.
                Func <DefaultSurfaces.Vertex, FSharpExpr <V4d> > whiteShader =
                    HighFun.ApplyArg0 <C4f, DefaultSurfaces.Vertex, FSharpExpr <V4d> >(
                        DefaultSurfaces.constantColor, C4f.White);
                Func <DefaultSurfaces.Vertex, FSharpExpr <DefaultSurfaces.Vertex> > trafo = c => DefaultSurfaces.trafo(c);

                var sg =
                    quadSg
                    .WithEffects(new[] {
                    FShadeSceneGraph.toEffect(FSharpFuncUtil.Create(trafo)),
                    FShadeSceneGraph.toEffect(FSharpFuncUtil.Create(whiteShader)),
                })
                    .ViewTrafo(viewTrafo.Select(t => t.ViewTrafo))
                    .ProjTrafo(perspective.Select(t => t.ProjTrafo()));

                var task = app.Runtime.CompileRender(win.FramebufferSignature, sg);

                win.RenderTask = DefaultOverlays.withStatistics(task);
                win.Run();
            }
        }
Exemplo n.º 7
0
        /** Static constructor. */
        static Parser()
        {
            var SFBool = new FieldParser(ParseSFBool);
            //var MFBool = new FieldParser(ParseMFBool);
            var SFColor    = new FieldParser(ParseSFColor);
            var MFColor    = new FieldParser(ParseMFColor);
            var SFFloat    = new FieldParser(ParseSFFloat);
            var MFFloat    = new FieldParser(ParseMFFloat);
            var SFImage    = new FieldParser(ParseSFImage);
            var SFInt32    = new FieldParser(ParseSFInt32);
            var MFInt32    = new FieldParser(ParseMFInt32);
            var SFNode     = new FieldParser(ParseSFNode);
            var MFNode     = new FieldParser(ParseMFNode);
            var SFRotation = new FieldParser(ParseSFRotation);
            var MFRotation = new FieldParser(ParseMFRotation);
            var SFString   = new FieldParser(ParseSFString);
            var MFString   = new FieldParser(ParseMFString);
            var SFTime     = new FieldParser(ParseSFFloat);
            //var MFTime = new FieldParser(ParseMFFloat);
            var SFVec2f = new FieldParser(ParseSFVec2f);
            var MFVec2f = new FieldParser(ParseMFVec2f);
            var SFVec3f = new FieldParser(ParseSFVec3f);
            var MFVec3f = new FieldParser(ParseMFVec3f);

            //            Dictionary<string, (FieldParser, object)> fields;

            // Lookup table for Vrml97 node types.
            // For each node type a NodeParseInfo entry specifies how
            // to handle this kind of node.
            m_parseInfoMap = new SymbolDict <NodeParseInfo>
            {
                // DEF
                [Vrml97Sym.DEF] = new NodeParseInfo(new NodeParser(ParseDEF)),

                // USE
                [Vrml97Sym.USE] = new NodeParseInfo(new NodeParser(ParseUSE)),

                // ROUTE
                [Vrml97Sym.ROUTE] = new NodeParseInfo(new NodeParser(ParseROUTE)),

                // NULL
                [Vrml97Sym.NULL] = new NodeParseInfo(new NodeParser(ParseNULL))
            };

            var defaultBBoxCenter = (SFVec3f, (object)V3f.Zero);
            var defaultBBoxSize   = (SFVec3f, (object)new V3f(-1, -1, -1));

            (FieldParser, object) fdd(FieldParser fp, object obj) => (fp, obj);
            (FieldParser, object) fd(FieldParser fp) => (fp, null);

            // Anchor
            m_parseInfoMap["Anchor"] = new NodeParseInfo(
                new SymbolDict <(FieldParser, object)>()
            {
                { "children", fd(MFNode) },
                { "description", fd(SFString) },
Exemplo n.º 8
0
        public static T TryPop <T>(this SymbolDict <T> self, Symbol key)
        {
            T value = default(T);

            if (self.TryGetValue(key, out value))
            {
                self.Remove(key);
            }
            return(value);
        }
Exemplo n.º 9
0
        public static T[] GetArray <T>(this SymbolDict <Array> dict, Symbol name, T[] defaultArray)
        {
            Array array;

            if (dict.TryGetValue(name, out array))
            {
                return((T[])array);
            }
            return(defaultArray);
        }
Exemplo n.º 10
0
        public static T[] GetArray <T>(this SymbolDict <Array> dict, Symbol name)
        {
            Array array;

            if (dict.TryGetValue(name, out array))
            {
                return((T[])array);
            }
            throw new ArgumentException(
                      String.Format("symbol \"{0}\" not found in dictionary", name));
        }
Exemplo n.º 11
0
        public static SymbolDict <Tv> Copy <Tv>(
            this SymbolDict <Tv> self)
        {
            var r = new SymbolDict <Tv>(self.Count);

            foreach (var kvp in self)
            {
                r[kvp.Key] = kvp.Value;
            }
            return(r);
        }
Exemplo n.º 12
0
        protected PolyLine(Symbol identifier)
            : base(identifier)
        {
            m_vertexCount    = 0;
            m_hideLastVertex = false;
            m_positionArray  = null;

            VertexAttributes   = new SymbolDict <Array>();
            LineAttributes     = new SymbolDict <Array>();
            InstanceAttributes = new SymbolDict <object>();
        }
Exemplo n.º 13
0
        public void Awake(int codedVersion)
        {
            m_vertexCount        = Get <int>(Property.VertexCount);
            m_hideLastVertex     = Get <bool>(Property.HideLastVertex);
            m_vertexAttributes   = Get <SymbolDict <Array> >(Property.VertexAttributes);
            m_lineAttributes     = Get <SymbolDict <Array> >(Property.LineAttributes);
            m_instanceAttributes = Get <SymbolDict <object> >(Property.InstanceAttributes);

            // use proerty assignment to initialize dependent fields
            PositionArray = VertexAttributeArray <V3d>(Property.Positions);
        }
Exemplo n.º 14
0
        public static SymbolDict <Tr> Copy <T, Tr>(
            this SymbolDict <T> self,
            Func <Symbol, T, Tr> fun)
        {
            var r = new SymbolDict <Tr>(self.Count);

            foreach (var kvp in self)
            {
                r[kvp.Key] = fun(kvp.Key, kvp.Value);
            }
            return(r);
        }
Exemplo n.º 15
0
        public static SymbolDict <Tr> Copy <T, Tr>(
            this SymbolDict <T> self,
            Func <KeyValuePair <Symbol, T>, KeyValuePair <Symbol, Tr> > fun)
        {
            var r = new SymbolDict <Tr>(self.Count);

            foreach (var kvp in self)
            {
                var nkvp = fun(kvp);
                r[nkvp.Key] = nkvp.Value;
            }
            return(r);
        }
Exemplo n.º 16
0
        public void ConcurrentSymbolDictTest(int rounds, int tasks)
        {
            int count = m_stringTable.Length;
            int block = count / tasks;

            var rnd  = new RandomSystem();
            var perm = new int[count].SetByIndex(i => i);

            var map = new SymbolDict <int>().AsConcurrent();

            // var map = new FastConcurrentSymbolDict<int>();

            Test.Begin("parallel adding and removing tests {0}", count);
            for (int r = 0; r < rounds; r++)
            {
                Test.Begin("round {0}", r);
                Test.Begin("adding in parallel");
                Parallel.For(0, tasks, t =>
                {
                    for (int i = t * block, e = i + block; i < e; i++)
                    {
                        map[m_symbolTable[perm[i]]] = i;
                    }
                });
                Test.IsTrue(count == map.Count);
                Test.End();

                Test.Begin("checking");
                for (int i = 0; i < count; i++)
                {
                    Test.IsTrue(map[m_symbolTable[perm[i]]] == i);
                }
                Test.End();

                rnd.Randomize(perm);
                Test.Begin("removing in parallel");
                Parallel.For(0, tasks, t =>
                {
                    for (int i = t * block, e = i + block; i < e; i++)
                    {
                        map.Remove(m_symbolTable[perm[i]]);
                    }
                });
                Test.IsTrue(map.Count == 0);
                Test.End();
                Test.End();
            }
            Test.End();
        }
Exemplo n.º 17
0
 /// <summary>
 /// Creates a shallow copy of the supplied map, but uses entries
 /// in the supplied override dictionary instead of map entries
 /// where they exist.
 /// </summary>
 public SymMapBase(SymMapBase map, SymbolDict<object> overrides)
     : this(map.m_typeName,
            overrides != null ? overrides.Copy() : new SymbolDict<object>())
 {
     if (overrides != null)
     {
         foreach (var item in map.m_ht)
         {
             if (overrides.Contains(item.Key)) continue;
             m_ht[item.Key] = item.Value;
         }
     }
     else
     {
         foreach (var item in map.m_ht)
             m_ht[item.Key] = item.Value;
     }
 }
Exemplo n.º 18
0
        static IModRef <BackendConfiguration> SetScene(IRenderControl win)
        {
            var view        = CameraView.LookAt(new V3d(2.0, 2.0, 2.0), V3d.Zero, V3d.OOI);
            var perspective =
                win.Sizes.Select(s => FrustumModule.perspective(60.0, 0.1, 10.0, ((float)s.X / (float)s.Y)));


            var viewTrafo = DefaultCameraController.control(win.Mouse, win.Keyboard, win.Time, view);

            var index     = new[] { 0, 1, 2, 0, 2, 3 };
            var positions = new[] { new V3f(-1, -1, 0), new V3f(1, -1, 0), new V3f(1, 1, 0), new V3f(-1, 1, 0) };

            var attributes = new SymbolDict <Array>()
            {
                { DefaultSemantic.Positions, positions }
            };

            var quad = new IndexedGeometry(IndexedGeometryMode.TriangleList,
                                           (Array)index,
                                           attributes,
                                           new SymbolDict <Object>());

            var quadSg = quad.ToSg();

            var whiteShader = Effects.ConstantColor.Effect(C4f.White);

            var trafo = Effects.Trafo.Effect;

            var sg =
                quadSg
                .WithEffects(new[] { trafo, whiteShader })
                .ViewTrafo(viewTrafo.Select(t => t.ViewTrafo))
                .ProjTrafo(perspective.Select(t => t.ProjTrafo()));

            var config = new ModRef <BackendConfiguration>(BackendConfigurationModule.UnmanagedOptimized);
            var task   = ((Aardvark.Rendering.GL.Runtime)win.Runtime).CompileRender(win.FramebufferSignature, config, Aardvark.SceneGraph.Semantics.RenderObjectSemantics.Semantic.renderObjects(sg));

            win.RenderTask = DefaultOverlays.withStatistics(task);

            return(config);
        }
Exemplo n.º 19
0
        public static SymbolDict <T1v> Copy <Tv, T1v>(
            this SymbolDict <Tv> self,
            SymbolDict <Func <Tv, T1v> > funMap,
            Func <Tv, T1v> defaultFun)
        {
            var r = new SymbolDict <T1v>(self.Count);

            foreach (var kvp in self)
            {
                Func <Tv, T1v> fun;
                if (funMap.TryGetValue(kvp.Key, out fun))
                {
                    r[kvp.Key] = fun(kvp.Value);
                }
                else if (defaultFun != null)
                {
                    r[kvp.Key] = defaultFun(kvp.Value);
                }
            }
            return(r);
        }
        public static IndexedGeometry GetIndexedGeometry(
            this PolyMesh mesh,
            PolyMesh.GetGeometryOptions options,
            double absoluteEps,
            IEnumerable <int> faceIndices,
            IEnumerable <Symbol> faceAttributeNames,
            IEnumerable <Symbol> vertexAttributeNames,
            IEnumerable <Symbol> faceVertexAttributeNames,
            IEnumerable <Symbol> instanceAttributeNames)
        {
            var faceBackMap = faceIndices.ToArray();
            var faceAttributeArray
                = (from a in faceAttributeNames
                   select PolyMesh.GetIAttribute(a, mesh.FaceAttributes)).WhereNotNull().ToArray();
            var vertexAttributeArray
                = (from a in vertexAttributeNames
                   select PolyMesh.GetIAttribute(a, mesh.VertexAttributes)).WhereNotNull().ToArray();
            var faceVertexAttributeArray
                = (from a in faceVertexAttributeNames
                   select PolyMesh.GetIAttribute(a, mesh.FaceVertexAttributes)).WhereNotNull().ToArray();

            var instanceAttributes = new SymbolDict <object>();

            foreach (var name in instanceAttributeNames)
            {
                instanceAttributes[name] = mesh.InstanceAttributes[name];
            }

            return(mesh.GetIndexedGeometry(
                       options,
                       absoluteEps,
                       faceBackMap,
                       faceAttributeArray,
                       vertexAttributeArray,
                       faceVertexAttributeArray,
                       instanceAttributes
                       ));
        }
 public static PolyMesh.Grouping Group(
     this IEnumerable <PolyMesh> meshes, SymbolDict <object> defaultInstanceValues = null)
 {
     return(Group(from m in meshes from f in m.Faces select f, defaultInstanceValues));
 }
Exemplo n.º 22
0
 /// <summary>
 /// Creates a shallow copy of the supplied map, but uses entries
 /// in the supplied override dictionary instead of map entries
 /// where they exist.
 /// </summary>
 public SymMap(SymMap map, SymbolDict <object> overrides)
     : base(map, overrides)
 {
     m_guidSymbol = Symbol.CreateNewGuid();
 }
Exemplo n.º 23
0
        public void SymbolDictTest(int rounds)
        {
            int count = m_stringTable.Length;
            int block = count / 10;

            var rnd  = new RandomSystem();
            var perm = new int[count].SetByIndex(i => i);

            var map = new SymbolDict <int>();

            Test.Begin("adding removing tests {0}", count);

            for (int r = 0; r < rounds; r++)
            {
                Test.Begin("round {0}", r);
                int added = 0;
                while (added < count)
                {
                    Test.Begin("adding 20%");
                    for (int i = added; i < added + 2 * block; i++)
                    {
                        map[m_symbolTable[perm[i]]] = i;
                    }
                    added += 2 * block;
                    Test.IsTrue(added == map.Count);
                    Test.End();

                    if (added == count)
                    {
                        break;
                    }

                    Test.Begin("removing 10%");
                    for (int i = added - block; i < added; i++)
                    {
                        int index   = 0;
                        var removed = map.TryRemove(m_symbolTable[perm[i]], out index);
                        Test.IsTrue(removed);
                        Test.IsTrue(index == i);
                    }
                    added -= block;
                    Test.IsTrue(added == map.Count);
                    Test.End();
                }
                Test.Begin("checking");
                for (int i = 0; i < count; i++)
                {
                    Test.IsTrue(map[m_symbolTable[perm[i]]] == i);
                }
                Test.IsTrue(count == map.Count);
                Test.End();
                added += 2 * block;
                rnd.Randomize(perm);
                Test.Begin("removing 100%");
                if ((r & 1) == 0)
                {
                    for (int i = 0; i < count; i++)
                    {
                        int  index   = 0;
                        bool removed = map.TryRemove(m_symbolTable[perm[i]], out index);
                        Test.IsTrue(removed);
                    }
                }
                else
                {
                    map.Clear();
                }
                Test.IsTrue(map.Count == 0);
                Test.End();
                Test.End();
            }
            Test.End();
        }
Exemplo n.º 24
0
 public SymMap(Symbol typeName, SymbolDict <object> ht)
     : base(typeName, ht)
 {
     m_guidSymbol = Symbol.CreateNewGuid();
 }
Exemplo n.º 25
0
 public RNNParams(string prefix = "")
 {
     _prefix = prefix;
     _params = new SymbolDict();
 }
Exemplo n.º 26
0
 public NodeParseInfo(
     SymbolDict <Tup <FieldParser, object> > fields)
     : this(null, fields)
 {
 }
Exemplo n.º 27
0
 /// <summary>
 /// Return an IDict with the supplied Dict added as deltas. Internally
 /// the supplied dicts are not modified, but referenced, and a suitable
 /// DeltaDict is built.
 /// </summary>
 public static IDict <Symbol, TValue> WithAdded <TKey, TValue>(
     this IDict <Symbol, TValue> dict,
     SymbolDict <TValue> deltaDict)
 {
     return(new DeltaSymbolDict <TValue>(dict, deltaDict));
 }
Exemplo n.º 28
0
 public SymMapBase(Symbol typeName, SymbolDict <object> ht)
 {
     m_typeName = typeName;
     m_ht       = ht;
 }
Exemplo n.º 29
0
        /** Static constructor. */
        static Parser()
        {
            FieldParser SFBool = new FieldParser(ParseSFBool);
            //FieldParser MFBool = new FieldParser(ParseMFBool);
            FieldParser SFColor    = new FieldParser(ParseSFColor);
            FieldParser MFColor    = new FieldParser(ParseMFColor);
            FieldParser SFFloat    = new FieldParser(ParseSFFloat);
            FieldParser MFFloat    = new FieldParser(ParseMFFloat);
            FieldParser SFImage    = new FieldParser(ParseSFImage);
            FieldParser SFInt32    = new FieldParser(ParseSFInt32);
            FieldParser MFInt32    = new FieldParser(ParseMFInt32);
            FieldParser SFNode     = new FieldParser(ParseSFNode);
            FieldParser MFNode     = new FieldParser(ParseMFNode);
            FieldParser SFRotation = new FieldParser(ParseSFRotation);
            FieldParser MFRotation = new FieldParser(ParseMFRotation);
            FieldParser SFString   = new FieldParser(ParseSFString);
            FieldParser MFString   = new FieldParser(ParseMFString);
            FieldParser SFTime     = new FieldParser(ParseSFFloat);
            //FieldParser MFTime = new FieldParser(ParseMFFloat);
            FieldParser SFVec2f = new FieldParser(ParseSFVec2f);
            FieldParser MFVec2f = new FieldParser(ParseMFVec2f);
            FieldParser SFVec3f = new FieldParser(ParseSFVec3f);
            FieldParser MFVec3f = new FieldParser(ParseMFVec3f);

//            Dictionary<string, Tup<FieldParser, object>> fields;

            // Lookup table for Vrml97 node types.
            // For each node type a NodeParseInfo entry specifies how
            // to handle this kind of node.
            m_parseInfoMap = new SymbolDict <NodeParseInfo>();


            // DEF
            m_parseInfoMap[Vrml97Sym.DEF] = new NodeParseInfo(new NodeParser(ParseDEF));

            // USE
            m_parseInfoMap[Vrml97Sym.USE] = new NodeParseInfo(new NodeParser(ParseUSE));

            // ROUTE
            m_parseInfoMap[Vrml97Sym.ROUTE] = new NodeParseInfo(new NodeParser(ParseROUTE));

            // NULL
            m_parseInfoMap[Vrml97Sym.NULL] = new NodeParseInfo(new NodeParser(ParseNULL));

            var defaultBBoxCenter = Tup.Create(SFVec3f, (object)V3f.Zero);
            var defaultBBoxSize   = Tup.Create(SFVec3f, (object)new V3f(-1, -1, -1));

            Func <FieldParser, object, Tup <FieldParser, object> > fdd =
                (fp, obj) => Tup.Create(fp, obj);
            Func <FieldParser, Tup <FieldParser, object> > fd =
                fp => new Tup <FieldParser, object>(fp, null);

            // Anchor
            m_parseInfoMap["Anchor"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "children", fd(MFNode) },
                { "description", fd(SFString) },
                { "parameter", fd(MFString) },
                { "url", fd(MFString) },
                { "bboxCenter", defaultBBoxCenter },
                { "bboxSize", defaultBBoxSize }
            });

            // Appearance
            m_parseInfoMap["Appearance"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "material", fd(SFNode) },
                { "texture", fd(SFNode) },
                { "textureTransform", fd(SFNode) }
            });

            // AudioClip
            m_parseInfoMap["AudioClip"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "description", fd(SFString) },
                { "loop", fdd(SFBool, false) },
                { "pitch", fdd(SFFloat, 1.0f) },
                { "startTime", fdd(SFTime, 0.0f) },
                { "stopTime", fdd(SFTime, 0.0f) },
                { "url", fd(MFString) }
            });

            // Background
            m_parseInfoMap["Background"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "groundAngle", fd(MFFloat) },
                { "groundColor", fd(MFColor) },
                { "backUrl", fd(MFString) },
                { "bottomUrl", fd(MFString) },
                { "frontUrl", fd(MFString) },
                { "leftUrl", fd(MFString) },
                { "rightUrl", fd(MFString) },
                { "topUrl", fd(MFString) },
                { "skyAngle", fd(MFFloat) },
                { "skyColor", fdd(MFColor, C3f.Black) }
            });

            // Billboard
            m_parseInfoMap["Billboard"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "axisOfRotation", fdd(SFVec3f, new V3f(0.0f, 1.0f, 0.0f)) },
                { "children", fd(MFNode) },
                { "bboxCenter", defaultBBoxCenter },
                { "bboxSize", defaultBBoxSize }
            });


            // Box
            m_parseInfoMap["Box"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "size", fdd(SFVec3f, new V3f(2.0f, 2.0f, 2.0f)) }
            });

            // Collision
            m_parseInfoMap["Collision"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "children", fd(MFNode) },
                { "collide", fdd(SFBool, true) },
                { "bboxCenter", defaultBBoxCenter },
                { "bboxSize", defaultBBoxSize },
                { "proxy", fd(SFNode) }
            });

            // Color
            m_parseInfoMap["Color"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "color", fd(MFColor) }
            });

            // ColorInterpolator
            m_parseInfoMap["ColorInterpolator"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "key", fd(MFFloat) },
                { "keyValue", fd(MFColor) }
            });

            // Cone
            m_parseInfoMap["Cone"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "bottomRadius", fdd(SFFloat, 1.0f) },
                { "height", fdd(SFFloat, 2.0f) },
                { "side", fdd(SFBool, true) },
                { "bottom", fdd(SFBool, true) }
            });

            // Coordinate
            m_parseInfoMap["Coordinate"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "point", fd(MFVec3f) }
            });

            // CoordinateInterpolator
            m_parseInfoMap["CoordinateInterpolator"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "key", fd(MFFloat) },
                { "keyValue", fd(MFVec3f) }
            });

            // Cylinder
            m_parseInfoMap["Cylinder"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "bottom", fdd(SFBool, true) },
                { "height", fdd(SFFloat, 2.0f) },
                { "radius", fdd(SFFloat, 1.0f) },
                { "side", fdd(SFBool, true) },
                { "top", fdd(SFBool, true) }
            });

            // CylinderSensor
            m_parseInfoMap["CylinderSensor"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "autoOffset", fdd(SFBool, true) },
                { "diskAngle", fdd(SFFloat, 0.262f) },
                { "enabled", fdd(SFBool, true) },
                { "maxAngle", fdd(SFFloat, -1.0f) },
                { "minAngle", fdd(SFFloat, 0.0f) },
                { "offset", fdd(SFFloat, 0.0f) }
            });

            // DirectionalLight
            m_parseInfoMap["DirectionalLight"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "ambientIntensity", fdd(SFFloat, 0.0f) },
                { "color", fdd(SFColor, C3f.White) },
                { "direction", fdd(SFVec3f, new V3f(0.0f, 0.0f, -1.0f)) },
                { "intensity", fdd(SFFloat, 1.0f) },
                { "on", fdd(SFBool, true) }
            });

            // ElevationGrid
            m_parseInfoMap["ElevationGrid"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "color", fd(SFNode) },
                { "normal", fd(SFNode) },
                { "texCoord", fd(SFNode) },
                { "height", fd(MFFloat) },
                { "ccw", fdd(SFBool, true) },
                { "colorPerVertex", fdd(SFBool, true) },
                { "creaseAngle", fdd(SFFloat, 0.0f) },
                { "normalPerVertex", fdd(SFBool, true) },
                { "solid", fdd(SFBool, true) },
                { "xDimension", fdd(SFInt32, 0) },
                { "xSpacing", fdd(SFFloat, 1.0f) },
                { "zDimension", fdd(SFInt32, 0) },
                { "zSpacing", fdd(SFFloat, 1.0f) }
            });

            // Extrusion
            m_parseInfoMap["Extrusion"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "beginCap", fdd(SFBool, true) },
                { "ccw", fdd(SFBool, true) },
                { "convex", fdd(SFBool, true) },
                { "creaseAngle", fdd(SFFloat, 0.0f) },
                { "crossSection", fdd(MFVec2f, new List <V2f>()
                    {
                        new V2f(1.0f, 1.0f), new V2f(1.0f, -1.0f), new V2f(-1.0f, -1.0f), new V2f(-1.0f, 1.0f), new V2f(1.0f, 1.0f)
                    }) },
                { "endCap", fdd(SFBool, true) },
                { "orientation", fdd(MFRotation, new V4f(0.0f, 0.0f, 1.0f, 0.0f)) },
                { "scale", fdd(MFVec2f, new V2f(1.0f, 1.0f)) },
                { "solid", fdd(SFBool, true) },
                { "spine", fdd(MFVec3f, new List <V3f>()
                    {
                        V3f.Zero, new V3f(0.0f, 1.0f, 0.0f)
                    }) }
            });

            // Fog
            m_parseInfoMap["Fog"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "color", fdd(SFColor, C3f.White) },
                { "fogType", fdd(SFString, "LINEAR") },
                { "visibilityRange", fdd(SFFloat, 0.0f) }
            });

            // FontStyle
            m_parseInfoMap["FontStyle"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "family", fdd(MFString, "SERIF") },
                { "horizontal", fdd(SFBool, true) },
                { "justify", fdd(MFString, "BEGIN") },
                { "language", fd(SFString) },
                { "leftToRight", fdd(SFBool, true) },
                { "size", fdd(SFFloat, 1.0f) },
                { "spacing", fdd(SFFloat, 1.0f) },
                { "style", fdd(SFString, "PLAIN") },
                { "topToBottom", fdd(SFBool, true) }
            });

            // Group
            m_parseInfoMap["Group"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "children", fd(MFNode) },
                { "bboxCenter", defaultBBoxCenter },
                { "bboxSize", defaultBBoxSize }
            });

            // ImageTexture
            m_parseInfoMap["ImageTexture"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "url", fd(MFString) },
                { "repeatS", fdd(SFBool, true) },
                { "repeatT", fdd(SFBool, true) }
            });

            // IndexedFaceSet
            m_parseInfoMap["IndexedFaceSet"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "color", fd(SFNode) },
                { "coord", fd(SFNode) },
                { "normal", fd(SFNode) },
                { "texCoord", fd(SFNode) },
                { "ccw", fdd(SFBool, true) },
                { "colorIndex", fd(MFInt32) },
                { "colorPerVertex", fdd(SFBool, true) },
                { "convex", fdd(SFBool, true) },
                { "coordIndex", fd(MFInt32) },
                { "creaseAngle", fdd(SFFloat, 0.0f) },
                { "normalIndex", fd(MFInt32) },
                { "normalPerVertex", fdd(SFBool, true) },
                { "solid", fdd(SFBool, true) },
                { "texCoordIndex", fd(MFInt32) },
                { "edgeSharpness", fd(MFFloat) },
                { "edgeSharpnessIndex", fd(MFInt32) },
                { "neighborMesh", fd(MFString) },
                { "neighborIndex", fd(MFInt32) },
                { "neighborSide", fd(MFInt32) },
                { "neighborFace", fd(MFInt32) },
                { "meshName", fd(SFString) },
                { "topologyHoles", fd(SFInt32) }
            });

            // IndexedLineSet
            m_parseInfoMap["IndexedLineSet"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "color", fd(SFNode) },
                { "coord", fd(SFNode) },
                { "colorIndex", fd(MFInt32) },
                { "colorPerVertex", fdd(SFBool, true) },
                { "coordIndex", fd(MFInt32) }
            });

            // Inline
            m_parseInfoMap["Inline"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "url", fd(MFString) },
                { "bboxCenter", defaultBBoxCenter },
                { "bboxSize", defaultBBoxSize }
            });

            // LOD
            m_parseInfoMap["LOD"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "level", fd(MFNode) },
                { "center", defaultBBoxCenter },
                { "range", fd(MFFloat) }
            });

            // Material
            m_parseInfoMap["Material"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "ambientIntensity", fdd(SFFloat, 0.2f) },
                { "diffuseColor", fdd(SFColor, new C3f(0.8f, 0.8f, 0.8f)) },
                { "emissiveColor", fdd(SFColor, C3f.Black) },
                { "shininess", fdd(SFFloat, 0.2f) },
                { "specularColor", fdd(SFColor, C3f.Black) },
                { "transparency", fdd(SFFloat, 0.0f) }
            });

            // MovieTexture
            m_parseInfoMap["MovieTexture"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "loop", fdd(SFBool, false) },
                { "speed", fdd(SFFloat, 1.0f) },
                { "startTime", fdd(SFTime, 1.0f) },
                { "stopTime", fdd(SFTime, 1.0f) },
                { "url", fd(MFString) },
                { "repeatS", fdd(SFBool, true) },
                { "repeatT", fdd(SFBool, true) }
            });

            // NavigationInfo
            m_parseInfoMap["NavigationInfo"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "avatarSize", fdd(MFFloat, new List <float>()
                    {
                        0.25f, 1.6f, 0.75f
                    }) },
                { "headlight", fdd(SFBool, true) },
                { "speed", fdd(SFFloat, 1.0f) },
                { "type", fdd(MFString, new List <string>()
                    {
                        "WALK", "ANY"
                    }) },
                { "visibilityLimit", fdd(SFFloat, 0.0f) }
            });

            // Normal
            m_parseInfoMap["Normal"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "vector", fd(MFVec3f) }
            });

            // NormalInterpolator
            m_parseInfoMap["NormalInterpolator"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "key", fd(MFFloat) },
                { "keyValue", fd(MFVec3f) }
            });

            // OrientationInterpolator
            m_parseInfoMap["OrientationInterpolator"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "key", fd(MFFloat) },
                { "keyValue", fd(MFRotation) }
            });

            // PixelTexture
            m_parseInfoMap["PixelTexture"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "image", fdd(SFImage, new List <uint>()
                    {
                        0, 0, 0
                    }) },
                { "repeatS", fdd(SFBool, true) },
                { "repeatT", fdd(SFBool, true) }
            });

            // PlaneSensor
            m_parseInfoMap["PlaneSensor"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "autoOffset", fdd(SFBool, true) },
                { "enabled", fdd(SFBool, true) },
                { "maxPosition", fdd(SFVec2f, new V2f(-1.0f, -1.0f)) },
                { "minPosition", fdd(SFVec2f, V2f.Zero) },
                { "offset", defaultBBoxCenter }
            });

            // PointLight
            m_parseInfoMap["PointLight"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "ambientIntensity", fdd(SFFloat, 0.0f) },
                { "attenuation", fdd(SFVec3f, new V3f(1.0f, 0.0f, 0.0f)) },
                { "color", fdd(SFColor, C3f.White) },
                { "intensity", fdd(SFFloat, 1.0f) },
                { "location", defaultBBoxCenter },
                { "on", fdd(SFBool, true) },
                { "radius", fdd(SFFloat, 100.0f) }
            });

            // PointSet
            m_parseInfoMap["PointSet"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "color", fd(SFNode) },
                { "coord", fd(SFNode) }
            });

            // PositionInterpolator
            m_parseInfoMap["PositionInterpolator"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "key", fd(MFFloat) },
                { "keyValue", fd(MFVec3f) }
            });

            // ProximitySensor
            m_parseInfoMap["ProximitySensor"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "center", defaultBBoxCenter },
                { "size", defaultBBoxCenter },
                { "enabled", fdd(SFBool, true) }
            });

            // ScalarInterpolator
            m_parseInfoMap["ScalarInterpolator"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "key", fd(MFFloat) },
                { "keyValue", fd(MFFloat) }
            });

            // Script
            // skipped

            // Shape
            m_parseInfoMap["Shape"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "appearance", fd(SFNode) },
                { "geometry", fd(SFNode) },
            });

            // Sound
            m_parseInfoMap["Sound"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "direction", fdd(SFVec3f, new V3f(0.0f, 0.0f, 1.0f)) },
                { "intensity", fdd(SFFloat, 1.0f) },
                { "location", defaultBBoxCenter },
                { "maxBack", fdd(SFFloat, 10.0f) },
                { "maxFront", fdd(SFFloat, 10.0f) },
                { "minBack", fdd(SFFloat, 1.0f) },
                { "minFront", fdd(SFFloat, 1.0f) },
                { "priority", fdd(SFFloat, 0.0f) },
                { "source", fd(SFNode) },
                { "spatialize", fdd(SFBool, true) }
            });

            // Sphere
            m_parseInfoMap["Sphere"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "radius", fdd(SFFloat, 1.0f) }
            });

            // SphereSensor
            m_parseInfoMap["SphereSensor"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "autoOffset", fdd(SFBool, true) },
                { "enabled", fdd(SFBool, true) },
                { "offset", fdd(SFRotation, new V4f(0.0f, 1.0f, 0.0f, 0.0f)) }
            });

            // SpotLight
            m_parseInfoMap["SpotLight"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "ambientIntensity", fdd(SFFloat, 0.0f) },
                { "attenuation", fdd(SFVec3f, new V3f(1.0f, 0.0f, 0.0f)) },
                { "beamWidth", fdd(SFFloat, 1.570796f) },
                { "color", fdd(SFColor, C3f.White) },
                { "cutOffAngle", fdd(SFFloat, 0.785398f) },
                { "direction", fdd(SFVec3f, new V3f(0.0f, 0.0f, -1.0f)) },
                { "intensity", fdd(SFFloat, 1.0f) },
                { "location", defaultBBoxCenter },
                { "on", fdd(SFBool, true) },
                { "radius", fdd(SFFloat, 100.0f) }
            });

            // Switch
            m_parseInfoMap["Switch"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "choice", fd(MFNode) },
                { "whichChoice", fdd(SFInt32, -1) }
            });

            // Text
            m_parseInfoMap["Text"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "string", fd(MFString) },
                { "fontStyle", fd(SFNode) },
                { "length", fd(MFFloat) },
                { "maxExtent", fdd(SFFloat, 0.0f) }
            });

            // TextureCoordinate
            m_parseInfoMap["TextureCoordinate"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "point", fd(MFVec2f) }
            });

            // TextureTransform
            m_parseInfoMap["TextureTransform"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "center", fdd(SFVec2f, V2f.Zero) },
                { "rotation", fdd(SFFloat, 0.0f) },
                { "scale", fdd(SFVec2f, new V2f(1.0f, 1.0f)) },
                { "translation", fdd(SFVec2f, V2f.Zero) }
            });

            // TimeSensor
            m_parseInfoMap["TimeSensor"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "cycleInterval", fdd(SFTime, 1.0f) },
                { "enabled", fdd(SFBool, true) },
                { "loop", fdd(SFBool, false) },
                { "startTime", fdd(SFTime, 0.0f) },
                { "stopTime", fdd(SFTime, 0.0f) }
            });

            // TouchSensor
            m_parseInfoMap["TouchSensor"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "enabled", fdd(SFBool, true) }
            });

            // Transform
            m_parseInfoMap["Transform"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "center", defaultBBoxCenter },
                { "children", fd(MFNode) },
                { "rotation", fdd(SFRotation, new V4f(0.0f, 0.0f, 1.0f, 0.0f)) },
                { "scale", fdd(SFVec3f, new V3f(1.0f, 1.0f, 1.0f)) },
                { "scaleOrientation", fdd(SFRotation, new V4f(0.0f, 0.0f, 1.0f, 0.0f)) },
                { "translation", defaultBBoxCenter },
                { "bboxCenter", defaultBBoxCenter },
                { "bboxSize", defaultBBoxSize }
            });

            // Viewpoint
            m_parseInfoMap["Viewpoint"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "fieldOfView", fdd(SFFloat, 0.785398f) },
                { "jump", fdd(SFBool, true) },
                { "orientation", fdd(SFRotation, new V4f(0.0f, 0.0f, 1.0f, 0.0f)) },
                { "position", fdd(SFVec3f, new V3f(0.0f, 0.0f, 10.0f)) },
                { "description", fd(SFString) }
            });

            // VisibilitySensor
            m_parseInfoMap["VisibilitySensor"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "center", defaultBBoxCenter },
                { "enabled", fdd(SFBool, true) },
                { "size", defaultBBoxCenter }
            });

            // WorldInfo
            m_parseInfoMap["WorldInfo"] = new NodeParseInfo(
                new SymbolDict <Tup <FieldParser, object> >()
            {
                { "title", fd(SFString) },
                { "info", fd(MFString) }
            });
        }
        public static PolyMesh.Grouping Group(
            this IEnumerable <PolyMesh.Face> faces, SymbolDict <object> defaultInstanceValues = null)
        {
            var groups = from face in faces group face by face.Mesh;

            var mc = groups.Count();

            var instanceAttributeArrays   = new SymbolDict <Array>();
            var faceAttributeArrays       = new SymbolDict <PolyMesh.IAttributeArray>();
            var vertexAttributeArrays     = new SymbolDict <PolyMesh.IAttributeArray>();
            var faceVertexAttributeArrays = new SymbolDict <PolyMesh.IAttributeArray>();

            bool matchingInstanceAttributeTypes = true;

            if (defaultInstanceValues == null)
            {
                defaultInstanceValues = PolyMesh.GroupingDefaultInstanceValues;
            }

            var nonMatchingMeshes = new HashSet <PolyMesh>();

            groups.ForEach((mg, mi) =>
            {
                var m = mg.Key;

                foreach (var kvp in m.InstanceAttributes)
                {
                    var type = kvp.Value.GetType();
                    if (!instanceAttributeArrays.TryGetValue(kvp.Key, out Array a))
                    {
                        instanceAttributeArrays[kvp.Key]
                            = a = Array.CreateInstance(type, mc);
                    }
                    if (type != a.GetType().GetElementType())
                    {
                        matchingInstanceAttributeTypes = false;
                        nonMatchingMeshes.Add(m);
                    }
                    a.SetValue(kvp.Value, mi);
                }

                foreach (var a in m.FaceIAttributes)
                {
                    if (!faceAttributeArrays.TryGetValue(a.Name, out PolyMesh.IAttributeArray ca))
                    {
                        faceAttributeArrays[a.Name] = ca =
                            new PolyMesh.IAttributeArray(a.ValueType, mc);
                    }
                    if (ca.Type != a.ValueType)
                    {
                        nonMatchingMeshes.Add(m);
                    }
                    ca.Array[mi] = a; ca.Count++;
                }
                foreach (var a in m.VertexIAttributes)
                {
                    if (!vertexAttributeArrays.TryGetValue(a.Name, out PolyMesh.IAttributeArray ca))
                    {
                        vertexAttributeArrays[a.Name] = ca =
                            new PolyMesh.IAttributeArray(a.ValueType, mc);
                    }
                    if (ca.Type != a.ValueType)
                    {
                        nonMatchingMeshes.Add(m);
                    }
                    ca.Array[mi] = a; ca.Count++;
                }
                foreach (var a in m.FaceVertexIAttributes)
                {
                    if (!faceVertexAttributeArrays.TryGetValue(a.Name, out PolyMesh.IAttributeArray ca))
                    {
                        faceVertexAttributeArrays[a.Name] = ca =
                            new PolyMesh.IAttributeArray(a.ValueType, mc);
                    }
                    if (ca.Type != a.ValueType)
                    {
                        nonMatchingMeshes.Add(m);
                    }
                    ca.Array[mi] = a; ca.Count++;
                }
            });

            groups.ForEach((mg, mi) =>
            {
                var m = mg.Key;
                foreach (var ca in faceAttributeArrays)
                {
                    if (!m.FaceAttributes.Contains(ca.Key))
                    {
                        nonMatchingMeshes.Add(m);
                    }
                }

                foreach (var ca in vertexAttributeArrays)
                {
                    if (!m.VertexAttributes.Contains(ca.Key))
                    {
                        nonMatchingMeshes.Add(m);
                    }
                }

                foreach (var ca in faceVertexAttributeArrays)
                {
                    if (!m.FaceVertexAttributes.Contains(ca.Key))
                    {
                        nonMatchingMeshes.Add(m);
                    }
                }
            });

            bool instanceAsFaceAttributes = true;

            foreach (var kvp in instanceAttributeArrays)
            {
                if (faceAttributeArrays.Contains(kvp.Key))
                {
                    instanceAsFaceAttributes = false;
                }
            }

            return(new PolyMesh.Grouping
            {
                Meshes = from g in groups select g.Key,
                NonMatchingMeshes = nonMatchingMeshes,
                MeshCount = mc,
                MatchingInstanceAttributeTypes = matchingInstanceAttributeTypes,
                InstanceAsFaceAttributes = instanceAsFaceAttributes,
                MatchingFaceAttributes = faceAttributeArrays.Values.All(
                    iaa => iaa.Count == mc && iaa.HasMatchingTypes),
                MatchingVertexAttributes = vertexAttributeArrays.Values.All(
                    iaa => iaa.Count == mc && iaa.HasMatchingTypes),
                MatchingFaceVertexAttributes = faceVertexAttributeArrays.Values.All(
                    iaa => iaa.Count == mc && iaa.HasMatchingTypes),
                Groups = groups,
                InstanceAttributeArrays = instanceAttributeArrays,
                FaceAttributeArrays = faceAttributeArrays,
                VertexAttributeArrays = vertexAttributeArrays,
                FaceVertexAttributeArrays = faceVertexAttributeArrays,
            });
        }
        public static IndexedGeometry GetIndexedGeometry(
            this PolyMesh mesh,
            PolyMesh.GetGeometryOptions options,
            double absoluteEps,
            int[] faceBackMap,
            PolyMesh.IAttribute[] faceAttributes,
            PolyMesh.IAttribute[] vertexAttributes,
            PolyMesh.IAttribute[] faceVertexAttributes,
            SymbolDict <object> instanceAttributes)
        {
            mesh.ComputeVertexBackMaps(faceBackMap,
                                       (options & PolyMesh.GetGeometryOptions.Compact) != 0,
                                       faceAttributes, vertexAttributes, faceVertexAttributes,
                                       out int[] firstIndexArray, out int[] vertexIndexArray,
                                       out int[] vBackMap, out int[] vfBackMap, out int[] vfvBackMap);

            var indexedAttributes = new SymbolDict <Array>();

            var vc = vBackMap.Length;

            if ((options & PolyMesh.GetGeometryOptions.FloatVectorsAndByteColors) != 0)
            {
                var fv = (options & PolyMesh.GetGeometryOptions.FloatVectors) != 0;
                var bc = (options & PolyMesh.GetGeometryOptions.ByteColors) != 0;
                foreach (var a in faceAttributes)
                {
                    var array = a.BackMappedConvertedCopy(vfBackMap, vc, fv, bc);
                    if (array != null)
                    {
                        indexedAttributes[a.Name] = array;
                    }
                }
                foreach (var a in vertexAttributes)
                {
                    var array = a.BackMappedConvertedCopy(vBackMap, vc, fv, bc);
                    if (array != null)
                    {
                        indexedAttributes[a.Name] = array;
                    }
                }
                foreach (var a in faceVertexAttributes)
                {
                    var array = a.BackMappedConvertedCopy(vfvBackMap, vc, fv, bc);
                    if (array != null)
                    {
                        indexedAttributes[a.Name] = array;
                    }
                }
            }
            else
            {
                foreach (var a in vertexAttributes)
                {
                    var array = a.BackMappedCopy(vBackMap, vc);
                    if (array != null)
                    {
                        indexedAttributes[a.Name] = array;
                    }
                }
                foreach (var a in faceAttributes)
                {
                    var array = a.BackMappedCopy(vfBackMap, vc);
                    if (array != null)
                    {
                        indexedAttributes[a.Name] = array;
                    }
                }
                foreach (var a in faceVertexAttributes)
                {
                    var array = a.BackMappedCopy(vfvBackMap, vc);
                    if (array != null)
                    {
                        indexedAttributes[a.Name] = array;
                    }
                }
            }

            var triangleIndices =
                PolyMesh.CreateSimpleTriangleVertexIndexArray(
                    firstIndexArray, vertexIndexArray, faceBackMap.Length,
                    vertexIndexArray.Length, mesh.FaceVertexCountRange);

            var indexArray =
                ((options & PolyMesh.GetGeometryOptions.IntIndices) != 0)
                    ? (Array)triangleIndices : (Array)triangleIndices.Map(i => (short)i);

            return(new IndexedGeometry(indexArray, indexedAttributes, instanceAttributes));
        }