public static void WeldSurroundingDraftsToThisMain(TerrainTileManager tileManager, Coord coord) /// Welds neig draft terrains to this one when switched on main, lowering draft edges /// Called in main thread on switch lods /// On drafts only because of the performance reasons { if (tileManager == null) { return; } TerrainTile thisTile = tileManager[coord]; for (int d = 0; d < weldDirections.Length; d++) { TerrainTile neigTile = tileManager[coord + weldDirections[d]]; if (neigTile?.draft == null) { continue; } if (!neigTile.draft.applyReady || !neigTile.draft.generateReady) { continue; //TODO: test this } if (neigTile.ActiveTerrain == neigTile.draft.terrain) { if (neigTile.draft.edges.lowered[-weldDirections[d]]) { continue; } WeldDraftToMain(thisTile, neigTile, weldDirections[d]); neigTile.draft.edges.lowered[-weldDirections[d]] = true; } } }
public static void WeldEdgesInThread(EdgesSet thisEdges, TerrainTileManager tileManager, Coord coord, bool isDraft = false) /// Welds edges (does not affect data) { if (tileManager == null) { return; } for (int d = 0; d < weldDirections.Length; d++) { TerrainTile neigTile = tileManager[coord + weldDirections[d]]; if (neigTile == null || (isDraft && neigTile.draft == null) || (isDraft && !neigTile.draft.generateReady) || (!isDraft && neigTile.main == null) || (!isDraft && !neigTile.main.generateReady)) { continue; } //if null or not generate-ready EdgesSet neigEdges = isDraft ? neigTile.draft?.edges : neigTile.main?.edges; if (neigEdges == null || !neigEdges.ready) { continue; } //height if (neigEdges.heightEdges != null && neigEdges.heightEdges.SizeX == thisEdges.heightEdges.SizeX) { Weld.WeldEdges(neigEdges.heightEdges, neigTile.coord, thisEdges.heightEdges, coord); } //splats if (neigEdges.splatEdges != null && thisEdges.splatEdges != null && thisEdges.splatEdges.Length == neigEdges.splatEdges.Length) { for (int i = 0; i < thisEdges.splatEdges.Length; i++) { if (thisEdges.splatEdges[i].SizeX == neigEdges.splatEdges[i].SizeX) { Weld.WeldEdges(neigEdges.splatEdges[i], neigTile.coord, thisEdges.splatEdges[i], coord); } } } //textures if (neigEdges.controlEdges != null && thisEdges.controlEdges != null && thisEdges.controlEdges.Length == neigEdges.controlEdges.Length) { for (int i = 0; i < thisEdges.controlEdges.Length; i++) { if (thisEdges.controlEdges[i].SizeX == neigEdges.controlEdges[i].SizeX) { Weld.WeldEdges(neigEdges.controlEdges[i], neigTile.coord, thisEdges.controlEdges[i], coord); } } } } }
public static void WeldCorners(TerrainTileManager tileManager, Coord coord, bool isDraft = false) /// Iterates all terrain at the corner and chooses the first occurrence value. { if (tileManager == null) { return; } TerrainTile thisTile = tileManager[coord]; Terrain thisTerrain = isDraft ? thisTile.draft?.terrain : thisTile.main?.terrain; TerrainData thisData = thisTerrain.terrainData; if (thisTerrain == null) { return; } int resolution = thisTerrain.terrainData.heightmapResolution; float[,] tempArr = new float[1, 1]; for (int c = 0; c < cornerDirections.Length; c++) { Coord corner = (cornerDirections[c] + 1) / 2; //float thisHeight = thisData.GetHeight((corner.x+1)/2, (corner.z+1)/2); //reading and selecting maximum for (int d = 0; d < cornerDirections.Length; d++) { Coord dir = (cornerDirections[d] + 1) / 2; TerrainTile cornerTile = tileManager[coord + dir + corner - 1]; if (cornerTile == null || cornerTile == thisTile) { continue; } Terrain cornerTerrain = isDraft ? cornerTile.draft?.terrain : cornerTile.main?.terrain; if (cornerTerrain == null || !cornerTerrain.isActiveAndEnabled) { continue; } TerrainData cornerData = cornerTerrain.terrainData; float cornerHeight = cornerData.GetHeight((1 - dir.x) * (resolution - 1), (1 - dir.z) * (resolution - 1)) / cornerData.size.y; tempArr[0, 0] = cornerHeight; thisData.SetHeightsDelayLOD(corner.x * (resolution - 1), corner.z * (resolution - 1), tempArr); break; } } }
//It all should work, but Unity calls Terrain.SetConnectivityDirty on each terrain enable or disable public static void SetNeighbors(TerrainTileManager tileManager, Coord coord) { if (tileManager == null) { return; } TerrainTile thisTile = tileManager[coord]; //foreach (TerrainTile tile in tileManager.Tiles()) TerrainTile tile = tileManager[coord]; coord = tile.coord; { Terrain terrain = tile.main?.terrain; //isDraft ? tile.draft?.terrain : tile.main?.terrain; //if (terrain == null || !terrain.isActiveAndEnabled) continue; //for (int d=0; d<weldDirections.Length; d++) //unroll Terrain leftNeighbor = tileManager[new Coord(coord.x - 1, coord.z)]?.main?.terrain; if (leftNeighbor != null && leftNeighbor.isActiveAndEnabled) { terrain.SetNeighbors(leftNeighbor, terrain.topNeighbor, terrain.rightNeighbor, terrain.bottomNeighbor); leftNeighbor.SetNeighbors(leftNeighbor.leftNeighbor, leftNeighbor.topNeighbor, terrain, leftNeighbor.bottomNeighbor); } Terrain rightNeighbor = tileManager[new Coord(coord.x + 1, coord.z)]?.main?.terrain; if (rightNeighbor != null && rightNeighbor.isActiveAndEnabled) { terrain.SetNeighbors(terrain.leftNeighbor, terrain.topNeighbor, rightNeighbor, terrain.bottomNeighbor); rightNeighbor.SetNeighbors(terrain, rightNeighbor.topNeighbor, rightNeighbor.rightNeighbor, rightNeighbor.bottomNeighbor); } Terrain bottomNeighbor = tileManager[new Coord(coord.x, coord.z - 1)]?.main?.terrain; if (bottomNeighbor != null && bottomNeighbor.isActiveAndEnabled) { terrain.SetNeighbors(terrain.leftNeighbor, terrain.topNeighbor, terrain.rightNeighbor, bottomNeighbor); bottomNeighbor.SetNeighbors(bottomNeighbor.leftNeighbor, terrain, bottomNeighbor.rightNeighbor, bottomNeighbor.bottomNeighbor); } Terrain topNeighbor = tileManager[new Coord(coord.x, coord.z + 1)]?.main?.terrain; if (topNeighbor != null && topNeighbor.isActiveAndEnabled) { terrain.SetNeighbors(terrain.leftNeighbor, topNeighbor, terrain.rightNeighbor, terrain.bottomNeighbor); topNeighbor.SetNeighbors(topNeighbor.leftNeighbor, topNeighbor.topNeighbor, topNeighbor.rightNeighbor, terrain); } } }
public static void WeldThisDraftWithSurroundings(TerrainTileManager tileManager, Coord coord) /// Welds this tile to tiles around it on switch to draft, lowering if surround is main or restoring weld if draft /// This will restore edges in surrounding drafts too { if (tileManager == null) { return; } TerrainTile thisTile = tileManager[coord]; for (int d = 0; d < weldDirections.Length; d++) { Coord dir = weldDirections[d]; TerrainTile neigTile = tileManager[coord + weldDirections[d]]; if (neigTile == null) { continue; } //restoring edges if (neigTile.draft != null && neigTile.ActiveTerrain == neigTile.draft.terrain) { if (neigTile.draft.edges.lowered[-dir]) { RestoreDraftWeld(neigTile, -dir); neigTile.draft.edges.lowered[-dir] = false; } if (thisTile.draft.edges.lowered[dir]) { RestoreDraftWeld(thisTile, dir); thisTile.draft.edges.lowered[dir] = false; } } //lowering this edges else if (neigTile.main != null && neigTile.ActiveTerrain == neigTile.main.terrain) { if (thisTile.draft.edges.lowered[dir]) { continue; } WeldDraftToMain(neigTile, thisTile, -dir); thisTile.draft.edges.lowered[dir] = true; } } }
public static void SetNeighborsAll(TerrainTileManager tileManager) { System.Diagnostics.Stopwatch timer = null; timer = new System.Diagnostics.Stopwatch(); timer.Start(); if (tileManager == null) { return; } //TerrainTile thisTile = tileManager[coord]; foreach (TerrainTile tile in tileManager.Tiles()) { SetNeighbors(tileManager, tile.coord); } timer.Stop(); Debug.Log("Neighboring in " + timer.Elapsed.TotalMilliseconds + "ms" + " (" + timer.ElapsedMilliseconds + ")"); }