public void Init(NavMeshTemplateCreation template)
        {
            this.template = template;

            int length = flattenSize;

            //!!!!!!!!!!!!!!!!//
            freeIndexStack = GenericPoolArray <int> .Take(INITIAL_FREE_INDEX_POOL_SIZE);

            arrayData = GenericPoolArray <Data> .Take(length *ARRAY_DATA_SIZE);

            for (int i = 0; i < length; i++)
            {
                arrayData[i].next = -2;
            }

            for (int i = length; i < arrayData.Length; i++)
            {
                arrayData[i].next = -1;
            }

            filledIndexes          = length;
            freeIndexStackLength   = 0;
            voxelDistanceThreshold = template.voxelSize;


            freeStackHS.Clear();
        }
        public void GetTreeShapes(NavMeshTemplateCreation template, ref List <ShapeDataAbstract> listToFill)
        {
            var bounds = template.chunkOffsetedBounds;

            int x = template.chunkData.x;
            int z = template.chunkData.z;
            HashSet <TreeInstanceData>   treeInstanceDataHashSet = new HashSet <TreeInstanceData>();
            Predicate <TreeInstanceData> predicate = (TreeInstanceData value) => { return(value.metaDataReference == this && value.bounds.Intersects(bounds)); };

            ChunkContentMap.GetContent(x - 1, z + 1, treeInstanceDataHashSet, predicate);
            ChunkContentMap.GetContent(x - 1, z, treeInstanceDataHashSet, predicate);
            ChunkContentMap.GetContent(x - 1, z + 1, treeInstanceDataHashSet, predicate);
            ChunkContentMap.GetContent(x, z + 1, treeInstanceDataHashSet, predicate);
            ChunkContentMap.GetContent(x, z, treeInstanceDataHashSet, predicate);
            ChunkContentMap.GetContent(x, z + 1, treeInstanceDataHashSet, predicate);
            ChunkContentMap.GetContent(x + 1, z + 1, treeInstanceDataHashSet, predicate);
            ChunkContentMap.GetContent(x + 1, z, treeInstanceDataHashSet, predicate);
            ChunkContentMap.GetContent(x + 1, z + 1, treeInstanceDataHashSet, predicate);

            foreach (var tree in treeInstanceDataHashSet)
            {
                foreach (var shape in tree.shapeData)
                {
                    if ((shape as ShapeDataAbstract).bounds.Intersects(bounds))
                    {
                        listToFill.Add(shape.Clone());
                    }
                }
            }

            //Debug.LogWarning(listToFill.Count);
            //foreach (var item in listToFill) {
            //    Debuger_K.AddBounds(item.bounds, Color.cyan);
            //}
        }
        public TriangulatorDataSet(
            NavMeshTemplateCreation template,
            List <NodeAbstract> nodes, List <EdgeAbstract> edges, Dictionary <NodeAbstract, TriangulatorNodeData> values,
            int layer, Area area, Passability passability)
        {
            this.area        = area;
            this.layer       = layer;
            this.passability = passability;

            Dictionary <NodeAbstract, int> indexes = new Dictionary <NodeAbstract, int>();

            _nodes = new TriangulatorNode[nodes.Count];
            _data  = new TriangulatorNodeData[nodes.Count];

            for (int i = 0; i < nodes.Count; i++)
            {
                _nodes[i] = new TriangulatorNode(nodes[i], i);
                _data[i]  = values[nodes[i]];
                indexes.Add(nodes[i], i);
            }

            edgeMap = new List <TriangulatorEdge> [EDGE_MAP_SIZE * EDGE_MAP_SIZE];
            for (int i = 0; i < EDGE_MAP_SIZE * EDGE_MAP_SIZE; i++)
            {
                edgeMap[i] = new List <TriangulatorEdge>();
            }
            chunkPos         = template.chunkData.realPositionV2;
            edgeMapPiselSize = EDGE_MAP_SIZE / PathFinder.gridSize;

            foreach (var edge in edges)
            {
                AddEdge(indexes[edge.a], indexes[edge.b], 1, false);
            }

            //debug
            //Vector3 realNotOffsetedPosition = template.chunkData.realPositionV3;
            //for (int x = 0; x < EDGE_MAP_SIZE + 1; x++) {
            //    Vector3 A = realNotOffsetedPosition + new Vector3(x * edgeMapPiselSize, 0, 0);
            //    Vector3 B = realNotOffsetedPosition + new Vector3(x * edgeMapPiselSize, 0, PathFinder.gridSize);
            //    Debuger_K.AddLine(A, B, Color.red);
            //}

            //for (int z = 0; z < EDGE_MAP_SIZE + 1; z++) {
            //    Vector3 A = realNotOffsetedPosition + new Vector3(0, 0, z * edgeMapPiselSize);
            //    Vector3 B = realNotOffsetedPosition + new Vector3(PathFinder.gridSize, 0, z * edgeMapPiselSize);
            //    Debuger_K.AddLine(A, B, Color.red);
            //}
        }
        public static ShapeCollector GetFromPool(VectorInt.Vector2Int size, NavMeshTemplateCreation template)
        {
            ShapeCollector result = null;

            lock (poolDictionary) {
                Stack <ShapeCollector> stack;
                if (poolDictionary.TryGetValue(size, out stack) == false)
                {
                    stack = new Stack <ShapeCollector>();
                    poolDictionary.Add(size, stack);

                    for (int i = 0; i < INITIAL_POOL_SIZE; i++)
                    {
                        stack.Push(new ShapeCollector(size));
                    }
                }

                result = stack.Count > 0 ? stack.Pop() : new ShapeCollector(size);
            }

            result.Init(template);
            return(result);
        }
        //first part search for nearest non obstructed node in scope of angle
        //next part search take nodes wich fail first part and search closest to normal angle left and right nodes
        //will probably fail
        private void MakeConnections(NavMeshTemplateCreation template)
        {
            if (profiler != null)
            {
                profiler.AddLogFormat("data sets count {0}", data.Count);
            }
            foreach (var dataSet in data)
            {
                if (profiler != null)
                {
                    profiler.AddLogFormat("current data nodes Length {0}", dataSet.nodes.Length);
                }

                if (dataSet.nodes.Length == 0) //cause it's empty
                {
                    continue;
                }



                dataSet.MakeConnections(template);



                //edges are clockwise right now
                //TEMP STUFF
                //var curNodes = dataSet.nodes;
                //var curEdges = dataSet.edges;

                //int nodesLength = curNodes.Length;
                //bool[] marks = new bool[nodesLength];


                //TriangulatorEdge[] temdStuffEdge = new TriangulatorEdge[curNodes.Length];
                //for (int i = 0; i < curEdges.Count; i++) {
                //    temdStuffEdge[curEdges[i].a] = curEdges[i];
                //}

                ////for (int i = 0; i < dataSet.nodes.Length; i++) {
                ////    Debuger_K.AddLabel(dataSet.NodePosV3(dataSet.nodes[i].id), dataSet.nodes[i].id);
                ////}

                ////foreach (var edge in dataSet.edges) {
                ////    Vector3 a = dataSet.NodePosV3(edge.a);
                ////    Vector3 b = dataSet.NodePosV3(edge.b);
                ////    Debuger_K.AddLabel(SomeMath.MidPoint(a, b), string.Format("{0}, {1}", edge.a, edge.b));
                ////}

                //Debug.Log(nodesLength);
                //int curNode = 1;


                //for (int i = 0; i < 5; i++) {
                //    int nextNode = temdStuffEdge[curNode].b;
                //    Debug.Log(temdStuffEdge[curNode].a + " : " + temdStuffEdge[curNode].b);

                //    Vector2 startPos = curNodes[curNode].positionV2;
                //    Vector2 curDir = curNodes[nextNode].positionV2 - curNodes[curNode].positionV2;

                //    for (int b = 0; b < 5; b++) {
                //        nextNode = temdStuffEdge[nextNode].b;

                //        if(!IsVisible(curNode, nextNode, dataSet)) {
                //            goto NEXT;
                //        }

                //        Vector2 nextPos = curNodes[nextNode].positionV2;
                //        Vector2 nextDir = nextPos - startPos;

                //        float cross = SomeMath.V2Cross(curDir, nextDir);
                //        if(cross <= 0) {
                //            goto NEXT;
                //        }

                //        curDir = nextDir;

                //        Debuger_K.AddLabel(curNodes[nextNode].positionV3, cross);
                //        Debuger_K.AddLine(curNodes[curNode].positionV3, curNodes[nextNode].positionV3, Color.red);
                //    }

                //    NEXT:{
                //        curNode = nextNode;
                //        continue;
                //    }
                //}
                //TEMP STUFF

                //dataSet.GenerateEdgeMap(10, template);
                //dataSet.CreateAngleVisibilityField();

                //TriangulatorNode[] nodes = dataSet.nodes;
                //TriangulatorNodeData[] nodeData = dataSet.data;
                //List<int> nextIterationNodes = new List<int>();

                //for (int curNodeIndex = 0; curNodeIndex < nodes.Length; curNodeIndex++) {
                //    if (nodeData[curNodeIndex].cross >= 0)
                //        continue;

                //    var curVisible = dataSet.AngleVisibilityField(curNodeIndex);

                //    for (int i = 0; i < curVisible.Length; i++) {
                //        if (IsVisible(curNodeIndex, curVisible[i], dataSet)) {
                //            dataSet.AddEdge(curNodeIndex, curVisible[i], 0);
                //            goto NEXT;
                //        }
                //    }

                //    nextIterationNodes.Add(curNodeIndex);
                //    NEXT: { continue; }
                //}

                //List<T2Helper> helpers = new List<T2Helper>();
                //foreach (var nodeIndex in nextIterationNodes) {
                //    Vector2 nodePos = nodes[nodeIndex].positionV2;
                //    Vector2 normal = nodeData[nodeIndex].normal;
                //    float validAngle = 180f - (nodeData[nodeIndex].angle * 0.5f);

                //    helpers.Clear();
                //    foreach (var targetNode in Array.FindAll(nodes, x => Vector2.Angle(normal, x.positionV2 - nodePos) < validAngle)) {
                //        if (nodeIndex == targetNode.id)
                //            continue;

                //        Vector2 targetNodeDirection = (targetNode.positionV2 - nodePos).normalized;
                //        helpers.Add(new T2Helper(targetNode.id, Vector2.Angle(normal, targetNodeDirection) * Mathf.Sign(SomeMath.V2Cross(normal, targetNodeDirection))));
                //    }

                //    helpers.Sort((x, y) => { return (int)Mathf.Sign(Math.Abs(x.angle) - Math.Abs(y.angle)); });

                //    for (int i = 0; i < helpers.Count; i++) {
                //        if (helpers[i].angle < 0 && IsVisible(nodeIndex, helpers[i].node, dataSet)) {
                //            dataSet.AddEdge(nodeIndex, helpers[i].node, 0);
                //            break;
                //        }
                //    }

                //    for (int i = 0; i < helpers.Count; i++) {
                //        if (helpers[i].angle > 0 && IsVisible(nodeIndex, helpers[i].node, dataSet)) {
                //            dataSet.AddEdge(nodeIndex, helpers[i].node, 0);
                //            break;
                //        }
                //    }
                //}
            }
        }
        public void Triangulate(XZPosInt pos, AgentProperties properties, ref GraphCombiner combiner, NavMeshTemplateCreation template)
        {
#if UNITY_EDITOR
            //for debug
            this.pos        = pos;
            this.properties = properties;
#endif

            this.combiner = combiner;

            //Debug.Log(chunk == null);
            //Debug.Log(properties == null);
            if (profiler != null)
            {
                profiler.AddLog("Start make connections");
            }
            MakeConnections(template);
            if (profiler != null)
            {
                profiler.AddLog("End make connections");
            }

#if UNITY_EDITOR
            if (Debuger_K.doDebug && Debuger_K.debugOnlyNavMesh == false)
            {
                DebugDataSets(pos, properties);
            }
#endif
            if (profiler != null)
            {
                profiler.AddLog("Start Generate Cells");
            }
            GenerateCells();
            if (profiler != null)
            {
                profiler.AddLog("End Generate Cells");
            }
        }
        //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);
        }
 public static ShapeCollector GetFromPool(int sizeX, int sizeZ, NavMeshTemplateCreation template)
 {
     return(GetFromPool(new VectorInt.Vector2Int(sizeX, sizeZ), template));
 }
        public static Bounds2DInt GetVolumeBounds(Vector3 spherePos, float sphereRadius, NavMeshTemplateCreation template)
        {
            float   voxelSize   = template.voxelSize;
            Vector3 chunkReal   = template.realOffsetedPosition;
            Vector3 sphereLocal = spherePos - chunkReal;

            return(new Bounds2DInt(
                       Mathf.Max((int)((sphereLocal.x - sphereRadius) / voxelSize), 0),
                       Mathf.Max((int)((sphereLocal.z - sphereRadius) / voxelSize), 0),
                       Mathf.Min((int)((sphereLocal.x + sphereRadius) / voxelSize) + 1, template.lengthX_extra),
                       Mathf.Min((int)((sphereLocal.z + sphereRadius) / voxelSize) + 1, template.lengthZ_extra)));
        }
        public void MakeConnections(NavMeshTemplateCreation template)
        {
            if (nodes.Length == 0)
            {
                return;
            }

            List <int>      nextIterationNodes = new List <int>();
            List <T2Helper> helpers            = new List <T2Helper>();

            //GenerateEdgeMap(10, template);
            CreateAngleVisibilityField();

            for (int curNodeIndex = 0; curNodeIndex < _nodes.Length; curNodeIndex++)
            {
                if (data[curNodeIndex].cross >= 0)
                {
                    continue;
                }

                var curVisible = visibilityField[curNodeIndex];

                for (int i = 0; i < curVisible.Length; i++)
                {
                    if (IsVisible(curNodeIndex, curVisible[i]))
                    {
                        AddEdge(curNodeIndex, curVisible[i], 0);
                        goto NEXT;
                    }
                }

                nextIterationNodes.Add(curNodeIndex);
                NEXT : { continue; }
            }

            foreach (var nodeIndex in nextIterationNodes)
            {
                Vector2 nodePos    = _nodes[nodeIndex].positionV2;
                Vector2 normal     = _data[nodeIndex].normal;
                float   validAngle = 180f - (_data[nodeIndex].angle * 0.5f);

                helpers.Clear();
                foreach (var targetNode in Array.FindAll(_nodes, x => Vector2.Angle(normal, x.positionV2 - nodePos) < validAngle))
                {
                    if (nodeIndex == targetNode.id)
                    {
                        continue;
                    }

                    Vector2 targetNodeDirection = (targetNode.positionV2 - nodePos).normalized;
                    helpers.Add(new T2Helper(targetNode.id, Vector2.Angle(normal, targetNodeDirection) * Mathf.Sign(SomeMath.V2Cross(normal, targetNodeDirection))));
                }

                helpers.Sort((x, y) => { return((int)Mathf.Sign(Math.Abs(x.angle) - Math.Abs(y.angle))); });

                //get first visible node on left
                for (int i = 0; i < helpers.Count; i++)
                {
                    if (helpers[i].angle < 0 && IsVisible(nodeIndex, helpers[i].node))
                    {
                        AddEdge(nodeIndex, helpers[i].node, 0);
                        break;
                    }
                }

                //get first visible node on right
                for (int i = 0; i < helpers.Count; i++)
                {
                    if (helpers[i].angle > 0 && IsVisible(nodeIndex, helpers[i].node))
                    {
                        AddEdge(nodeIndex, helpers[i].node, 0);
                        break;
                    }
                }
            }
        }
Example #11
0
 public GraphCombiner(NavMeshTemplateCreation template, Graph graph)
 {
     this.graph    = graph;
     this.template = template;
     this.profiler = template.profiler;
 }