Пример #1
0
        private static bool IsFaceVisible(VoxelHandle V, Geo.TemplateFace Face, ChunkManager Chunks, out VoxelHandle Neighbor)
        {
            var delta = OrientationHelper.GetFaceNeighborOffset(Face.Orientation);

            Neighbor = new VoxelHandle(Chunks, V.Coordinate + delta);
            return(IsFaceVisible(V, Neighbor, Face));
        }
        private static int GetVoxelVertexExploredNeighbors(VoxelHandle V, Geo.TemplateFace Face, SliceCache Cache)
        {
            var exploredVerts = 0;

            if (V.IsExplored)
            {
                exploredVerts = 4;
            }
            else
            {
                for (int faceVertex = 0; faceVertex < Face.Mesh.VertexCount; ++faceVertex)
                {
                    var cacheKey            = SliceCache.GetCacheKey(V, Face.Mesh.Verticies[faceVertex].LogicalVertex);
                    var anyNeighborExplored = true;

                    if (!Cache.ExploredCache.TryGetValue(cacheKey, out anyNeighborExplored))
                    {
                        anyNeighborExplored = VoxelHelpers.EnumerateVertexNeighbors2D(V.Coordinate, Face.Mesh.Verticies[faceVertex].LogicalVertex)
                                              .Select(c => new VoxelHandle(V.Chunk.Manager, c))
                                              .Any(n => n.IsValid && n.IsExplored);
                        Cache.ExploredCache.Add(cacheKey, anyNeighborExplored);
                    }

                    if (anyNeighborExplored)
                    {
                        exploredVerts += 1;
                    }
                }
            }

            return(exploredVerts);
        }
Пример #3
0
        private static void GenerateHangingCornerFringe(
            RawPrimitive Into,
            Geo.TemplateFace Face,
            TerrainTileSheet TileSheet,
            SliceCache Cache,
            GrassType decalType,
            Geo.TemplateCorner Corner,
            Vector3 Sag)
        {
            var vertex = Cache.FaceGeometry[Corner.Vertex];

            Cache.TempVerticies[0] = new ExtendedVertex(
                vertex.Position,
                vertex.Color, vertex.VertColor,
                TileSheet.MapTileUVs(new Vector2(0.0f, 0.0f), decalType.FringeTiles[2]), TileSheet.GetTileBounds(decalType.FringeTiles[2]));

            Cache.TempVerticies[1] = new ExtendedVertex(
                Cache.EdgeFringeTempVerticies[Corner.EdgeA].Set ? Cache.EdgeFringeTempVerticies[Corner.EdgeA].End :
                (vertex.Position
                 + OrientationHelper.GetFaceNeighborOffset(Face.Edges[Corner.EdgeA].Orientation).AsVector3() * 0.5f
                 + Sag),
                vertex.Color, vertex.VertColor,
                TileSheet.MapTileUVs(new Vector2(0.5f, 0.0f), decalType.FringeTiles[2]), TileSheet.GetTileBounds(decalType.FringeTiles[2]));

            Cache.TempVerticies[2] = new ExtendedVertex(
                vertex.Position
                + OrientationHelper.GetFaceNeighborOffset(Face.Edges[Corner.EdgeA].Orientation).AsVector3() * 0.5f
                + OrientationHelper.GetFaceNeighborOffset(Face.Edges[Corner.EdgeB].Orientation).AsVector3() * 0.5f
                + Sag,
                vertex.Color, vertex.VertColor,
                TileSheet.MapTileUVs(new Vector2(0.5f, 0.5f), decalType.FringeTiles[2]), TileSheet.GetTileBounds(decalType.FringeTiles[2]));

            Cache.TempVerticies[3] = new ExtendedVertex(
                Cache.EdgeFringeTempVerticies[Corner.EdgeB].Set ? Cache.EdgeFringeTempVerticies[Corner.EdgeB].Start :
                (vertex.Position
                 + OrientationHelper.GetFaceNeighborOffset(Face.Edges[Corner.EdgeB].Orientation).AsVector3() * 0.5f
                 + Sag),
                vertex.Color, vertex.VertColor,
                TileSheet.MapTileUVs(new Vector2(0.0f, 0.5f), decalType.FringeTiles[2]), TileSheet.GetTileBounds(decalType.FringeTiles[2]));

            AddQuad(Into, Cache.TempVerticies, QuadIndicies);
        }
