//public GraphTriangulator(GraphGenerator generator, NavMeshTemplateCreation template) {
        //    var volumes = generator.getVolumes;
        //    var nodes = generator.getNodes;

        //    //layer, hash
        //    Dictionary<int, Dictionary<int, List<NodeAbstract>>> dicNodes = new Dictionary<int, Dictionary<int, List<NodeAbstract>>>();
        //    Dictionary<int, Dictionary<int, List<EdgeAbstract>>> dicEdges = new Dictionary<int, Dictionary<int, List<EdgeAbstract>>>();
        //    Dictionary<int, Dictionary<int, Dictionary<NodeAbstract, TriangulatorNodeData>>> dicValues = new Dictionary<int, Dictionary<int, Dictionary<NodeAbstract, TriangulatorNodeData>>>();

        //    foreach (var volume in volumes) {
        //        dicNodes.Add(volume.id, new Dictionary<int, List<NodeAbstract>>());
        //        dicEdges.Add(volume.id, new Dictionary<int, List<EdgeAbstract>>());
        //        dicValues.Add(volume.id, new Dictionary<int, Dictionary<NodeAbstract, TriangulatorNodeData>>());

        //        //some hardcoded stuff
        //        foreach (var a in volume.containsAreas) {
        //            int crouchHash = PathFinder.GetAreaHash(a, Passability.Crouchable);
        //            int walkHash = PathFinder.GetAreaHash(a, Passability.Walkable);

        //            dicNodes[volume.id].Add(crouchHash, new List<NodeAbstract>());
        //            dicEdges[volume.id].Add(crouchHash, new List<EdgeAbstract>());
        //            dicValues[volume.id].Add(crouchHash, new Dictionary<NodeAbstract, TriangulatorNodeData>());

        //            dicNodes[volume.id].Add(walkHash, new List<NodeAbstract>());
        //            dicEdges[volume.id].Add(walkHash, new List<EdgeAbstract>());
        //            dicValues[volume.id].Add(walkHash, new Dictionary<NodeAbstract, TriangulatorNodeData>());
        //        }
        //    }

        //    foreach (var first in nodes) {
        //        foreach (var pair in first.getData) {
        //            int volume = pair.Key.x;
        //            int hash = pair.Key.y;

        //            dicNodes[volume][hash].Add(first);
        //            dicEdges[volume][hash].Add(first[volume, hash]);

        //            NodeTemp middle = first.GetNode(volume, hash);
        //            NodeTemp last = middle.GetNode(volume, hash);

        //            float cross = SomeMath.V2Cross(
        //                last.x - middle.x, last.z - middle.z,
        //                first.x - middle.x, first.z - middle.z);

        //            if (cross < 0) {
        //                Vector2 directionLast = new Vector2(last.x - middle.x, last.z - middle.z).normalized;
        //                Vector2 directionFirst = new Vector2(first.x - middle.x, first.z - middle.z).normalized;
        //                dicValues[volume][hash].Add(middle, new TriangulatorNodeData(cross, Vector2.Angle(directionLast, directionFirst), (directionLast + directionFirst).normalized * -1));
        //            }
        //            else
        //                dicValues[volume][hash].Add(middle, new TriangulatorNodeData(cross, 0, Vector2.zero));
        //        }
        //    }

        //    foreach (var volume in volumes) {
        //        foreach (var a in volume.containsAreas) {
        //            int crouchHash = PathFinder.GetAreaHash(a, Passability.Crouchable);
        //            data.Add(new TriangulatorDataSet(
        //                template,
        //                dicNodes[volume.id][crouchHash],
        //                dicEdges[volume.id][crouchHash],
        //                dicValues[volume.id][crouchHash],
        //                volume.id, a, Passability.Crouchable));


        //            int walkHash = PathFinder.GetAreaHash(a, Passability.Walkable);
        //            data.Add(new TriangulatorDataSet(
        //                template,
        //                dicNodes[volume.id][walkHash],
        //                dicEdges[volume.id][walkHash],
        //                dicValues[volume.id][walkHash],
        //                volume.id, a, Passability.Walkable));
        //        }
        //    }

        //    //data.RemoveAll(x => x.nodes.Count == 0);
        //}

        public GraphTriangulator(GraphGeneratorNew generator, NavMeshTemplateCreation template)
        {
            int maxLayers = generator.volumeContainer.layersCount;

            //var volumes = generator.dataLayers;
            var nodes = generator.getNodes;

            //DataLayer[] dataLayers = generator.dataLayers;
            //int dataLayersLength = dataLayers.Length;

            profiler = template.profiler;



            //layer, hash
            Dictionary <int, List <NodeAbstract> >[] dicNodes = new Dictionary <int, List <NodeAbstract> > [maxLayers];
            Dictionary <int, List <EdgeAbstract> >[] dicEdges = new Dictionary <int, List <EdgeAbstract> > [maxLayers];
            Dictionary <int, Dictionary <NodeAbstract, TriangulatorNodeData> >[] dicValues = new Dictionary <int, Dictionary <NodeAbstract, TriangulatorNodeData> > [maxLayers];

            for (int id = 0; id < maxLayers; id++)
            {
                dicNodes[id]  = new Dictionary <int, List <NodeAbstract> >();
                dicEdges[id]  = new Dictionary <int, List <EdgeAbstract> >();
                dicValues[id] = new Dictionary <int, Dictionary <NodeAbstract, TriangulatorNodeData> >();

                //DataLayer layer = dataLayers[id];

                //some hardcoded stuff
                //foreach (var hash in layer.allAreaHashes) {
                //    dicNodes[id].Add(hash, new List<NodeAbstract>());
                //    dicEdges[id].Add(hash, new List<EdgeAbstract>());
                //    dicValues[id].Add(hash, new Dictionary<NodeAbstract, TriangulatorNodeData>());
                //}
            }
            if (profiler != null)
            {
                profiler.AddLog("start preparing data in GraphTriangulator");
            }
            foreach (var first in nodes)
            {
                foreach (var pair in first.getData)
                {
                    int layer = pair.Key.x;
                    int hash  = pair.Key.y;

                    var curDicNodes  = dicNodes[layer];
                    var curDicEdges  = dicEdges[layer];
                    var curDicValues = dicValues[layer];


                    if (curDicNodes.ContainsKey(hash) == false)
                    {
                        curDicNodes.Add(hash, new List <NodeAbstract>());
                        curDicEdges.Add(hash, new List <EdgeAbstract>());
                        curDicValues.Add(hash, new Dictionary <NodeAbstract, TriangulatorNodeData>());
                    }

                    curDicNodes[hash].Add(first);
                    curDicEdges[hash].Add(first[layer, hash]);

                    NodeTemp middle = first.GetNode(layer, hash);
                    NodeTemp last   = middle.GetNode(layer, hash);

                    float cross = SomeMath.V2Cross(
                        last.x - middle.x, last.z - middle.z,
                        first.x - middle.x, first.z - middle.z);

                    if (cross < 0)
                    {
                        Vector2 directionLast  = new Vector2(last.x - middle.x, last.z - middle.z).normalized;
                        Vector2 directionFirst = new Vector2(first.x - middle.x, first.z - middle.z).normalized;
                        curDicValues[hash].Add(middle, new TriangulatorNodeData(cross, Vector2.Angle(directionLast, directionFirst), (directionLast + directionFirst).normalized * -1));
                    }
                    else
                    {
                        curDicValues[hash].Add(middle, new TriangulatorNodeData(cross, 0, Vector2.zero));
                    }
                }
            }


            for (int id = 0; id < maxLayers; id++)
            {
                foreach (var hash in dicNodes[id].Keys)
                {
                    Area        area;
                    Passability pass;
                    template.hashData.GetAreaByHash((short)hash, out area, out pass);

                    data.Add(new TriangulatorDataSet(
                                 template,
                                 dicNodes[id][hash],
                                 dicEdges[id][hash],
                                 dicValues[id][hash],
                                 id, area, pass));
                }
            }
            if (profiler != null)
            {
                profiler.AddLog("end preparing data in GraphTriangulator");
            }
            //data.RemoveAll(x => x.nodes.Count == 0);
        }
        XZPosInt pos;//for debug

        public GraphTriangulator(GraphGenerator generator, NavMeshTemplateRecast template)
        {
            var volumes = generator.getVolumes;
            var nodes   = generator.getNodes;

            //layer, hash
            Dictionary <int, Dictionary <int, List <NodeAbstract> > > dicNodes = new Dictionary <int, Dictionary <int, List <NodeAbstract> > >();
            Dictionary <int, Dictionary <int, List <EdgeAbstract> > > dicEdges = new Dictionary <int, Dictionary <int, List <EdgeAbstract> > >();
            Dictionary <int, Dictionary <int, Dictionary <NodeAbstract, TriangulatorNodeData> > > dicValues = new Dictionary <int, Dictionary <int, Dictionary <NodeAbstract, TriangulatorNodeData> > >();

            foreach (var volume in volumes)
            {
                dicNodes.Add(volume.id, new Dictionary <int, List <NodeAbstract> >());
                dicEdges.Add(volume.id, new Dictionary <int, List <EdgeAbstract> >());
                dicValues.Add(volume.id, new Dictionary <int, Dictionary <NodeAbstract, TriangulatorNodeData> >());

                //some hardcoded stuff
                foreach (var a in volume.containsAreas)
                {
                    int crouchHash = PathFinder.GetAreaHash(a, Passability.Crouchable);
                    int walkHash   = PathFinder.GetAreaHash(a, Passability.Walkable);

                    dicNodes[volume.id].Add(crouchHash, new List <NodeAbstract>());
                    dicEdges[volume.id].Add(crouchHash, new List <EdgeAbstract>());
                    dicValues[volume.id].Add(crouchHash, new Dictionary <NodeAbstract, TriangulatorNodeData>());

                    dicNodes[volume.id].Add(walkHash, new List <NodeAbstract>());
                    dicEdges[volume.id].Add(walkHash, new List <EdgeAbstract>());
                    dicValues[volume.id].Add(walkHash, new Dictionary <NodeAbstract, TriangulatorNodeData>());
                }
            }

            foreach (var first in nodes)
            {
                foreach (var pair in first.getData)
                {
                    int volume = pair.Key.x;
                    int hash   = pair.Key.y;

                    dicNodes[volume][hash].Add(first);
                    dicEdges[volume][hash].Add(first[volume, hash]);

                    NodeTemp middle = first.GetNode(volume, hash);
                    NodeTemp last   = middle.GetNode(volume, hash);

                    float cross = SomeMath.V2Cross(
                        last.x - middle.x, last.z - middle.z,
                        first.x - middle.x, first.z - middle.z);

                    if (cross < 0)
                    {
                        Vector2 directionLast  = new Vector2(last.x - middle.x, last.z - middle.z).normalized;
                        Vector2 directionFirst = new Vector2(first.x - middle.x, first.z - middle.z).normalized;
                        dicValues[volume][hash].Add(middle, new TriangulatorNodeData(cross, Vector2.Angle(directionLast, directionFirst), (directionLast + directionFirst).normalized * -1));
                    }
                    else
                    {
                        dicValues[volume][hash].Add(middle, new TriangulatorNodeData(cross, 0, Vector2.zero));
                    }
                }
            }

            foreach (var volume in volumes)
            {
                foreach (var a in volume.containsAreas)
                {
                    int crouchHash = PathFinder.GetAreaHash(a, Passability.Crouchable);
                    data.Add(new TriangulatorDataSet(
                                 template,
                                 dicNodes[volume.id][crouchHash],
                                 dicEdges[volume.id][crouchHash],
                                 dicValues[volume.id][crouchHash],
                                 volume.id, a, Passability.Crouchable));


                    int walkHash = PathFinder.GetAreaHash(a, Passability.Walkable);
                    data.Add(new TriangulatorDataSet(
                                 template,
                                 dicNodes[volume.id][walkHash],
                                 dicEdges[volume.id][walkHash],
                                 dicValues[volume.id][walkHash],
                                 volume.id, a, Passability.Walkable));
                }
            }

            //data.RemoveAll(x => x.nodes.Count == 0);
        }