static float Evaluate(float value, MapRulesSettings mapRulesSettings) { float a = mapRulesSettings.slope; float b = mapRulesSettings.shift; return(Mathf.Pow(value, a) / (Mathf.Pow(value, a) + Mathf.Pow(b - b * value, a))); }
public static float[,] GenerateCornerFalloffMap(int size, MapRulesSettings mapRulesSettings, Corner corner) { float[,] map = new float[size, size]; for (int i = 0; i < size / 2; i++) { for (int j = 0; j < size / 2; j++) { float x = i / (float)size * 2 - 1; float y = j / (float)size * 2 - 1; float value = Mathf.Max(Mathf.Abs(x), Mathf.Abs(y)); map[i, j] = Evaluate(value, mapRulesSettings); } } for (int i = 0; i < size / 2; i++) { for (int j = size / 2; j < size; j++) { float x = i / (float)size * 2 - 1; float value = Mathf.Max(Mathf.Abs(x), 0); map[i, j] = Evaluate(value, mapRulesSettings); } } for (int j = 0; j < size / 2; j++) { for (int i = size / 2; i < size; i++) { float y = j / (float)size * 2 - 1; float value = Mathf.Max(0, Mathf.Abs(y)); map[i, j] = Evaluate(value, mapRulesSettings); } } if (corner == Corner.BOTTOMLEFT) { Utils <float> .rotateMatrix(map); } else if (corner == Corner.BOTTOMRIGHT) { for (int i = 0; i < 2; i++) { Utils <float> .rotateMatrix(map); } } else if (corner == Corner.TOPRIGHT) { for (int i = 0; i < 3; i++) { Utils <float> .rotateMatrix(map); } } return(map); }
public static float[,] GenerateEdgeFalloffMap(int size, MapRulesSettings mapRulesSettings, Edge edge) { float[,] map = new float[size, size]; int maxY; int maxX; int startX; int startY; if (edge == Edge.LEFT) { startX = 0; startY = 0; maxX = size / 2; maxY = size; } else if (edge == Edge.RIGHT) { startX = size / 2; startY = 0; maxX = size; maxY = size; } else if (edge == Edge.BOTTOM) { startX = 0; startY = size / 2; maxX = size; maxY = size; } else { // TOP SETTINGS startX = 0; startY = 0; maxX = size; maxY = size / 2; } bool isVertical = edge == Edge.LEFT || edge == Edge.RIGHT; for (int i = startY; i < maxY; i++) // y { for (int j = startX; j < maxX; j++) // x { float x = i / (float)size * 2 - 1; float y = j / (float)size * 2 - 1; float value = isVertical ? Mathf.Max(0, Mathf.Abs(y)): Mathf.Max(Mathf.Abs(x), 0); map[i, j] = Evaluate(value, mapRulesSettings); } } return(map); }
public TerrainChunk(Vector2 coord, HeightMapSettings heightMapSettings, MeshSettings meshSettings, MapRulesSettings mapRulesSettings, LODInfo[] detailLevels, int colliderLODIndex, Transform parent, Transform viewer, Material material, ResourcePool resourcePool) { this.coord = coord; this.detailLevels = detailLevels; this.colliderLODIndex = colliderLODIndex; this.heightMapSettings = heightMapSettings; this.meshSettings = meshSettings; this.mapRulesSettings = mapRulesSettings; this.resourcePool = resourcePool; this.viewer = viewer; sampleCenter = coord * meshSettings.meshWorldSize / meshSettings.meshScale; Vector2 position = coord * meshSettings.meshWorldSize; bounds = new Bounds(position, Vector2.one * meshSettings.meshWorldSize); meshObject = new GameObject("Terrain Chunk"); meshObject.layer = LayerMask.NameToLayer("Terrain"); meshRenderer = meshObject.AddComponent <MeshRenderer>(); meshFilter = meshObject.AddComponent <MeshFilter>(); meshCollider = meshObject.AddComponent <MeshCollider>(); meshRenderer.material = material; meshObject.transform.position = new Vector3(position.x, 0, position.y); meshObject.transform.parent = parent; SetVisible(false); lodMeshes = new LODMesh[detailLevels.Length]; for (int i = 0; i < detailLevels.Length; i++) { lodMeshes[i] = new LODMesh(detailLevels[i].lod); lodMeshes[i].updateCallback += UpdateTerrainChunk; lodMeshes[i].updateCallback += GenerateResourceNodes; if (i == colliderLODIndex) { lodMeshes[i].updateCallback += UpdateCollisionMesh; } } maxViewDistance = detailLevels[detailLevels.Length - 1].visibleDistanceThreshold; }
public static float[,] GenerateFalloffMap(int size, MapRulesSettings mapRulesSettings) { float[,] map = new float[size, size]; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { float x = i / (float)size * 2 - 1; float y = j / (float)size * 2 - 1; float value = Mathf.Max(Mathf.Abs(x), Mathf.Abs(y)); map[i, j] = Evaluate(value, mapRulesSettings); } } return(map); }
public static HeightMap GenerateHeightMap(int width, int height, HeightMapSettings settings, MapRulesSettings mapRules, Vector2 sampleCenter, ChunkBorderInfo borderInfo) { float[,] values = Noise.GenerateNoiseMap(width, height, settings.noiseSettings, sampleCenter); AnimationCurve heightCurveThreadSafe = new AnimationCurve(settings.heightCurve.keys); float minValue = float.MaxValue; float maxValue = float.MinValue; if (mapRules.useFalloff) { float[,] falloffMap; if (mapRules.useFalloff) { if (mapRules.maxMapSizeInChunks.x <= 1 && mapRules.maxMapSizeInChunks.y <= 1) { falloffMap = FalloffGenerator.GenerateFalloffMap(width, mapRules); } else if (borderInfo.isCorner) { falloffMap = FalloffGenerator.GenerateCornerFalloffMap(width, mapRules, borderInfo.corner); } else if (borderInfo.isEdge) { falloffMap = FalloffGenerator.GenerateEdgeFalloffMap(width, mapRules, borderInfo.edge); } else { falloffMap = new float[width, height]; } } else { falloffMap = new float[width, height]; } for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { values[i, j] = Mathf.Clamp01(values[i, j] - falloffMap[i, j]); values[i, j] *= heightCurveThreadSafe.Evaluate(values[i, j]) * settings.heightMultiplier; if (values[i, j] > maxValue) { maxValue = values[i, j]; } if (values[i, j] < minValue) { minValue = values[i, j]; } } } } else { for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { values[i, j] = Mathf.Clamp01(values[i, j]); values[i, j] *= heightCurveThreadSafe.Evaluate(values[i, j]) * settings.heightMultiplier; if (values[i, j] > maxValue) { maxValue = values[i, j]; } if (values[i, j] < minValue) { minValue = values[i, j]; } } } } return(new HeightMap(values, minValue, maxValue)); }