public void RebuildMoteLayer(int LocalY) { #if DEBUG if (LocalY < 0 || LocalY >= VoxelConstants.ChunkSizeY) { throw new InvalidOperationException(); } #endif var moteList = new List <NewInstanceData>(); // Enumerate voxels. for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x) { for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z) { var v = VoxelHandle.UnsafeCreateLocalHandle(this, new LocalVoxelCoordinate(x, LocalY, z)); if (!v.IsValid) { continue; } // Don't generate in empty voxels. if (v.IsEmpty) { continue; } if (!v.IsExplored) { continue; } // Don't generate motes if above is not empty var voxelAbove = VoxelHelpers.GetVoxelAbove(v); if (voxelAbove.IsValid && (!voxelAbove.IsEmpty || voxelAbove.LiquidLevel != 0)) { continue; } // Find biome type. var biomeData = Manager.World.Overworld.Map.GetBiomeAt(v.WorldPosition, Manager.World.Overworld.InstanceSettings.Origin); // Don't generate if not on grass type. if (v.GrassType == 0 || Library.GetGrassType(v.GrassType).Name != biomeData.GrassDecal) { continue; } // Biomes can contain multiple types of mote. foreach (var moteDetail in biomeData.Motes) { // Lower mote if voxel is ramped. float vOffset = 0.0f; if (v.RampType != RampType.None) { vOffset = -0.5f; } var vPos = v.WorldPosition * moteDetail.RegionScale; float value = MoteNoise.Noise(vPos.X, vPos.Y, vPos.Z); if (!(Math.Abs(value) > moteDetail.SpawnThreshold)) { continue; } float s = MoteScaleNoise.Noise(vPos.X, vPos.Y, vPos.Z) * moteDetail.MoteScale; var smallNoise = ClampVector(VertexNoise.GetRandomNoiseVector(vPos * 20.0f) * 20.0f, 0.4f); smallNoise.Y = 0.0f; var mote = GenerateGrassMote( Manager.World, v.WorldPosition + new Vector3(0.5f, 1.0f + s * 0.5f + vOffset, 0.5f) + smallNoise, new Color(v.Sunlight ? 255 : 0, 128, 0), s, moteDetail); moteList.Add(mote); } } } MoteRecords[LocalY] = moteList; }
public void InitializeFromChunk(VoxelChunk chunk, GraphicsDevice graphics) { //chunk.PrimitiveMutex.WaitOne(); if (!chunk.IsVisible || IsBuilding) { // chunk.PrimitiveMutex.ReleaseMutex(); return; } IsBuilding = true; //chunk.PrimitiveMutex.ReleaseMutex(); accumulatedVertices.Clear(); faceExists.Clear(); drawFace.Clear(); int[,,] totalDepth = new int[chunk.SizeX, chunk.SizeY, chunk.SizeZ]; for (int x = 0; x < chunk.SizeX; x++) { for (int z = 0; z < chunk.SizeZ; z++) { bool drynessEncountered = false; int previousSum = 0; for (int y = 0; y < chunk.SizeY; y++) { WaterCell cell = chunk.Data.Water[chunk.Data.IndexAt(x, y, z)]; byte waterLevel = cell.WaterLevel; if (cell.Type != LiqType) { waterLevel = 0; } if (drynessEncountered) { if (waterLevel > 0) { drynessEncountered = false; previousSum += waterLevel; totalDepth[x, y, z] = previousSum; } } else { if (waterLevel > 0) { previousSum += waterLevel; totalDepth[x, y, z] = previousSum; } else { drynessEncountered = true; previousSum = 0; totalDepth[x, y, z] = 0; } } } } } int maxY = chunk.SizeY; if (chunk.Manager.ChunkData.Slice == ChunkManager.SliceMode.Y) { maxY = (int)Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, chunk.SizeY); } Voxel myVoxel = chunk.MakeVoxel(0, 0, 0); Voxel vox = chunk.MakeVoxel(0, 0, 0); for (int x = 0; x < chunk.SizeX; x++) { for (int y = 0; y < maxY; y++) { for (int z = 0; z < chunk.SizeZ; z++) { int index = chunk.Data.IndexAt(x, y, z); if (chunk.Data.Water[index].WaterLevel > 0 && chunk.Data.Water[index].Type == LiqType) { bool isTop = false; myVoxel.GridPosition = new Vector3(x, y, z); for (int i = 0; i < 6; i++) { BoxFace face = (BoxFace)i; if (face == BoxFace.Bottom) { continue; } Vector3 delta = faceDeltas[face]; bool success = chunk.Manager.ChunkData.GetVoxel(chunk, new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z) + chunk.Origin, ref vox); if (success) { if (face == BoxFace.Top) { if (vox.WaterLevel == 0 || y == (int)chunk.Manager.ChunkData.MaxViewingLevel) { drawFace[face] = true; } else { drawFace[face] = false; } } else { if (vox.WaterLevel == 0 && vox.IsEmpty) { drawFace[face] = true; } else { drawFace[face] = false; } bool gotVox = chunk.Manager.ChunkData.GetVoxel(chunk, new Vector3(x, y + 1, z) + chunk.Origin, ref vox); isTop = !gotVox || vox.IsEmpty || vox.WaterLevel == 0; } } else { drawFace[face] = true; } if (!drawFace[face]) { continue; } IEnumerable <ExtendedVertex> vertices = CreateWaterFace(myVoxel, face, chunk, x, y, z, totalDepth[x, y, z], isTop); foreach (ExtendedVertex newVertex in vertices.Select(vertex => new ExtendedVertex(vertex.Position + VertexNoise.GetRandomNoiseVector(vertex.Position), vertex.Color, vertex.VertColor, vertex.TextureCoordinate, vertex.TextureBounds))) { accumulatedVertices.Add(newVertex); } } } } } } try { ExtendedVertex[] vertex = new ExtendedVertex[accumulatedVertices.Count]; for (int i = 0; i < accumulatedVertices.Count; i++) { vertex[i] = accumulatedVertices[i]; } Vertices = vertex; chunk.PrimitiveMutex.WaitOne(); ResetBuffer(graphics); chunk.PrimitiveMutex.ReleaseMutex(); } catch (System.Threading.AbandonedMutexException e) { Console.Error.WriteLine(e.Message); } IsBuilding = false; }
public void RebuildMoteLayer(int Y) { BoundingBox box = GetBoundingBox(); box.Min.Y = Y; box.Max.Y = Y + 1; //Drawer3D.DrawBox(box, Color.Red, 0.1f, true); // Destroy old motes. if (MoteRecords[Y] != null) { foreach (var record in MoteRecords[Y]) { DestroyGrassMote(this.Manager.World, record.Type, record); } MoteRecords[Y].Clear(); } else { MoteRecords[Y] = new List <NewInstanceData>(); } // Enumerate voxels. for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x) { for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z) { // Don't generate motes if above is not empty if (Y < VoxelConstants.ChunkSizeY - 1) { var voxelAbove = new VoxelHandle(this, new LocalVoxelCoordinate(x, Y + 1, z)); if (!voxelAbove.IsEmpty || voxelAbove.WaterCell.WaterLevel != 0) { continue; } } var v = new VoxelHandle(this, new LocalVoxelCoordinate(x, Y, z)); // Don't generate in empty voxels. if (v.IsEmpty) { continue; } if (!v.IsExplored) { continue; } // Find biome type. var biome = Overworld.Map[ (int)MathFunctions.Clamp(v.WorldPosition.X / Manager.World.WorldScale, 0, Overworld.Map.GetLength(0) - 1), (int)MathFunctions.Clamp(v.WorldPosition.Z / Manager.World.WorldScale, 0, Overworld.Map.GetLength(1) - 1)] .Biome; var biomeData = BiomeLibrary.Biomes[biome]; // Don't generate if not on grass type. if (v.GrassType == 0 || GrassLibrary.GetGrassType(v.GrassType).Name != biomeData.GrassDecal) { continue; } // Biomes can contain multiple types of mote. foreach (var moteDetail in biomeData.Motes) { // Lower mote if voxel is ramped. float vOffset = 0.0f; if (v.RampType != RampType.None) { vOffset = -0.5f; } var vPos = v.WorldPosition * moteDetail.RegionScale; float value = MoteNoise.Noise(vPos.X, vPos.Y, vPos.Z); if (!(Math.Abs(value) > moteDetail.SpawnThreshold)) { continue; } float s = MoteScaleNoise.Noise(vPos.X, vPos.Y, vPos.Z) * moteDetail.MoteScale; var smallNoise = ClampVector(VertexNoise.GetRandomNoiseVector(vPos * 20.0f) * 20.0f, 0.4f); smallNoise.Y = 0.0f; var mote = GenerateGrassMote( Manager.World, v.WorldPosition + new Vector3(0.5f, 1.0f + s * 0.5f + vOffset, 0.5f) + smallNoise, new Color(v.SunColor, 128, 0), s, moteDetail.Name); MoteRecords[Y].Add(mote); } } } }