protected ColliderCollectorTerrainAbstract(NavMeshTemplateRecast template, Collider[] colliders) { this.template = template; foreach (var collider in colliders) { if (IsValid(collider)) { validColliders.Add(collider); } } }
private static void ThreadWorker(object obj) { NavMeshTemplateRecast template = (NavMeshTemplateRecast)obj; try { template.Work(); } catch (Exception e) { if (template.profiler != null) { template.profiler.DebugLog(ProfilderLogMode.warning); } Debug.LogError(e); throw; } }
private static IEnumerator TemplatePopulationLoop() { NavMeshTemplateRecast nm_t = null; while (true) { //if (_disconnectionQueue.Count > 0) // Debug.Log("NavMeshTemplateRecast blocked by _disconnectionQueue.Count > 0"); if (_acceptingWork == false | _activeThreads >= _settings.maxThreads | _disconnectionQueue.Count > 0) { goto next; } lock (_navMeshTemplateQueue) nm_t = _navMeshTemplateQueue.Count > 0 ? _navMeshTemplateQueue.Dequeue() : null; if (nm_t == null) { goto next; } _activeCreationWorks++; nm_t.Populate(); if (multithread) { ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadWorker), nm_t); _activeThreads++; //increasing thread count but it's not really a thread. it's whole operation until connection } else { nm_t.Work(); } //Debug.LogFormat("taken {0}, now active creation is {1}", "NavMeshTemplateRecast", _activeCreationWorks); goto next; next: { yield return(new WaitForEndOfFrame()); continue; } } }
private static void QueueNavMeshTemplateToPopulation(XZPosInt pos, AgentProperties properties) { if (_acceptingWork == false) { return; } //Debug.Log("queue 1 " + pos); NavMeshTemplateRecast template = new NavMeshTemplateRecast(_chunkRange, pos, properties); Action <Graph> callBack = (Graph graph) => { //Debug.Log("callback 1 " + pos); QueueFinishGraphInMainThread(graph); }; template.SetCallBack(callBack); _allTemplatesCreative[new GeneralXZData(pos, properties)] = template; lock (_navMeshTemplateQueue) _navMeshTemplateQueue.Enqueue(template); }
public ColliderCollectorTerrainMeshAbstract(NavMeshTemplateRecast template, Collider[] colliders) : base(template, colliders) { List <Terrain> allTerrains = new List <Terrain>(); for (int i = 0; i < validColliders.Count; i++) { allTerrains.Add(validColliders[i].GetComponent <Terrain>()); } if (template.profiler != null) { template.profiler.AddLog("collecting terrain using fast collector. valid colliders:" + validColliders.Count); } float voxelSize = template.voxelSize; Bounds offsetedBounds = template.chunkOffsetedBounds; Vector3 boundsMin = offsetedBounds.min; Vector3 boundsMax = offsetedBounds.max; float minSize = PathFinder.settings.terrainFastMinimalSize; foreach (var curTerrain in allTerrains) { TerrainColliderInfoMesh info = new TerrainColliderInfoMesh(curTerrain); if (template.profiler != null) { template.profiler.AddLog("start collecting tree bounds"); } info.treeData = GenerateTreeBounds(curTerrain); if (template.profiler != null) { template.profiler.AddLog("end collecting tree bounds. collected bounds: " + info.treeData.Count); } TerrainData data = curTerrain.terrainData; Vector3 position = curTerrain.transform.position; Vector3 scale = data.size; //height map int resolution = 1; int heightMapSizeX = data.heightmapWidth; int heightMapSizeZ = data.heightmapHeight; float hScaleX = scale.x / (heightMapSizeX - 1); float hScaleZ = scale.z / (heightMapSizeZ - 1); for (int i = 0; i < 4; i++) { if (minSize > hScaleX * resolution) { resolution = (int)Mathf.Pow(2, i); } else { break; } } int hTargetMinX = Mathf.Clamp(((Mathf.RoundToInt((boundsMin.x - position.x) / hScaleX) / resolution) - 1) * resolution, 0, heightMapSizeX); int hTargetMinZ = Mathf.Clamp(((Mathf.RoundToInt((boundsMin.z - position.z) / hScaleZ) / resolution) - 1) * resolution, 0, heightMapSizeX); int hTargetMaxX = Mathf.Clamp(((Mathf.RoundToInt((boundsMax.x - position.x) / hScaleX) / resolution) + 1) * resolution + 1, 0, heightMapSizeX); int hTargetMaxZ = Mathf.Clamp(((Mathf.RoundToInt((boundsMax.z - position.z) / hScaleZ) / resolution) + 1) * resolution + 1, 0, heightMapSizeX); int hSizeX = hTargetMaxX - hTargetMinX; int hSizeZ = hTargetMaxZ - hTargetMinZ; int hTargetSizeX = hSizeX / resolution + 1; int hTargetSizeZ = hSizeZ / resolution + 1; if (resolution == 1) { hTargetSizeX = hSizeX; hTargetSizeZ = hSizeZ; } info.heightMap = data.GetHeights(hTargetMinX, hTargetMinZ, hSizeX, hSizeZ); info.heightMatrix = Matrix4x4.TRS( position + new Vector3(hScaleX * hTargetMinX, 0, hScaleZ * hTargetMinZ), Quaternion.identity, new Vector3(hScaleX * resolution, scale.y, hScaleZ * resolution)); info.hSizeX = hTargetSizeX; info.hSizeZ = hTargetSizeZ; info.resolution = resolution; //rest VectorInt.Vector3Int terrainStartInt = new VectorInt.Vector3Int((position / voxelSize) + template.halfFragmentOffset); VectorInt.Vector3Int terrainEndInt = new VectorInt.Vector3Int((position + data.size) / voxelSize + template.halfFragmentOffset); int startXClamp = Mathf.Clamp(terrainStartInt.x, template.startX_extra, template.endX_extra); int startZClamp = Mathf.Clamp(terrainStartInt.z, template.startZ_extra, template.endZ_extra); int endXClamp = Mathf.Clamp(terrainEndInt.x, template.startX_extra, template.endX_extra); int endZClamp = Mathf.Clamp(terrainEndInt.z, template.startZ_extra, template.endZ_extra); int terrainStartX = terrainStartInt.x; int terrainStartZ = terrainStartInt.z; float terrainSizeX = terrainEndInt.x - terrainStartX; float terrainSizeZ = terrainEndInt.z - terrainStartZ; SetTerrainSettings(info, curTerrain, startXClamp, startZClamp, endXClamp, endZClamp, terrainStartX, terrainStartZ, terrainSizeX, terrainSizeZ, position); terrainsInfo.Add(info); } }
protected ColliderCollectorPrimitivesAbstract(NavMeshTemplateRecast template, Collider[] colliders) : base(template, colliders) { GenerateTemplates(); }
//main thread public ColliderCollectorTerrainUnityWay(NavMeshTemplateRecast template, Collider[] colliders) : base(template, colliders) { var allTerrains = (from collider in validColliders select collider.GetComponent <Terrain>()); float fragmentSize = template.voxelSize; float halfFragment = fragmentSize * 0.5f; foreach (var curTerrain in allTerrains) { TerrainData data = curTerrain.terrainData; Vector3 position = curTerrain.transform.position; VectorInt.Vector3Int terrainStartInt = new VectorInt.Vector3Int((position / fragmentSize) + template.halfFragmentOffset); VectorInt.Vector3Int terrainEndInt = new VectorInt.Vector3Int((position + data.size) / fragmentSize + template.halfFragmentOffset); int startXClamp = Mathf.Clamp(terrainStartInt.x, template.startX_extra, template.endX_extra); int startZClamp = Mathf.Clamp(terrainStartInt.z, template.startZ_extra, template.endZ_extra); int endXClamp = Mathf.Clamp(terrainEndInt.x, template.startX_extra, template.endX_extra); int endZClamp = Mathf.Clamp(terrainEndInt.z, template.startZ_extra, template.endZ_extra); int terrainStartX = terrainStartInt.x; int terrainStartZ = terrainStartInt.z; int offset = terrainStartInt.y; float terrainSizeX = terrainEndInt.x - terrainStartX; float terrainSizeZ = terrainEndInt.z - terrainStartZ; float[][] heightMap = new float[template.lengthX_extra][]; int[][] passabilityMap = new int[template.lengthX_extra][]; //angle map for (int x = 0; x < template.lengthX_extra; x++) { heightMap[x] = new float[template.lengthZ_extra]; passabilityMap[x] = new int[template.lengthZ_extra]; } //some cashed values int startX_extra = template.startX_extra; int startZ_extra = template.startZ_extra; float maxSlope = template.maxSlope; //lets do bazzilion times Terrain.SampleHeight and TerrainData.GetSteepness! //it cant be done in thread cause terrain API is "threadsafe"! //actualy it can be done. but in order to do this we need to recreate this part of terrain mesh in thread but no. i dont want to do this. no. //maybe later for (int x = startXClamp; x < endXClamp; x++) { for (int z = startZClamp; z < endZClamp; z++) { heightMap[x - startX_extra][z - startZ_extra] = curTerrain.SampleHeight(new Vector3(x * fragmentSize + halfFragment, 0, z * fragmentSize + halfFragment)) + offset; passabilityMap[x - startX_extra][z - startZ_extra] = data.GetSteepness((x - terrainStartX) / terrainSizeX, (z - terrainStartZ) / terrainSizeZ) < maxSlope ? (int)Passability.Walkable : (int)Passability.Slope; } } TerrainColliderInfoPrecise info = new TerrainColliderInfoPrecise(curTerrain, heightMap, passabilityMap); if (template.profiler != null) { template.profiler.AddLog("start collecting tree bounds"); } info.treeData = GenerateTreeBounds(curTerrain); if (template.profiler != null) { template.profiler.AddLog("end collecting tree bounds. collected bounds: " + info.treeData.Count); } SetTerrainSettings(info, curTerrain, startXClamp, startZClamp, endXClamp, endZClamp, terrainStartX, terrainStartZ, terrainSizeX, terrainSizeZ, position); _terrainsInfo.Add(info); } }
//construtor are called in main thread but execute Collect(FragmentContainer) in own thread public ColliderCollectorPrimitivesCPU(NavMeshTemplateRecast template, Collider[] colliders) : base(template, colliders) { }
public ColliderCollectorTerrainComputeShader(NavMeshTemplateRecast template, Collider[] colliders) : base(template, colliders) { }
public TerrainCollectorAbstract(NavMeshTemplateRecast template, Collider[] colliders) : base(template, colliders) { }