Пример #1
0
        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;
        }
Пример #2
0
        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;
        }
Пример #3
0
        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);
                    }
                }
            }
        }