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