public static void GenerateWater(VoxelChunk chunk, ChunkGeneratorSettings Settings) { var iceID = Library.GetVoxelType("Ice"); for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x) { for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z) { if (Settings.Overworld.Map.GetBiomeAt(new Vector3(x, 0, z) + chunk.Origin.ToVector3(), Settings.Overworld.InstanceSettings.Origin).HasValue(out var biome)) { for (var y = 0; y < VoxelConstants.ChunkSizeY; ++y) { var globalY = y + chunk.Origin.Y; if (globalY > Settings.NormalizedSeaLevel) { break; } var voxel = VoxelHandle.UnsafeCreateLocalHandle(chunk, new LocalVoxelCoordinate(x, y, z)); if (voxel.IsEmpty && voxel.Sunlight) { if (globalY == Settings.NormalizedSeaLevel && biome.WaterSurfaceIce) { voxel.RawSetType(iceID); } else { voxel.QuickSetLiquid(biome.WaterIsLava ? LiquidType.Lava : LiquidType.Water, WaterManager.maxWaterLevel); } } } } } } }
private static void GenerateSliceGeometry( RawPrimitive Into, VoxelChunk Chunk, int LocalY, TerrainTileSheet TileSheet, WorldManager World, SliceCache Cache) { for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x) { for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z) { GenerateVoxelGeometry(Into, VoxelHandle.UnsafeCreateLocalHandle(Chunk, new LocalVoxelCoordinate(x, LocalY, z)), TileSheet, World, Cache); } } }
private static void PrecomputeVoxelSlopesSlice(ChunkManager Chunks, VoxelChunk Chunk, int LocalY) { for (int x = 0; x < VoxelConstants.ChunkSizeX; x++) { for (int z = 0; z < VoxelConstants.ChunkSizeZ; z++) { PrecomputeVoxelSlopes(Chunks, VoxelHandle.UnsafeCreateLocalHandle(Chunk, new LocalVoxelCoordinate(x, LocalY, z))); } } var startChunkCorner = new GlobalVoxelCoordinate(Chunk.ID, new LocalVoxelCoordinate(0, 0, 0)) + new GlobalVoxelOffset(-1, 0, -1); var endChunkCorner = new GlobalVoxelCoordinate(Chunk.ID, new LocalVoxelCoordinate(0, 0, 0)) + new GlobalVoxelOffset(VoxelConstants.ChunkSizeX, 0, VoxelConstants.ChunkSizeZ); for (int x = startChunkCorner.X; x <= endChunkCorner.X; ++x) { var v1 = new VoxelHandle(Chunk.Manager, new GlobalVoxelCoordinate(x, Chunk.Origin.Y + LocalY, startChunkCorner.Z)); if (v1.IsValid) { PrecomputeVoxelSlopes(Chunks, v1); } var v2 = new VoxelHandle(Chunk.Manager, new GlobalVoxelCoordinate(x, Chunk.Origin.Y + LocalY, endChunkCorner.Z)); if (v2.IsValid) { PrecomputeVoxelSlopes(Chunks, v2); } } for (int z = startChunkCorner.Z + 1; z < endChunkCorner.Z; ++z) { var v1 = new VoxelHandle(Chunk.Manager, new GlobalVoxelCoordinate(startChunkCorner.X, Chunk.Origin.Y + LocalY, z)); if (v1.IsValid) { PrecomputeVoxelSlopes(Chunks, v1); } var v2 = new VoxelHandle(Chunk.Manager, new GlobalVoxelCoordinate(endChunkCorner.X, Chunk.Origin.Y + LocalY, z)); if (v2.IsValid) { PrecomputeVoxelSlopes(Chunks, v2); } } }
public static void GenerateLava(VoxelChunk chunk, ChunkGeneratorSettings Settings) { if (chunk.Origin.Y >= Settings.LavaLevel) { return; } for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x) { for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z) { for (var y = 0; y < Settings.LavaLevel - chunk.Origin.Y; ++y) { var voxel = VoxelHandle.UnsafeCreateLocalHandle(chunk, new LocalVoxelCoordinate(x, y, z)); if (voxel.IsEmpty && voxel.LiquidLevel == 0) { voxel.QuickSetLiquid(LiquidType.Lava, WaterManager.maxWaterLevel); } } } } }
public static void GenerateCaves(VoxelChunk Chunk, ChunkGeneratorSettings Settings) { if (Library.GetBiome("Cave").HasValue(out BiomeData caveBiome) && Library.GetBiome("Hell").HasValue(out BiomeData hellBiome)) { for (int x = 0; x < VoxelConstants.ChunkSizeX; x++) { for (int z = 0; z < VoxelConstants.ChunkSizeZ; z++) { for (int i = 0; i < Settings.CaveLevels.Count; i++) { // Does layer intersect this voxel? int y = Settings.CaveLevels[i]; if (y + Settings.MaxCaveHeight < Chunk.Origin.Y) { continue; } if (y >= Chunk.Origin.Y + VoxelConstants.ChunkSizeY) { continue; } var coordinate = new GlobalVoxelCoordinate(Chunk.Origin.X + x, y, Chunk.Origin.Z + z); var data = GetCaveGenerationData(coordinate, i, Settings); var biome = (y <= Settings.HellLevel) ? hellBiome : caveBiome; if (!data.CaveHere) { continue; } for (int dy = 0; dy < data.Height; dy++) { var globalY = y + dy; // Prevent caves punching holes in bedrock. if (globalY <= 0) { continue; } // Check if voxel is inside chunk. if (globalY <= 0 || globalY < Chunk.Origin.Y || globalY >= Chunk.Origin.Y + VoxelConstants.ChunkSizeY) { continue; } var voxel = VoxelHandle.UnsafeCreateLocalHandle(Chunk, new LocalVoxelCoordinate(x, globalY - Chunk.Origin.Y, z)); // Prevent caves from breaking surface. bool caveBreaksSurface = false; foreach (var neighborCoordinate in VoxelHelpers.EnumerateAllNeighbors(voxel.Coordinate)) { var v = Chunk.Manager.CreateVoxelHandle(neighborCoordinate); if (!v.IsValid || (v.Sunlight)) { caveBreaksSurface = true; break; } } if (caveBreaksSurface) { break; } voxel.RawSetType(Library.EmptyVoxelType); if (dy == 0) { // Place soil voxel and grass below cave. var below = VoxelHelpers.GetVoxelBelow(voxel); if (below.IsValid) { below.RawSetType(Library.GetVoxelType(biome.SoilLayer.VoxelType)); var grassType = Library.GetGrassType(biome.GrassDecal); if (grassType != null) { below.RawSetGrass(grassType.ID); } } // Spawn flora and fauna. if (data.Noise > Settings.CaveSize * 1.8f && globalY > Settings.LavaLevel) { GenerateCaveFlora(below, biome, Settings); GenerateCaveFauna(below, biome, Settings); } } } } } } } }
public static VoxelChunk GenerateChunk(GlobalChunkCoordinate ID, ChunkGeneratorSettings Settings) { var origin = new GlobalVoxelCoordinate(ID, new LocalVoxelCoordinate(0, 0, 0)); var worldDepth = Settings.WorldSizeInChunks.Y * VoxelConstants.ChunkSizeY; var waterHeight = NormalizeHeight(Settings.Overworld.GenerationSettings.SeaLevel + 1.0f / worldDepth); var c = new VoxelChunk(Settings.World.ChunkManager, ID); if (GameSettings.Current.NoStone) { return(c); } for (int x = 0; x < VoxelConstants.ChunkSizeX; x++) { for (int z = 0; z < VoxelConstants.ChunkSizeZ; z++) { var overworldPosition = OverworldMap.WorldToOverworld(new Vector2(x + origin.X, z + origin.Z), Settings.Overworld.InstanceSettings.Origin); if (Settings.Overworld.Map.GetBiomeAt(new Vector3(x + origin.X, 0, z + origin.Z), Settings.Overworld.InstanceSettings.Origin).HasValue(out var biomeData)) { var normalizedHeight = NormalizeHeight(Settings.Overworld.Map.LinearInterpolate(overworldPosition, OverworldField.Height)); var height = MathFunctions.Clamp(normalizedHeight * worldDepth, 0.0f, worldDepth - 2); var stoneHeight = (int)MathFunctions.Clamp((int)(height - (biomeData.SoilLayer.Depth + (Math.Sin(overworldPosition.X) + Math.Cos(overworldPosition.Y)))), 1, height); for (int y = 0; y < VoxelConstants.ChunkSizeY; y++) { var globalY = origin.Y + y; var voxel = VoxelHandle.UnsafeCreateLocalHandle(c, new LocalVoxelCoordinate(x, y, z)); if (globalY == 0) { voxel.RawSetType(Library.GetVoxelType("Bedrock")); continue; } // Below the stone line, use subsurface layers. if (globalY <= stoneHeight && stoneHeight > 1) { var depth = stoneHeight - globalY - biomeData.SubsurfaceLayers[0].Depth + 1; var subsurfaceLayer = 0; while (depth > 0 && subsurfaceLayer < biomeData.SubsurfaceLayers.Count - 1) { depth -= biomeData.SubsurfaceLayers[subsurfaceLayer].Depth; subsurfaceLayer += 1; } voxel.RawSetType(Library.GetVoxelType(biomeData.SubsurfaceLayers[subsurfaceLayer].VoxelType)); } // Otherwise, on the surface. else if ((globalY == (int)height || globalY == stoneHeight) && normalizedHeight > waterHeight) { voxel.RawSetType(Library.GetVoxelType(biomeData.SoilLayer.VoxelType)); if (!String.IsNullOrEmpty(biomeData.GrassDecal)) { if (!biomeData.ClumpGrass || (biomeData.ClumpGrass && Settings.NoiseGenerator.Noise(overworldPosition.X / biomeData.ClumpSize, 0, overworldPosition.Y / biomeData.ClumpSize) > biomeData.ClumpTreshold)) { voxel.RawSetGrass(Library.GetGrassType(biomeData.GrassDecal).ID); } } } else if (globalY > height && globalY > 0) { voxel.RawSetType(Library.EmptyVoxelType); } else if (normalizedHeight <= waterHeight) { voxel.RawSetType(Library.GetVoxelType(biomeData.ShoreVoxel)); } else { voxel.RawSetType(Library.GetVoxelType(biomeData.SoilLayer.VoxelType)); } } } } } return(c); }