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); //} }
public GraphCombiner(NavMeshTemplateRecast template, Graph graph) { this.graph = graph; this.template = template; }
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(); }