public Dictionary <int, TerrainWeldUvs> Process(WeldRegenerationOrder order) { int biggerTerrainIndex = order.GetBiggerTerrainIndex(); var biggerTerrain = order.GetTerrainOfIndex(biggerTerrainIndex); var biggerTerrainId = biggerTerrain.Terrain.WeldingInputTerrainId; TerrainSide biggerTerrainSide = new TerrainSide() { SideType = biggerTerrain.SideType, TerrainId = biggerTerrainId }; var outWeldModificationsDict = new Dictionary <int, TerrainWeldUvs>(); if (!_terrainSideToStripPositions.ContainsKey(biggerTerrainSide)) { var registrationResult = _level2Manager.RegisterStrip(CreateStripSide(biggerTerrain, new Vector2(0, 1))); outWeldModificationsDict[biggerTerrainId] = registrationResult.WeldUvs; _terrainSideToStripPositions[biggerTerrainSide] = registrationResult.StripPosition; } var weldPosition = _terrainSideToStripPositions[biggerTerrainSide]; var smallerTerrain = order.GetTerrainOfIndex(1 - biggerTerrainIndex); var smallerSide = new TerrainSide() { SideType = smallerTerrain.SideType, TerrainId = smallerTerrain.Terrain.WeldingInputTerrainId }; _followerStripPositions[smallerSide] = weldPosition; var followerSide = CreateStripSide(smallerTerrain, CalculateFollowerMarginUv(biggerTerrain, smallerTerrain)); var followerWeldUv = _level2Manager.AddStipSegment(weldPosition, followerSide); outWeldModificationsDict[smallerTerrain.Terrain.WeldingInputTerrainId] = followerWeldUv; return(outWeldModificationsDict); }
// TODO SIMPLIFY CODE private void BuildTerrainMesh(TerrainSide side) { int index = (int)side; Mesh mesh = _meshFilters[index].sharedMesh; Vector3[] vertices; int[] triangles; int triIndex = 0; int i; switch (side) { case TerrainSide.Top: vertices = new Vector3[resolution * resolution]; triangles = new int[(resolution - 1) * (resolution - 1) * 6]; for (int y = 0; y < resolution; y++) { for (int x = 0; x < resolution; x++) { i = x + y * resolution; Vector2 percent = new Vector2(x, y) / (resolution - 1); Vector3 point = new Vector3((percent.x - .5f) * TerrainGrid.Width, 0f, -(percent.y - .5f) * TerrainGrid.Height); point.y = CalculateHeight(point); vertices[i] = point; if (x != resolution - 1 && y != resolution - 1) { triangles[triIndex] = i; triangles[triIndex + 1] = i + resolution + 1; triangles[triIndex + 2] = i + resolution; triangles[triIndex + 3] = i; triangles[triIndex + 4] = i + 1; triangles[triIndex + 5] = i + resolution + 1; triIndex += 6; } } } break; case TerrainSide.Bottom: vertices = new Vector3[resolution * resolution]; triangles = new int[(resolution - 1) * (resolution - 1) * 6]; for (int y = 0; y < resolution; y++) { for (int x = 0; x < resolution; x++) { i = x + y * resolution; Vector2 percent = new Vector2(x, y) / (resolution - 1); Vector3 point = new Vector3((percent.x - .5f) * TerrainGrid.Width, -1f, -(percent.y - .5f) * TerrainGrid.Height); vertices[i] = point; if (x != resolution - 1 && y != resolution - 1) { triangles[triIndex] = i + resolution; triangles[triIndex + 1] = i + resolution + 1; triangles[triIndex + 2] = i; triangles[triIndex + 3] = i + resolution + 1; triangles[triIndex + 4] = i + 1; triangles[triIndex + 5] = i; triIndex += 6; } } } break; default: vertices = new Vector3[resolution * 2]; triangles = new int[(resolution - 1) * 6]; float semiWidth = terrainOptions.width / 2f; float semiHeight = terrainOptions.height / 2f; i = 0; switch (side) { case TerrainSide.Back: for (int x = 0; x < resolution; x++) { for (int y = -1; y <= 0; y++) { float scaledX = (x / (resolution - 1f) - 0.5f) * TerrainGrid.Width; vertices[i] = new Vector3(scaledX, y, semiWidth); if (vertices[i].y > -1f) { vertices[i].y = CalculateHeight(vertices[i]); } if (x != resolution - 1 && y != 0) { triangles[triIndex] = i; triangles[triIndex + 1] = i + 2; triangles[triIndex + 2] = i + 1; triangles[triIndex + 3] = i + 1; triangles[triIndex + 4] = i + 2; triangles[triIndex + 5] = i + 3; triIndex += 6; } i++; } } break; case TerrainSide.Front: for (int x = 0; x < resolution; x++) { for (int y = -1; y <= 0; y++) { float scaledX = (x / (resolution - 1f) - 0.5f) * TerrainGrid.Width; vertices[i] = new Vector3(scaledX, y, -semiWidth); if (vertices[i].y > -1f) { vertices[i].y = CalculateHeight(vertices[i]); } if (x != resolution - 1 && y != 0) { triangles[triIndex] = i; triangles[triIndex + 1] = i + 1; triangles[triIndex + 2] = i + 2; triangles[triIndex + 3] = i + 1; triangles[triIndex + 4] = i + 3; triangles[triIndex + 5] = i + 2; triIndex += 6; } i++; } } break; case TerrainSide.Left: for (int z = 0; z < resolution; z++) { for (int y = -1; y <= 0; y++) { float scaledZ = (z / (resolution - 1f) - 0.5f) * TerrainGrid.Height; vertices[i] = new Vector3(-semiHeight, y, scaledZ); if (vertices[i].y > -1f) { vertices[i].y = CalculateHeight(vertices[i]); } if (y != 0 && z != resolution - 1) { triangles[triIndex] = i; triangles[triIndex + 1] = i + 2; triangles[triIndex + 2] = i + 1; triangles[triIndex + 3] = i + 1; triangles[triIndex + 4] = i + 2; triangles[triIndex + 5] = i + 3; triIndex += 6; } i++; } } break; case TerrainSide.Right: for (int z = 0; z < resolution; z++) { for (int y = -1; y <= 0; y++) { float scaledZ = (z / (resolution - 1f) - 0.5f) * TerrainGrid.Height; vertices[i] = new Vector3(semiHeight, y, scaledZ); if (vertices[i].y > -1f) { vertices[i].y = CalculateHeight(vertices[i]); } if (y != 0 && z != resolution - 1) { triangles[triIndex] = i; triangles[triIndex + 1] = i + 1; triangles[triIndex + 2] = i + 2; triangles[triIndex + 3] = i + 1; triangles[triIndex + 4] = i + 3; triangles[triIndex + 5] = i + 2; triIndex += 6; } i++; } } break; } int verticesCount = vertices.Length; for (i = 0; i < verticesCount; i++) { if (vertices[i].y > 0.01f) { vertices[i].y = CalculateHeight(vertices[i]); } } break; } mesh.Clear(); mesh.vertices = vertices; mesh.triangles = triangles; mesh.RecalculateNormals(); }
public override void Serialize(BinaryWriter w, MapItem item) { var t = item as Terrain; w.Write(t.Uid); WriteKdopBounds(w, t); byte kflag1 = 0; kflag1 |= (byte)(t.WaterReflection.ToByte() << 7); kflag1 |= (byte)(t.Right.VegetationCollision.ToByte() << 6); kflag1 |= (byte)((byte)t.StepSize << 4); kflag1 |= (byte)((byte)t.Right.Terrain.Transition << 2); kflag1 |= (byte)t.Right.Terrain.Noise; w.Write(kflag1); byte kflag2 = 0; kflag2 |= (byte)(t.IgnoreCutPlanes.ToByte() << 6); kflag2 |= (byte)(t.LowPolyVegetation.ToByte() << 5); kflag2 |= (byte)(t.StretchTerrain.ToByte() << 4); kflag2 |= (byte)((!t.Right.DetailVegetation).ToByte() << 3); kflag2 |= (byte)((!t.Boundary).ToByte() << 2); kflag2 |= (byte)((!t.Collision).ToByte() << 1); kflag2 |= t.Railings.InvertRailing.ToByte(); w.Write(kflag2); byte kflag3 = 0; kflag3 |= (byte)(t.SmoothDetailVegetation.ToByte() << 2); kflag3 |= (!t.TerrainShadows).ToByte(); w.Write(kflag3); byte kflag4 = 0; kflag4 |= (byte)(t.Left.VegetationCollision.ToByte() << 5); kflag4 |= (byte)((!t.Left.DetailVegetation).ToByte() << 4); kflag4 |= (byte)((byte)t.Left.Terrain.Transition << 2); kflag4 |= (byte)t.Left.Terrain.Noise; w.Write(kflag4); w.Write((byte)(t.ViewDistance / distFactor)); w.Write(t.Node.Uid); w.Write(t.ForwardNode.Uid); w.Write(t.NodeOffset); w.Write(t.ForwardNodeOffset); w.Write(t.Length); w.Write(t.RandomSeed); foreach (var railing in t.Railings.Models) { w.Write(railing.Model); w.Write((short)(railing.Offset * modelOffsetFactor)); } TerrainSide bwRight = null; TerrainSide bwLeft = null; if (t.BackwardItem is Terrain bwTerrain) { bwRight = bwTerrain.Right; bwLeft = bwTerrain.Left; } WriteThatTerrainAndVegetationPart(t.Right, bwRight); WriteThatTerrainAndVegetationPart(t.Left, bwLeft); WriteObjectList(w, t.VegetationSpheres); t.Right.Terrain.QuadData.Serialize(w); t.Left.Terrain.QuadData.Serialize(w); w.Write(t.Right.Edge); w.Write(t.Right.EdgeLook); w.Write(t.Left.Edge); w.Write(t.Left.EdgeLook); void WriteThatTerrainAndVegetationPart(TerrainSide side, TerrainSide bwTerrainSide) { w.Write((ushort)(side.Terrain.Size * terrainSizeFactor)); w.Write(side.Terrain.Profile); w.Write(side.Terrain.Coefficient); if (bwTerrainSide is null) { // prev profile w.Write(0UL); // prev coef w.Write(0f); } else { // prev profile w.Write(bwTerrainSide.Terrain.Profile); // prev coef w.Write(bwTerrainSide.Terrain.Coefficient); } foreach (var veg in side.Vegetation) { veg.Serialize(w); } w.Write((ushort)(side.NoDetailVegetationFrom * noDetVegFromToFactor)); w.Write((ushort)(side.NoDetailVegetationTo * noDetVegFromToFactor)); } }
private static void StitchTerrains(Terrain terrain, Terrain second, TerrainSide side, bool smooth = true) { TerrainData terrainData = terrain.terrainData; TerrainData secondData = second.terrainData; float[,] heights = terrainData.GetHeights(0, 0, terrainData.heightmapWidth, terrainData.heightmapHeight); float[,] secondHeights = secondData.GetHeights(0, 0, secondData.heightmapWidth, secondData.heightmapHeight); if (side == TerrainSide.Right) { int y = heights.GetLength(0) - 1; int x = 0; int y2 = 0; for (x = 0; x < heights.GetLength(1); x++) { heights[x, y] = average(heights[x, y], secondHeights[x, y2]); if (smooth) { heights[x, y] += Mathf.Abs(heights[x, y - 1] - secondHeights[x, y2 + 1]) / Smoothlevel; } secondHeights[x, y2] = heights[x, y]; for (int i = 1; i < StitcheLength; i++) { heights[x, y - i] = (average(heights[x, y - i], heights[x, y - i + 1]) + Mathf.Abs(heights[x, y - i] - heights[x, y - i + 1]) / Smoothlevel) * (StitcheLength - i) / StitcheLength + heights[x, y - i] * i / StitcheLength; secondHeights[x, y2 + i] = (average(secondHeights[x, y2 + i], secondHeights[x, y2 + i - 1]) + Mathf.Abs(secondHeights[x, y2 + i] - secondHeights[x, y2 + i - 1]) / Smoothlevel) * (StitcheLength - i) / StitcheLength + secondHeights[x, y2 + i] * i / StitcheLength; } } } else { if (side == TerrainSide.Top) { int y = 0; int x = heights.GetLength(0) - 1; int x2 = 0; for (y = 0; y < heights.GetLength(1); y++) { heights[x, y] = average(heights[x, y], secondHeights[x2, y]); if (smooth) { heights[x, y] += Mathf.Abs(heights[x - 1, y] - secondHeights[x2 + 1, y]) / Smoothlevel; } secondHeights[x2, y] = heights[x, y]; for (int i = 1; i < StitcheLength; i++) { heights[x - i, y] = (average(heights[x - i, y], heights[x - i + 1, y]) + Mathf.Abs(heights[x - i, y] - heights[x - i + 1, y]) / Smoothlevel) * (StitcheLength - i) / StitcheLength + heights[x - i, y] * i / StitcheLength; secondHeights[x2 + i, y] = (average(secondHeights[x2 + i, y], secondHeights[x2 + i - 1, y]) + Mathf.Abs(secondHeights[x2 + i, y] - secondHeights[x2 + i - 1, y]) / Smoothlevel) * (StitcheLength - i) / StitcheLength + secondHeights[x2 + i, y] * i / StitcheLength; } } } } terrainData.SetHeights(0, 0, heights); terrain.terrainData = terrainData; secondData.SetHeights(0, 0, secondHeights); second.terrainData = secondData; terrain.Flush(); second.Flush(); }
protected bool Equals(TerrainSide other) { return(TerrainId == other.TerrainId && SideType == other.SideType); }