示例#1
0
        private static void GenerateGrassFringe(RawPrimitive Into, VoxelHandle Voxel, Geo.TemplateFace Face, TerrainTileSheet TileSheet, SliceCache Cache, GrassType decalType)
        {
            for (var i = 0; i < 4; ++i)
            {
                Cache.EdgeFringeTempVerticies[i].Set = false;
            }

            if (Face.Edges != null)
            {
                for (var e = 0; e < Face.Edges.Length; ++e)
                {
                    var fringeNeighbor = VoxelHelpers.GetNeighbor(Voxel, OrientationHelper.GetFaceNeighborOffset(Face.Edges[e].Orientation));
                    if (fringeNeighbor.IsValid)
                    {
                        if (fringeNeighbor.IsEmpty)
                        {
                            GenerateEdgeFringe(Into, Face, e, TileSheet, Cache, decalType, new Vector3(0.0f, -0.5f, 0.0f), 0.5f);
                        }
                        else
                        {
                            var above = VoxelHelpers.GetVoxelAbove(fringeNeighbor);
                            if (above.IsValid && !above.IsEmpty)
                            {
                                GenerateEdgeFringe(Into, Face, e, TileSheet, Cache, decalType, new Vector3(0.0f, 0.5f, 0.0f), -0.1f);
                            }
                            else if (fringeNeighbor.GrassType == 0 || (fringeNeighbor.GrassType != Voxel.GrassType && Library.GetGrassType(fringeNeighbor.GrassType).FringePrecedence < decalType.FringePrecedence))
                            {
                                GenerateEdgeFringe(Into, Face, e, TileSheet, Cache, decalType, new Vector3(0.0f, 0.2f, 0.0f), 0.5f);
                            }
                        }
                    }
                }
            }

            if (Face.Corners != null)
            {
                for (var c = 0; c < Face.Corners.Length; ++c)
                {
                    var cornerNeighbor = VoxelHelpers.GetNeighbor(Voxel, OrientationHelper.GetFaceNeighborOffset(Face.Edges[Face.Corners[c].EdgeA].Orientation) + OrientationHelper.GetFaceNeighborOffset(Face.Edges[Face.Corners[c].EdgeB].Orientation));

                    var manhattanA = VoxelHelpers.GetNeighbor(Voxel, OrientationHelper.GetFaceNeighborOffset(Face.Edges[Face.Corners[c].EdgeA].Orientation));
                    var manhattanB = VoxelHelpers.GetNeighbor(Voxel, OrientationHelper.GetFaceNeighborOffset(Face.Edges[Face.Corners[c].EdgeB].Orientation));

                    if (manhattanA.IsValid && !manhattanA.IsEmpty && manhattanA.GrassType == Voxel.GrassType)
                    {
                        continue;
                    }

                    if (manhattanB.IsValid && !manhattanB.IsEmpty && manhattanB.GrassType == Voxel.GrassType)
                    {
                        continue;
                    }


                    if (cornerNeighbor.IsValid)
                    {
                        if (cornerNeighbor.IsEmpty) // Todo: Do not generate fringe if horizontal neighbors are occupied.
                        // Todo: Also - needs to use corners set by edge fringe when they are at different heights. Maybe specify which edges the corner is in between?
                        {
                            GenerateHangingCornerFringe(Into, Face, TileSheet, Cache, decalType, Face.Corners[c], new Vector3(0.0f, -0.5f, 0.0f));
                        }
                        else
                        {
                            var above = VoxelHelpers.GetVoxelAbove(cornerNeighbor);
                            if (above.IsValid && !above.IsEmpty)
                            {
                            }
                            else if (cornerNeighbor.GrassType == 0 || (cornerNeighbor.GrassType != Voxel.GrassType && Library.GetGrassType(cornerNeighbor.GrassType).FringePrecedence < decalType.FringePrecedence))
                            {
                                GenerateHangingCornerFringe(Into, Face, TileSheet, Cache, decalType, Face.Corners[c], new Vector3(0.0f, 0.1f, 0.0f));
                            }
                        }
                    }
                }
            }
        }
        public static void GenerateSurfaceLife(VoxelChunk TopChunk, ChunkGeneratorSettings Settings)
        {
            var creatureCounts = new Dictionary <string, Dictionary <string, int> >();
            var worldDepth     = Settings.WorldSizeInChunks.Y * VoxelConstants.ChunkSizeY;

            for (var x = TopChunk.Origin.X; x < TopChunk.Origin.X + VoxelConstants.ChunkSizeX; x++)
            {
                for (var z = TopChunk.Origin.Z; z < TopChunk.Origin.Z + VoxelConstants.ChunkSizeZ; z++)
                {
                    var overworldPosition = OverworldMap.WorldToOverworld(new Vector2(x, z), Settings.Overworld.InstanceSettings.Origin);

                    if (Settings.Overworld.Map.GetBiomeAt(new Vector3(x, 0, z), Settings.Overworld.InstanceSettings.Origin).HasValue(out var biome))
                    {
                        var normalizedHeight = NormalizeHeight(Settings.Overworld.Map.LinearInterpolate(overworldPosition, OverworldField.Height));
                        var height           = (int)MathFunctions.Clamp(normalizedHeight * worldDepth, 0.0f, worldDepth - 2);

                        var voxel = Settings.World.ChunkManager.CreateVoxelHandle(new GlobalVoxelCoordinate(x, height, z));

                        if (!voxel.IsValid ||
                            voxel.Coordinate.Y == 0 ||
                            voxel.Coordinate.Y >= worldDepth - Settings.TreeLine)
                        {
                            continue;
                        }

                        if (voxel.LiquidLevel != 0)
                        {
                            continue;
                        }

                        var above = VoxelHelpers.GetVoxelAbove(voxel);
                        if (above.IsValid && (above.LiquidLevel != 0 || !above.IsEmpty))
                        {
                            continue;
                        }

                        foreach (var animal in biome.Fauna)
                        {
                            if (MathFunctions.RandEvent(animal.SpawnProbability))
                            {
                                if (!creatureCounts.ContainsKey(biome.Name))
                                {
                                    creatureCounts[biome.Name] = new Dictionary <string, int>();
                                }
                                var dict = creatureCounts[biome.Name];
                                if (!dict.ContainsKey(animal.Name))
                                {
                                    dict[animal.Name] = 0;
                                }
                                if (dict[animal.Name] < animal.MaxPopulation)
                                {
                                    EntityFactory.CreateEntity <GameComponent>(animal.Name,
                                                                               voxel.WorldPosition + Vector3.Up * 1.5f);
                                }
                                break;
                            }
                        }

                        if (voxel.Type.Name != biome.SoilLayer.VoxelType)
                        {
                            continue;
                        }

                        foreach (VegetationData veg in biome.Vegetation)
                        {
                            if (voxel.GrassType == 0)
                            {
                                continue;
                            }

                            if (MathFunctions.RandEvent(veg.SpawnProbability) &&
                                Settings.NoiseGenerator.Noise(voxel.Coordinate.X / veg.ClumpSize,
                                                              veg.NoiseOffset, voxel.Coordinate.Z / veg.ClumpSize) >= veg.ClumpThreshold)
                            {
                                var treeSize = MathFunctions.Rand() * veg.SizeVariance + veg.MeanSize;

                                EntityFactory.CreateEntity <Plant>(veg.Name,
                                                                   voxel.WorldPosition + new Vector3(0.5f, 1.0f, 0.5f),
                                                                   Blackboard.Create("Scale", treeSize));

                                break;
                            }
                        }
                    }
                }
            }
        }
        private static void PrecomputeVoxelSlopes(ChunkManager Chunks, VoxelHandle V)
        {
            if (!V.IsValid)
            {
                return;
            }

            if (V.IsEmpty || !V.IsVisible || V.Type == null || !V.Type.CanRamp)
            {
                V.RampType = RampType.None;
                return;
            }

            var vAbove = VoxelHelpers.GetVoxelAbove(V);

            if (vAbove.IsValid && !vAbove.IsEmpty)
            {
                V.RampType = RampType.None;
                return;
            }

            var compositeRamp = RampType.None;

            foreach (var vertex in TopVerticies)
            {
                // If there are no empty neighbors, no slope.


                // - Check manhattan neighbors - both full?
                //      then check if they can slope - if yes, and diagonal is empty, slope
                //          if not, then no slope
                //      if diagonal full - obviously no slope.
                if (!VoxelHelpers.EnumerateVertexNeighbors2D(V.Coordinate, vertex) // Todo: Account for case where only open voxel is diagonal between two full ones
                    .Any(n =>
                {
                    var handle = Chunks.CreateVoxelHandle(n);
                    if (handle.IsValid)
                    {
                        return(handle.IsEmpty);
                    }
                    return(false);
                }))
                {
                    continue;
                }

                switch (vertex)
                {
                case VoxelVertex.FrontTopLeft:
                    compositeRamp |= RampType.TopFrontLeft;
                    break;

                case VoxelVertex.FrontTopRight:
                    compositeRamp |= RampType.TopFrontRight;
                    break;

                case VoxelVertex.BackTopLeft:
                    compositeRamp |= RampType.TopBackLeft;
                    break;

                case VoxelVertex.BackTopRight:
                    compositeRamp |= RampType.TopBackRight;
                    break;
                }
            }

            V.RampType = compositeRamp;
        }