Пример #4
0
        public static void GenerateFaceGeometry(
            RawPrimitive Into,
            VoxelHandle Voxel,
            Geo.TemplateFace Face,
            TerrainTileSheet TileSheet,
            WorldManager World,
            SliceCache Cache)
        {
            if (Face.CullType == Geo.FaceCullType.Cull && !IsFaceVisible(Voxel, Face, World.ChunkManager, out var neighbor))
            {
                return;
            }

            if (Face.Orientation == FaceOrientation.Top)
            {
                if (Voxel.GrassType != 0)
                {
                    var decalType = Library.GetGrassType(Voxel.GrassType);
                    PrepVerticies(World, Voxel, Face, Cache, GetVoxelVertexExploredNeighbors(Voxel, Face, Cache), TileSheet, decalType.Tile, true, 0.0f);

                    GenerateGrassFringe(Into, Voxel, Face, TileSheet, Cache, decalType);
                }
                else
                {
                    PrepVerticies(World, Voxel, Face, Cache, GetVoxelVertexExploredNeighbors(Voxel, Face, Cache), TileSheet, SelectTile(Voxel.Type, Face.Orientation), true, 0.0f);
                }

                AddQuad(Into, Cache.FaceGeometry, QuadIndicies);

                if (Voxel.DecalType != 0)
                {
                    var decalType = Library.GetDecalType(Voxel.DecalType);
                    PrepVerticies(World, Voxel, Face, Cache, GetVoxelVertexExploredNeighbors(Voxel, Face, Cache), TileSheet, decalType.Tile, true, 0.02f);
                    AddQuad(Into, Cache.FaceGeometry, QuadIndicies);
                }
            }
            else
            {
                PrepVerticies(World, Voxel, Face, Cache, GetVoxelVertexExploredNeighbors(Voxel, Face, Cache), TileSheet, SelectTile(Voxel.Type, Face.Orientation), true, 0.0f);
                AddQuad(Into, Cache.FaceGeometry, QuadIndicies);
            }
        }
Пример #5
0
        private static void GenerateEdgeFringe(
            RawPrimitive Into,
            Geo.TemplateFace Face,
            int EdgeIndex,
            TerrainTileSheet TileSheet,
            SliceCache Cache,
            GrassType decalType,
            Vector3 Sag,
            float Scale)
        {
            var start = Cache.FaceGeometry[Face.Edges[EdgeIndex].Start];
            var end   = Cache.FaceGeometry[Face.Edges[EdgeIndex].End];

            Cache.EdgeFringeTempVerticies[EdgeIndex].Set = true;

            Cache.TempVerticies[0] = new ExtendedVertex(
                start.Position,
                start.Color, start.VertColor,
                TileSheet.MapTileUVs(new Vector2(0.0f, 0.0f), decalType.FringeTiles[0]), TileSheet.GetTileBounds(decalType.FringeTiles[0]));

            Cache.TempVerticies[1] = new ExtendedVertex(
                end.Position,
                end.Color, end.VertColor,
                TileSheet.MapTileUVs(new Vector2(1.0f, 0.0f), decalType.FringeTiles[0]), TileSheet.GetTileBounds(decalType.FringeTiles[0]));

            Cache.EdgeFringeTempVerticies[EdgeIndex].End = end.Position + OrientationHelper.GetFaceNeighborOffset(Face.Edges[EdgeIndex].Orientation).AsVector3() * Scale + Sag;
            Cache.TempVerticies[2] = new ExtendedVertex(
                Cache.EdgeFringeTempVerticies[EdgeIndex].End,
                end.Color, end.VertColor,
                TileSheet.MapTileUVs(new Vector2(1.0f, 0.5f), decalType.FringeTiles[0]), TileSheet.GetTileBounds(decalType.FringeTiles[0]));

            Cache.EdgeFringeTempVerticies[EdgeIndex].Start = start.Position + OrientationHelper.GetFaceNeighborOffset(Face.Edges[EdgeIndex].Orientation).AsVector3() * Scale + Sag;
            Cache.TempVerticies[3] = new ExtendedVertex(
                Cache.EdgeFringeTempVerticies[EdgeIndex].Start,
                start.Color, start.VertColor,
                TileSheet.MapTileUVs(new Vector2(0.0f, 0.5f), decalType.FringeTiles[0]), TileSheet.GetTileBounds(decalType.FringeTiles[0]));

            AddQuad(Into, Cache.TempVerticies, QuadIndicies);
        }
