Ejemplo n.º 1
0
        public TriangulatorDataSet(
            NavMeshTemplateRecast 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);
            //}
        }
Ejemplo n.º 2
0
 public GraphCombiner(NavMeshTemplateRecast template, Graph graph)
 {
     this.graph    = graph;
     this.template = template;
 }
Ejemplo n.º 3
0
        public void MakeConnections(NavMeshTemplateRecast 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;
                    }
                }
            }
        }
        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);
        }
        //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(NavMeshTemplateRecast template)
        {
            foreach (var dataSet in data)
            {
                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, NavMeshTemplateRecast template)
        {
            this.pos        = pos;
            this.properties = properties;
            this.combiner   = combiner;

            //Debug.Log(chunk == null);
            //Debug.Log(properties == null);


            MakeConnections(template);

#if UNITY_EDITOR
            if (Debuger_K.doDebug && Debuger_K.debugOnlyNavMesh == false)
            {
                DebugDataSets(pos, properties);
            }
#endif

            GenerateCells();
        }