public void InitCloudTiles(int viewDistance) { // 1 cloud tile = 30 blocks // Min amount of cloud tiles = 5*5 // Also we'll display clouds triple as far as block view distance CloudTileLength = GameMath.Clamp(viewDistance / CloudTileSize, 20, 200); QuantityCloudTiles = CloudTileLength * CloudTileLength; Tiles = new CloudTile[QuantityCloudTiles]; tempTiles = new CloudTile[QuantityCloudTiles]; int seed = rand.Next(); for (int x = 0; x < CloudTileLength; x++) { for (int z = 0; z < CloudTileLength; z++) { Tiles[x * CloudTileLength + z] = new CloudTile() { GridXOffset = (short)(x - CloudTileLength / 2), GridZOffset = (short)(z - CloudTileLength / 2), brightnessRand = new LCGRandom(seed) }; } } }
void UpdateBufferContents(MeshData mesh) { int pos = 0; for (int i = 0; i < Tiles.Length; i++) { CloudTile tile = Tiles[i]; mesh.CustomShorts.Values[pos++] = (short)(CloudTileSize * tile.GridXOffset); mesh.CustomShorts.Values[pos++] = (short)(CloudTileSize * tile.GridZOffset); mesh.CustomShorts.Values[pos++] = tile.NorthThickness; mesh.CustomShorts.Values[pos++] = tile.EastThickness; mesh.CustomShorts.Values[pos++] = tile.SouthThickness; mesh.CustomShorts.Values[pos++] = tile.WestThickness; mesh.CustomShorts.Values[pos++] = tile.SelfThickness; mesh.CustomShorts.Values[pos++] = tile.Brightness; mesh.CustomShorts.Values[pos++] = tile.ThinCloudMode; mesh.CustomShorts.Values[pos++] = tile.UndulatingCloudMode; mesh.CustomShorts.Values[pos++] = tile.CloudOpaqueness; mesh.CustomShorts.Values[pos++] = 0; // nothing } }
public void InitCloudTiles(int viewDistance) { // 1 cloud tile = 30 blocks // Min amount of cloud tiles = 5*5 // Also we'll display clouds triple as far as block view distance CloudTileLength = Math.Max(20, viewDistance / CloudTileSize); QuantityCloudTiles = CloudTileLength * CloudTileLength; cloudTiles = new CloudTile[QuantityCloudTiles]; cloudTilesTmp = new CloudTile[QuantityCloudTiles]; int i = 0; for (int x = 0; x < CloudTileLength; x++) { for (int z = 0; z < CloudTileLength; z++) { cloudTiles[i++] = new CloudTile() { XOffset = x, ZOffset = z }; } } }
public void UpdateCloudTiles() { weatherSim.EnsureNoiseCacheIsFresh(); byte zero = 0; int end = CloudTileLength - 2; // Load density from perlin noise for (int dx = 0; dx < CloudTileLength; dx++) { for (int dz = 0; dz < CloudTileLength; dz++) { int x = (tilePosX + dx - CloudTileLength / 2 - tileOffsetX); int z = (tilePosZ + dz - CloudTileLength / 2 - tileOffsetZ); brightnessRand.InitPositionSeed(x, z); double density = weatherSim.GetBlendedCloudDensityAt(dx, dz); CloudTile cloudTile = cloudTiles[dx * CloudTileLength + dz]; cloudTile.MaxDensity = (byte)GameMath.Clamp((int)((64 * 255 * density * 3)) / 64, 0, 255); cloudTile.Brightness = (byte)(235 + brightnessRand.NextInt(21)); cloudTile.YOffset = (float)weatherSim.GetBlendedCloudOffsetYAt(dx, dz); } } // Has to be done after all densities have updated for (int dx = 0; dx < CloudTileLength; dx++) { for (int dz = 0; dz < CloudTileLength; dz++) { CloudTile cloud = cloudTiles[dx * CloudTileLength + dz]; byte northDensity = dz < 1 ? zero : cloudTiles[dx * CloudTileLength + dz - 1].MaxDensity; byte southDensity = dz >= end ? zero : cloudTiles[dx * CloudTileLength + dz + 1].MaxDensity; byte eastDensity = dx >= end ? zero : cloudTiles[(dx + 1) * CloudTileLength + dz].MaxDensity; byte westDensity = dx < 1 ? zero : cloudTiles[(dx - 1) * CloudTileLength + dz].MaxDensity; int changeVal = northDensity == 0 || cloud.MaxDensity - northDensity > 5 ? 1 : -1; cloud.NorthFaceDensity = (byte)GameMath.Clamp((cloud.NorthFaceDensity + changeVal), 0, cloud.MaxDensity); changeVal = eastDensity == 0 || cloud.MaxDensity - eastDensity > 5 ? 1 : -1; cloud.EastFaceDensity = (byte)GameMath.Clamp((cloud.EastFaceDensity + changeVal), 0, cloud.MaxDensity); changeVal = southDensity == 0 || cloud.MaxDensity - southDensity > 5 ? 1 : -1; cloud.SouthFaceDensity = (byte)GameMath.Clamp((cloud.SouthFaceDensity + changeVal), 0, cloud.MaxDensity); changeVal = westDensity == 0 || cloud.MaxDensity - westDensity > 5 ? 1 : -1; cloud.WestFaceDensity = (byte)GameMath.Clamp((cloud.WestFaceDensity + changeVal), 0, cloud.MaxDensity); cloud.UpDownDensity += (byte)GameMath.Clamp(cloud.MaxDensity - cloud.UpDownDensity, -1, 1); } } }
public void MoveCloudTilesOffThread(int dx, int dz) { // We have to "physically" move the cloud tiles so that we can smoothly blend tile.SelfThickness for (int x = 0; x < CloudTileLength; x++) { for (int z = 0; z < CloudTileLength; z++) { int newX = GameMath.Mod(x + dx, CloudTileLength); int newZ = GameMath.Mod(z + dz, CloudTileLength); CloudTile tile = Tiles[x * CloudTileLength + z]; tile.GridXOffset = (short)(newX - CloudTileLength / 2); tile.GridZOffset = (short)(newZ - CloudTileLength / 2); tempTiles[newX * CloudTileLength + newZ] = tile; } } var flip = Tiles; Tiles = tempTiles; tempTiles = flip; }
public void MoveCloudTiles(int dx, int dz) { CloudTile deftile = new CloudTile(); for (int x = 0; x < CloudTileLength; x++) { for (int z = 0; z < CloudTileLength; z++) { int newX = GameMath.Mod(x + dx, CloudTileLength); int newZ = GameMath.Mod(z + dz, CloudTileLength); CloudTile tile = cloudTiles[x * CloudTileLength + z]; tile.XOffset = newX; tile.ZOffset = newZ; cloudTilesTmp[newX * CloudTileLength + newZ] = tile; } } CloudTile[] tmp = cloudTiles; cloudTiles = cloudTilesTmp; cloudTilesTmp = tmp; }
void UpdateBufferContents(MeshData mesh) { //int floatsPosition = 0; int intsPosition = 0; int bytesPosition = 0; for (int i = 0; i < cloudTiles.Length; i++) { CloudTile cloud = cloudTiles[i]; mesh.CustomInts.Values[intsPosition++] = (cloud.XOffset - CloudTileLength / 2); mesh.CustomInts.Values[intsPosition++] = (cloud.ZOffset - CloudTileLength / 2); mesh.CustomBytes.Values[bytesPosition++] = cloud.NorthFaceDensity; mesh.CustomBytes.Values[bytesPosition++] = cloud.EastFaceDensity; mesh.CustomBytes.Values[bytesPosition++] = cloud.SouthFaceDensity; mesh.CustomBytes.Values[bytesPosition++] = cloud.WestFaceDensity; mesh.CustomBytes.Values[bytesPosition++] = cloud.UpDownDensity; mesh.CustomBytes.Values[bytesPosition++] = cloud.Brightness; bytesPosition += 2; } }
public void UpdateCloudTilesOffThread(int changeSpeed) { // Load density from perlin noise int cnt = CloudTileLength * CloudTileLength; int prevTopLeftRegX = -9999; int prevTopLeftRegZ = -9999; Vec3i tileOffset = new Vec3i(offThreadState.TileOffsetX - offThreadState.WindTileOffsetX, 0, offThreadState.TileOffsetZ - offThreadState.WindTileOffsetZ); Vec3i tileCenterPos = offThreadState.CenterTilePos; for (int i = 0; i < cnt; i++) { CloudTile cloudTile = Tiles[i]; int tileXPos = tileCenterPos.X + cloudTile.GridXOffset; int tileZPos = tileCenterPos.Z + cloudTile.GridZOffset; cloudTile.brightnessRand.InitPositionSeed(tileXPos - offThreadState.WindTileOffsetX, tileZPos - offThreadState.WindTileOffsetZ); // This is a block position Vec3d cloudTilePos = new Vec3d(tileXPos * CloudTileSize, 0, tileZPos * CloudTileSize); int regSize = capi.World.BlockAccessor.RegionSize; int topLeftRegX = (int)Math.Round(cloudTilePos.X / regSize) - 1; int topLeftRegZ = (int)Math.Round(cloudTilePos.Z / regSize) - 1; if (topLeftRegX != prevTopLeftRegX || topLeftRegZ != prevTopLeftRegZ) { prevTopLeftRegX = topLeftRegX; prevTopLeftRegZ = topLeftRegZ; weatherSys.LoadAdjacentSimsAndLerpValues(cloudTilePos); weatherSys.EnsureCloudTileCacheIsFresh(tileOffset); } else { weatherSys.loadLerp(cloudTilePos); } // This is the tile position relative to the current regions origin point int cloudTileX = (int)cloudTilePos.X / CloudTileSize; int cloudTileZ = (int)cloudTilePos.Z / CloudTileSize; // Here we need the cloud tile position relative to cloud tile pos 0/0 of the current region double density = GameMath.Clamp(weatherSys.GetBlendedCloudThicknessAt(cloudTileX, cloudTileZ), 0, 1); double bright = weatherSys.GetBlendedCloudBrightness(1) * (0.85f + cloudTile.brightnessRand.NextFloat() * 0.15f); cloudTile.TargetBrightnes = (short)(GameMath.Clamp(bright, 0, 1) * short.MaxValue); cloudTile.TargetThickness = (short)GameMath.Clamp(density * short.MaxValue, 0, short.MaxValue); cloudTile.TargetThinCloudMode = (short)GameMath.Clamp(weatherSys.GetBlendedThinCloudModeness() * short.MaxValue, 0, short.MaxValue); cloudTile.TargetCloudOpaquenes = (short)GameMath.Clamp(weatherSys.GetBlendedCloudOpaqueness() * short.MaxValue, 0, short.MaxValue); cloudTile.TargetUndulatingCloudMode = (short)GameMath.Clamp(weatherSys.GetBlendedUndulatingCloudModeness() * short.MaxValue, 0, short.MaxValue); cloudTile.Brightness = LerpTileValue(cloudTile.TargetBrightnes, cloudTile.Brightness, changeSpeed); cloudTile.SelfThickness = LerpTileValue(cloudTile.TargetThickness, cloudTile.SelfThickness, changeSpeed); cloudTile.ThinCloudMode = LerpTileValue(cloudTile.TargetThinCloudMode, cloudTile.ThinCloudMode, changeSpeed); cloudTile.CloudOpaqueness = LerpTileValue(cloudTile.TargetCloudOpaquenes, cloudTile.CloudOpaqueness, changeSpeed); cloudTile.UndulatingCloudMode = LerpTileValue(cloudTile.TargetUndulatingCloudMode, cloudTile.UndulatingCloudMode, changeSpeed); // North: Negative Z // South: Positive Z if (i > 0) { Tiles[i - 1].NorthThickness = cloudTile.SelfThickness; } if (i < Tiles.Length - 1) { Tiles[i + 1].SouthThickness = cloudTile.SelfThickness; } // East: Positive X // West: Negative X if (i < CloudTileLength - 1) { Tiles[i + CloudTileLength].EastThickness = cloudTile.SelfThickness; } if (i > CloudTileLength - 1) { Tiles[i - CloudTileLength].WestThickness = cloudTile.SelfThickness; } } }
public void UpdateCloudTilesOffThread(int changeSpeed) { bool reloadRainNoiseValues = false; accum++; if (accum > 10) { accum = 0; reloadRainNoiseValues = true; } // Load density from perlin noise int cnt = CloudTileLength * CloudTileLength; int prevTopLeftRegX = -9999; int prevTopLeftRegZ = -9999; Vec3i tileOffset = new Vec3i(offThreadState.TileOffsetX - offThreadState.WindTileOffsetX, 0, offThreadState.TileOffsetZ - offThreadState.WindTileOffsetZ); Vec3i tileCenterPos = offThreadState.CenterTilePos; for (int i = 0; i < cnt; i++) { CloudTile cloudTile = Tiles[i]; int tileXPos = tileCenterPos.X + cloudTile.GridXOffset; int tileZPos = tileCenterPos.Z + cloudTile.GridZOffset; /*if (cloudTile.GridXOffset == 0 && cloudTile.GridZOffset == 0 && reloadRainNoiseValues) * { * int a = 1; * }*/ cloudTile.brightnessRand.InitPositionSeed(tileXPos - offThreadState.WindTileOffsetX, tileZPos - offThreadState.WindTileOffsetZ); // This is a block position Vec3d cloudTilePos = new Vec3d(tileXPos * CloudTileSize, capi.World.SeaLevel, tileZPos * CloudTileSize); int regSize = capi.World.BlockAccessor.RegionSize; int topLeftRegX = (int)Math.Round(cloudTilePos.X / regSize) - 1; int topLeftRegZ = (int)Math.Round(cloudTilePos.Z / regSize) - 1; if (topLeftRegX != prevTopLeftRegX || topLeftRegZ != prevTopLeftRegZ) { prevTopLeftRegX = topLeftRegX; prevTopLeftRegZ = topLeftRegZ; wreaderpreload.LoadAdjacentSims(cloudTilePos); wreaderpreload.EnsureCloudTileCacheIsFresh(tileOffset); } // Noise generation (from the precipitation and temperature subsystems) is expensive, lets do it less often. // Since the clouds have smooth transition anyways, it should not be noticable at all if (reloadRainNoiseValues || !cloudTile.rainValuesSet) { wreaderpreload.LoadLerp(cloudTilePos); cloudTile.lerpRainCloudOverlay = wreaderpreload.lerpRainCloudOverlay; cloudTile.lerpRainOverlay = wreaderpreload.lerpRainOverlay; cloudTile.rainValuesSet = true; } else { wreaderpreload.LoadLerp(cloudTilePos, true, cloudTile.lerpRainCloudOverlay, cloudTile.lerpRainOverlay); } // This is the tile position relative to the current regions origin point int cloudTileX = (int)cloudTilePos.X / CloudTileSize; int cloudTileZ = (int)cloudTilePos.Z / CloudTileSize; // Here we need the cloud tile position relative to cloud tile pos 0/0 of the current region double density = GameMath.Clamp(wreaderpreload.GetBlendedCloudThicknessAt(cloudTileX, cloudTileZ), 0, 1); double bright = wreaderpreload.GetBlendedCloudBrightness(1) * (0.85f + cloudTile.brightnessRand.NextFloat() * 0.15f); cloudTile.TargetBrightnes = (short)(GameMath.Clamp(bright, 0, 1) * short.MaxValue); cloudTile.TargetThickness = (short)GameMath.Clamp(density * short.MaxValue, 0, short.MaxValue); cloudTile.TargetThinCloudMode = (short)GameMath.Clamp(wreaderpreload.GetBlendedThinCloudModeness() * short.MaxValue, 0, short.MaxValue); cloudTile.TargetCloudOpaquenes = (short)GameMath.Clamp(wreaderpreload.GetBlendedCloudOpaqueness() * short.MaxValue, 0, short.MaxValue); cloudTile.TargetUndulatingCloudMode = (short)GameMath.Clamp(wreaderpreload.GetBlendedUndulatingCloudModeness() * short.MaxValue, 0, short.MaxValue); cloudTile.Brightness = LerpTileValue(cloudTile.TargetBrightnes, cloudTile.Brightness, changeSpeed); cloudTile.SelfThickness = LerpTileValue(cloudTile.TargetThickness, cloudTile.SelfThickness, changeSpeed); cloudTile.ThinCloudMode = LerpTileValue(cloudTile.TargetThinCloudMode, cloudTile.ThinCloudMode, changeSpeed); cloudTile.CloudOpaqueness = LerpTileValue(cloudTile.TargetCloudOpaquenes, cloudTile.CloudOpaqueness, changeSpeed); cloudTile.UndulatingCloudMode = LerpTileValue(cloudTile.TargetUndulatingCloudMode, cloudTile.UndulatingCloudMode, changeSpeed); /*cloudTile.Brightness = 0; * cloudTile.SelfThickness = short.MaxValue; * cloudTile.CloudOpaqueness = short.MaxValue;*/ // North: Negative Z // South: Positive Z if (i > 0) { Tiles[i - 1].NorthThickness = cloudTile.SelfThickness; } if (i < Tiles.Length - 1) { Tiles[i + 1].SouthThickness = cloudTile.SelfThickness; } // East: Positive X // West: Negative X if (i < CloudTileLength - 1) { Tiles[i + CloudTileLength].EastThickness = cloudTile.SelfThickness; } if (i > CloudTileLength - 1) { Tiles[i - CloudTileLength].WestThickness = cloudTile.SelfThickness; } } }