Пример #6
0
        private static bool IsFaceVisible(VoxelHandle voxel, VoxelHandle neighbor, Geo.TemplateFace face)
        {
            if (!voxel.IsValid)
            {
                return(false);
            }

            if (!neighbor.IsValid)
            {
                if (voxel.IsExplored)
                {
                    return(!voxel.IsEmpty);
                }
                else
                {
                    return(true);
                }
            }
            else
            {
                if (!voxel.IsExplored)
                {
                    if (!neighbor.IsVisible)
                    {
                        return(true);
                    }

                    if (neighbor.IsExplored && neighbor.IsEmpty)
                    {
                        return(true);
                    }

                    if (!neighbor.Type.CanRamp)
                    {
                        return(false);
                    }

                    if (neighbor.RampType == RampType.None)
                    {
                        return(false);
                    }

                    if (!IsSideFace(face))
                    {
                        return(false);
                    }

                    if (!neighbor.IsExplored)
                    {
                        return(false);
                    }

                    return(true);
                }
                else
                {
                    if (neighbor.IsExplored && neighbor.IsEmpty)
                    {
                        return(true);
                    }

                    if (face.Orientation == FaceOrientation.Top && !neighbor.IsVisible)
                    {
                        return(true);
                    }

                    if (neighbor.Type.IsTransparent && !voxel.Type.IsTransparent)
                    {
                        return(true);
                    }

                    var neighborSideOrientation = OrientationHelper.GetOppositeFace(face.Orientation);
                    var neighborSolid           = TemplateSolidLibrary.GetTemplateSolid(neighbor.Type.TemplateSolid);
                    var neighborSide            = neighborSolid.Faces.FirstOrDefault(s => s.Orientation == neighborSideOrientation);
                    if (neighborSide == null)
                    {
                        return(true);
                    }
                    if (neighborSide.FaceShape == TemplateFaceShapes.LowerSlab && face.FaceShape != TemplateFaceShapes.LowerSlab)
                    {
                        return(true);
                    }

                    if (neighbor.Type.CanRamp &&
                        neighbor.RampType != RampType.None &&
                        IsSideFace(face) &&
                        ShouldDrawFace(face.Orientation, neighbor.RampType, voxel.RampType) &&
                        neighbor.IsExplored)
                    {
                        return(true);
                    }

                    return(false);
                }
            }
        }
Пример #7
0
 private static bool IsSideFace(Geo.TemplateFace face)
 {
     return(face.Orientation != FaceOrientation.Top && face.Orientation != FaceOrientation.Bottom);
 }
Пример #8
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));
                            }
                        }
                    }
                }
            }
        }
Пример #9
0
        private static void PrepVerticies(
            WorldManager World,
            VoxelHandle Voxel,
            Geo.TemplateFace Face,
            SliceCache Cache,
            int ExploredVertexCount,
            TerrainTileSheet TileSheet,
            Point Tile,
            bool ApplyLighting,
            float explodeOffset)
        {
            for (var vertex = 0; vertex < Face.Mesh.VertexCount; ++vertex) // Blows up if face has more than 4 verticies.
            {
                var lighting = new VertexLighting.VertexColorInfo {
                    AmbientColor = 255, DynamicColor = 255, SunColor = 255
                };

                if (ApplyLighting)
                {
                    lighting = VertexLighting.CalculateVertexLight(Voxel, Face.Mesh.Verticies[vertex].LogicalVertex, World.ChunkManager, Cache);
                }

                var slopeOffset = Vector3.Zero;
                if (Face.Mesh.Verticies[vertex].ApplySlope && ShouldSlope(Face.Mesh.Verticies[vertex].LogicalVertex, Voxel))
                {
                    slopeOffset = new Vector3(0.0f, -0.5f, 0.0f);
                }

                var voxelPosition = Face.Mesh.Verticies[vertex].Position + slopeOffset + Voxel.WorldPosition;
                voxelPosition += VertexNoise.GetNoiseVectorFromRepeatingTexture(voxelPosition);
                voxelPosition += explodeOffset * OrientationHelper.GetFaceNeighborOffset(Face.Orientation).AsVector3();

                if (ExploredVertexCount == 0)
                {
                    Cache.FaceGeometry[vertex] = new ExtendedVertex
                    {
                        Position          = voxelPosition,
                        TextureCoordinate = TileSheet.MapTileUVs(Face.Mesh.Verticies[vertex].TextureCoordinate, BlackTile),
                        TextureBounds     = TileSheet.GetTileBounds(BlackTile),
                        VertColor         = new Color(0.0f, 0.0f, 0.0f, 1.0f),
                        Color             = new Color(0.0f, 0.0f, 0.0f, 1.0f)
                    };
                }
                else
                {
                    var anyNeighborExplored = true;
                    if (!Cache.ExploredCache.TryGetValue(SliceCache.GetCacheKey(Voxel, Face.Mesh.Verticies[vertex].LogicalVertex), out anyNeighborExplored))
                    {
                        anyNeighborExplored = true;
                    }

                    Cache.FaceGeometry[vertex] = new ExtendedVertex
                    {
                        Position          = voxelPosition,
                        TextureCoordinate = TileSheet.MapTileUVs(Face.Mesh.Verticies[vertex].TextureCoordinate, Tile),
                        TextureBounds     = TileSheet.GetTileBounds(Tile),
                        VertColor         = anyNeighborExplored ? new Color(1.0f, 1.0f, 1.0f, 1.0f) : new Color(0.0f, 0.0f, 0.0f, 1.0f),
                        Color             = lighting.AsColor()
                    };
                }
            }
        }