protected override void Init() { seaLevelAlignedWithInt = (waterLevel / (float)maxHeight); beachLevelAlignedWithInt = (waterLevel + 1f) / maxHeight; if (steps != null) { for (int k = 0; k < steps.Length; k++) { if (steps [k].noiseTexture != null) { bool repeated = false; for (int j = 0; j < k - 1; j++) { if (steps [k].noiseTexture == steps [k].noiseTexture) { steps [k].noiseValues = steps [j].noiseValues; steps [k].noiseTextureSize = steps [j].noiseTextureSize; repeated = true; break; } } if (!repeated && (steps [k].noiseTextureSize == 0 || steps [k].noiseValues == null || steps [k].lastTextureLoaded == null || steps [k].noiseTexture != steps [k].lastTextureLoaded)) { steps [k].lastTextureLoaded = steps [k].noiseTexture; steps [k].noiseValues = NoiseTools.LoadNoiseTexture(steps [k].noiseTexture, out steps [k].noiseTextureSize); } } // Validate references if (steps [k].inputIndex0 < 0 || steps [k].inputIndex0 >= steps.Length) { steps [k].inputIndex0 = 0; } if (steps [k].inputIndex1 < 0 || steps [k].inputIndex1 >= steps.Length) { steps [k].inputIndex1 = 0; } } } if (moisture != null && (noiseMoistureTextureSize == 0 || moistureValues == null || lastMoistureTextureLoaded == null || lastMoistureTextureLoaded != moisture)) { lastMoistureTextureLoaded = moisture; moistureValues = NoiseTools.LoadNoiseTexture(moisture, out noiseMoistureTextureSize); } if (waterVoxel == null) { waterVoxel = Resources.Load <VoxelDefinition> ("VoxelPlay/Defaults/Water/VoxelWaterSea"); } paintShore = shoreVoxel != null; if (heightChunkData == null) { heightChunkData = new HeightMapInfo[16 * 16]; } // Ensure voxels are available env.AddVoxelDefinition(shoreVoxel); env.AddVoxelDefinition(waterVoxel); env.AddVoxelDefinition(bedrockVoxel); }
void GeneratePerlinNoise(ref float minValue, ref float maxValue) { Vector2[] pows = new Vector2[octaves]; for (int k = 0; k < pows.Length; k++) { pows [k].x = Mathf.Max(1f, Mathf.Pow(lacunarity, (k + 1))); pows [k].y = Mathf.Pow(persistance, k); } float offsetValue = offset * size; for (int index = 0, y = 0; y < size; y++) { float yf = (float)y / size; for (int x = 0; x < size; x++) { float xf = (float)x / size; float v = 1f; for (int o = 0; o < octaves; o++) { int frequency = (int)pows [o].x; float amplitude = pows [o].y; float xx = xf * frequency + offsetValue; float yy = yf * frequency + offsetValue; float ov = NoiseTools.GetTilablePerlinValue(xx, yy, frequency, frequency) + 0.5f; v += amplitude * ov; } values [index++] = v; if (v < minValue) { minValue = v; } if (v > maxValue) { maxValue = v; } } } }
/// <summary> /// Gets the altitude and moisture (in 0-1 range). /// </summary> /// <param name="x">The x coordinate.</param> /// <param name="z">The z coordinate.</param> /// <param name="altitude">Altitude.</param> /// <param name="moisture">Moisture.</param> public override void GetHeightAndMoisture(float x, float z, out float altitude, out float moisture) { if (!isInitialized) { Initialize(); } bool allowBeach = true; altitude = 0; if (steps != null && steps.Length > 0) { float value = 0; for (int k = 0; k < steps.Length; k++) { if (steps [k].enabled) { switch (steps [k].operation) { case TerrainStepType.SampleHeightMapTexture: value = NoiseTools.GetNoiseValueBilinear(steps [k].noiseValues, steps [k].noiseTextureSize, x * steps [k].frecuency, z * steps [k].frecuency); value = value * (steps [k].noiseRangeMax - steps [k].noiseRangeMin) + steps [k].noiseRangeMin; break; case TerrainStepType.SampleRidgeNoiseFromTexture: value = NoiseTools.GetNoiseValueBilinear(steps [k].noiseValues, steps [k].noiseTextureSize, x * steps [k].frecuency, z * steps [k].frecuency, true); value = value * (steps [k].noiseRangeMax - steps [k].noiseRangeMin) + steps [k].noiseRangeMin; break; case TerrainStepType.Shift: value += steps [k].param; break; case TerrainStepType.BeachMask: { int i1 = steps [k].inputIndex0; if (steps [i1].value > steps [k].threshold) { allowBeach = false; } } break; case TerrainStepType.AddAndMultiply: value = (value + steps [k].param) * steps [k].param2; break; case TerrainStepType.MultiplyAndAdd: value = (value * steps [k].param) + steps [k].param2; break; case TerrainStepType.Exponential: if (value < 0) { value = 0; } value = (float)System.Math.Pow(value, steps [k].param); break; case TerrainStepType.Constant: value = steps [k].param; break; case TerrainStepType.Invert: value = 1f - value; break; case TerrainStepType.Copy: { int i1 = steps [k].inputIndex0; value = steps [i1].value; } break; case TerrainStepType.Random: value = WorldRand.GetValue(x, z); break; case TerrainStepType.BlendAdditive: { int i1 = steps [k].inputIndex0; int i2 = steps [k].inputIndex1; value = steps [i1].value * steps [k].weight0 + steps [i2].value * steps [k].weight1; } break; case TerrainStepType.BlendMultiply: { int i1 = steps [k].inputIndex0; int i2 = steps [k].inputIndex1; value = steps [i1].value * steps [i2].value; } break; case TerrainStepType.Threshold: { int i1 = steps [k].inputIndex0; if (steps [i1].value >= steps [k].threshold) { value = steps [i1].value + steps [k].thresholdShift; } else { value = steps [k].thresholdParam; } } break; case TerrainStepType.FlattenOrRaise: if (value >= steps [k].threshold) { value = (value - steps [k].threshold) * steps [k].thresholdParam + steps [k].threshold; } break; case TerrainStepType.Clamp: if (value < steps [k].min) { value = steps [k].min; } else if (value > steps [k].max) { value = steps [k].max; } break; case TerrainStepType.Select: { int i1 = steps [k].inputIndex0; if (steps [i1].value < steps [k].min) { value = steps [k].thresholdParam; } else if (steps [i1].value > steps [k].max) { value = steps [k].thresholdParam; } else { value = steps [i1].value; } } break; case TerrainStepType.Fill: { int i1 = steps [k].inputIndex0; if (steps [i1].value >= steps [k].min && steps [i1].value <= steps [k].max) { value = steps [k].thresholdParam; } } break; case TerrainStepType.Test: { int i1 = steps [k].inputIndex0; if (steps [i1].value >= steps [k].min && steps [i1].value <= steps [k].max) { value = 1f; } else { value = 0f; } } break; } } steps [k].value = value; } altitude = value; } else { altitude = -9999; // no terrain so make altitude very low so every chunk be considered above terrain for GI purposes } // Moisture moisture = NoiseTools.GetNoiseValueBilinear(moistureValues, noiseMoistureTextureSize, x * moistureScale, z * moistureScale); // Remove any potential beach if (altitude < beachLevelAlignedWithInt && altitude >= seaLevelAlignedWithInt) { float depth = beachLevelAlignedWithInt - altitude; if (depth > beachWidth || !allowBeach) { altitude = seaLevelAlignedWithInt - 0.0001f; } } // Adjusts sea depth if (altitude < seaLevelAlignedWithInt) { float depth = seaLevelAlignedWithInt - altitude; altitude = seaLevelAlignedWithInt - 0.0001f - depth * seaDepthMultiplier; } }