Пример #1
0
        private static void BuildVoxelGeometry(
            RawPrimitive Into,
            int X,
            int Y,
            int Z,
            VoxelChunk Chunk,
            //BoxPrimitive BedrockModel,
            Cache Cache,
            DesignationSet Designations,
            WorldManager World)
        {
            var v = VoxelHandle.UnsafeCreateLocalHandle(Chunk, new LocalVoxelCoordinate(X, Y, Z));

            if (!v.IsValid || !v.IsVisible)
            {
                return;                             // How did this even get called then??
            }
            BuildDesignationGeometry(Into, Chunk, Cache, Designations, World, v);

            if ((v.IsExplored && v.IsEmpty))
            {
                return;
            }
            if (!v.IsExplored && v.Sunlight)
            {
                return;
            }

            if (Library.GetVoxelPrimitive(v.Type).HasValue(out BoxPrimitive primitive))
            {
                BuildVoxelGeometryFromPrimitive(Into, Chunk, Cache, v, primitive);
            }
        }
Пример #2
0
        private static void BuildDesignationGeometry(RawPrimitive Into, VoxelChunk Chunk, Cache Cache, DesignationSet Designations, WorldManager World, VoxelHandle v)
        {
            // Todo: Store designations per chunk.
            foreach (var designation in Designations == null ? new List <DesignationSet.VoxelDesignation>() : Designations.EnumerateDesignations(v).ToList())
            {
                if ((designation.Type & World.Renderer.PersistentSettings.VisibleTypes) != designation.Type) // If hidden by player, do not draw.
                {
                    return;
                }

                var designationProperties = Library.GetDesignationTypeProperties(designation.Type).Value;
                var designationVisible    = false;

                if (designation.Type == DesignationType.Put)
                {
                    designationVisible = v.Coordinate.Y < World.Renderer.PersistentSettings.MaxViewingLevel;
                }
                else
                {
                    designationVisible = VoxelHelpers.DoesVoxelHaveVisibleSurface(World, v);
                }

                if (designationVisible &&
                    Library.GetVoxelPrimitive(Library.DesignationVoxelType).HasValue(out BoxPrimitive designationPrimitive))
                {
                    switch (designationProperties.DrawType)
                    {
                    case DesignationDrawType.FullBox:
                        for (int i = 0; i < 6; i++)
                        {
                            BuildVoxelFaceGeometry(Into, Chunk, Cache, designationPrimitive, v, designationProperties.Color, designationPrimitive.UVs, DesignationTransform, (BoxFace)i, false);
                        }
                        break;

                    case DesignationDrawType.TopBox:
                        BuildVoxelFaceGeometry(Into, Chunk, Cache, designationPrimitive, v, designationProperties.Color, designationPrimitive.UVs, DesignationTransform, 0, false);
                        break;

                    case DesignationDrawType.PreviewVoxel:
                    {
                        if (Library.GetVoxelType(designation.Tag.ToString()).HasValue(out VoxelType voxelType) &&
                            Library.GetVoxelPrimitive(voxelType).HasValue(out BoxPrimitive previewPrimitive))
                        {
                            var offsetMatrix = Matrix.Identity;
                            if (!v.IsEmpty)
                            {
                                offsetMatrix = Matrix.CreateTranslation(0.0f, 0.1f, 0.0f);
                            }
                            for (int i = 0; i < 6; i++)
                            {
                                BuildVoxelFaceGeometry(Into, Chunk, Cache, previewPrimitive, v, designationProperties.Color, previewPrimitive.UVs, offsetMatrix, (BoxFace)i, false);
                            }
                        }
                    }
                    break;
                    }
                }
            }
        }
Пример #3
0
        private static void BuildVoxelGeometry(
            RawPrimitive Into,
            int X,
            int Y,
            int Z,
            VoxelChunk Chunk,
            BoxPrimitive BedrockModel,
            Cache Cache,
            DesignationSet Designations,
            WorldManager World)
        {
            var v = VoxelHandle.UnsafeCreateLocalHandle(Chunk, new LocalVoxelCoordinate(X, Y, Z));

            if (!v.IsValid || !v.IsVisible)
            {
                return;                             // How did this even get called then??
            }
            BuildDesignationGeometry(Into, Chunk, Cache, Designations, World, v);

            if ((v.IsExplored && v.IsEmpty))
            {
                return;
            }

            var primitive = Library.GetVoxelPrimitive(v.Type);

            if (v.IsExplored && primitive == null)
            {
                return;
            }
            if (!v.IsExplored && v.Sunlight)
            {
                return;
            }

            if (primitive == null)
            {
                primitive = BedrockModel;
            }

            var tint = v.Type.Tint;

            var uvs = primitive.UVs;

            if (v.Type.HasTransitionTextures && v.IsExplored)
            {
                uvs = ComputeTransitionTexture(new VoxelHandle(v.Chunk.Manager, v.Coordinate));
            }

            BuildVoxelTopFaceGeometry(Into, Chunk, Cache, primitive, v, uvs, 0);

            for (int i = 1; i < 6; i++)
            {
                BuildVoxelFaceGeometry(Into, Chunk, Cache, primitive, v, tint, uvs, Matrix.Identity, i, true);
            }
        }
Пример #4
0
        private static void BuildDesignationGeometry(RawPrimitive Into, VoxelChunk Chunk, Cache Cache, DesignationSet Designations, WorldManager World, VoxelHandle v)
        {
            var designations    = Designations == null ? new List <DesignationSet.VoxelDesignation>() : Designations.EnumerateDesignations(v).ToList();
            int maxViewingLevel = World.Renderer.PersistentSettings.MaxViewingLevel;

            foreach (var designation in designations)
            {
                if ((designation.Type & World.Renderer.PersistentSettings.VisibleTypes) == designation.Type)
                {
                    var props = Library.GetDesignationTypeProperties(designation.Type);
                    var designationVisible = false;

                    if (designation.Type == DesignationType.Put)
                    {
                        designationVisible = v.Coordinate.Y < maxViewingLevel;
                    }
                    else
                    {
                        designationVisible = VoxelHelpers.DoesVoxelHaveVisibleSurface(World, v);
                    }

                    if (designationVisible)
                    {
                        var desPrim = Library.GetVoxelPrimitive(Library.DesignationVoxelType);
                        switch (props.DrawType)
                        {
                        case DrawBoxType.FullBox:
                            for (int i = 0; i < 6; i++)
                            {
                                BuildVoxelFaceGeometry(Into, Chunk, Cache, desPrim, v, props.Color, desPrim.UVs, DesignationTransform, i, false);
                            }
                            break;

                        case DrawBoxType.TopBox:
                            BuildVoxelFaceGeometry(Into, Chunk, Cache, desPrim, v, props.Color, desPrim.UVs, DesignationTransform, 0, false);
                            break;

                        case DrawBoxType.PreviewVoxel:
                        {
                            var previewPrim  = Library.GetVoxelPrimitive(Library.GetVoxelType(designation.Tag.ToString()));
                            var offsetMatrix = Matrix.Identity;
                            if (!v.IsEmpty)
                            {
                                offsetMatrix = Matrix.CreateTranslation(0.0f, 0.1f, 0.0f);
                            }
                            for (int i = 0; i < 6; i++)
                            {
                                BuildVoxelFaceGeometry(Into, Chunk, Cache, previewPrim, v, props.Color, previewPrim.UVs, offsetMatrix, i, false);
                            }
                        }
                        break;
                        }
                    }
                }
            }
        }
Пример #5
0
 public MeshComponent(
     ComponentManager Manager,
     Matrix localTransform,
     Vector3 boundingBoxExtents,
     Vector3 boundingBoxPos,
     RawPrimitive Mesh,
     String Asset) :
     base(Manager, "primitive", localTransform, boundingBoxExtents, boundingBoxPos)
 {
     this.Mesh  = Mesh;
     this.Asset = Asset;
 }
Пример #6
0
        private static void AddDecalGeometry(
            RawPrimitive Into,
            int[] AmbientScratchSpace,
            BoxPrimitive Primitive,
            VoxelHandle V,
            BoxPrimitive.FaceDescriptor faceDescriptor,
            int exploredVerts,
            Vector3[] VertexPositions,
            VertexColorInfo[] VertexColors,
            Color[] VertexTints,
            DecalType Decal,
            byte Orientation)
        {
            var indexOffset = Into.VertexCount;
            var UV          = new Vector2(Decal.Tile.X * (1.0f / 16.0f), Decal.Tile.Y * (1.0f / 16.0f));
            var UVBounds    = new Vector4(UV.X + 0.001f, UV.Y + 0.001f, UV.X + (1.0f / 16.0f) - 0.001f, UV.Y + (1.0f / 16.0f) - 0.001f);
            var UVs         = new Vector2[faceDescriptor.VertexCount];

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
            {
                var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex];
                UVs[faceVertex] = UV + new Vector2(vertex.Position.X / 16.0f, vertex.Position.Z / 16.0f);
            }

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
            {
                var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex];

                AmbientScratchSpace[faceVertex] = VertexColors[faceVertex].AmbientColor;

                var uv = faceVertex + Orientation;
                uv %= faceDescriptor.VertexCount; // This will only work if the face has 4 verts...

                Into.AddVertex(new ExtendedVertex(
                                   VertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(VertexPositions[faceVertex]),
                                   VertexColors[faceVertex].AsColor(),
                                   VertexTints[faceVertex],
                                   UVs[uv],
                                   UVBounds));
            }

            bool flippedQuad = AmbientScratchSpace[0] + AmbientScratchSpace[2] >
                               AmbientScratchSpace[1] + AmbientScratchSpace[3];

            for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount +
                 faceDescriptor.IndexOffset; idx++)
            {
                ushort offset  = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx];
                ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset];
                Into.AddIndex((short)(indexOffset + offset - offset0));
            }
        }
Пример #7
0
 private static void BuildSliceGeometry(
     VoxelChunk chunk,
     BoxPrimitive bedrockModel,
     Cache Cache,
     int y,
     RawPrimitive sliceGeometry)
 {
     for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x)
     {
         for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z)
         {
             BuildVoxelGeometry(sliceGeometry,
                                x, y, z, chunk, bedrockModel, Cache);
         }
     }
 }
Пример #8
0
        private static void BuildVoxelGeometryFromPrimitive(RawPrimitive Into, VoxelChunk Chunk, Cache Cache, VoxelHandle v, BoxPrimitive primitive)
        {
            var tint = v.Type.Tint;
            var uvs  = primitive.UVs;

            if (v.Type.HasTransitionTextures && v.IsExplored)
            {
                uvs = ComputeTransitionTexture(new VoxelHandle(v.Chunk.Manager, v.Coordinate));
            }

            BuildVoxelTopFaceGeometry(Into, Chunk, Cache, primitive, v, uvs);

            for (int i = 1; i < 6; i++)
            {
                BuildVoxelFaceGeometry(Into, Chunk, Cache, primitive, v, tint, uvs, Matrix.Identity, (BoxFace)i, true);
            }
        }
Пример #9
0
 private static void BuildSliceGeometry(
     VoxelChunk chunk,
     BoxPrimitive bedrockModel,
     Cache Cache,
     int LocalY,
     RawPrimitive sliceGeometry,
     DesignationSet DesignationSet,
     WorldManager World)
 {
     for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x)
     {
         for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z)
         {
             BuildVoxelGeometry(sliceGeometry, x, LocalY, z, chunk, bedrockModel, Cache, DesignationSet, World);
         }
     }
 }
Пример #10
0
        private static void BuildVoxelGeometry(
            RawPrimitive Into,
            int X,
            int Y,
            int Z,
            VoxelChunk Chunk,
            BoxPrimitive BedrockModel,
            Cache Cache)
        {
            var v = new VoxelHandle(Chunk, new LocalVoxelCoordinate(X, Y, Z));

            if ((v.IsExplored && v.IsEmpty) || !v.IsVisible)
            {
                return;
            }

            var primitive = VoxelLibrary.GetPrimitive(v.Type);

            if (v.IsExplored && primitive == null)
            {
                return;
            }

            if (primitive == null)
            {
                primitive = BedrockModel;
            }

            var tint = v.Type.Tint;

            var uvs = primitive.UVs;

            if (v.Type.HasTransitionTextures && v.IsExplored)
            {
                uvs = ComputeTransitionTexture(new VoxelHandle(v.Chunk.Manager.ChunkData, v.Coordinate));
            }

            BuildVoxelTopFaceGeometry(Into,
                                      Chunk, Cache, primitive, v, uvs, 0);
            for (int i = 1; i < 6; i++)
            {
                BuildVoxelFaceGeometry(Into, Chunk,
                                       Cache, primitive, v, tint, uvs, i);
            }
        }
Пример #11
0
        public override void CreateCosmeticChildren(ComponentManager Manager)
        {
            base.CreateCosmeticChildren(Manager);

            if (SharedMesh == null)
            {
                SharedMesh = AssetManager.GetContentMesh("Entities/Furniture/sm_anvil");
            }

            AddChild(new MeshComponent(Manager,
                                       Matrix.CreateRotationY(0.25f),
                                       new Vector3(1.0f, 1.0f, 1.0f),
                                       new Vector3(0.0f, 0.0f, 0.0f),
                                       SharedMesh,
                                       "Entities/Furniture/tx_anvil"))
            .SetFlag(Flag.ShouldSerialize, false)
            .SetFlag(Flag.RotateBoundingBox, true);
        }
Пример #12
0
        private static void BuildDecalGeometry(
            RawPrimitive Into,
            VoxelChunk Chunk,
            Cache Cache,
            BoxPrimitive Primitive,
            VoxelHandle V,
            VertexColorInfo[] VertexColors,
            Color[] VertexTint,
            Vector3[] VertexPositions,
            BoxPrimitive.FaceDescriptor Face,
            int ExploredVerts)
        {
            if (V.DecalType == 0)
            {
                return;
            }

            var decalType = Library.GetDecalType(V.DecalType);

            AddDecalGeometry(Into, Cache.AmbientValues, Primitive, Face, ExploredVerts, VertexPositions, VertexColors, VertexTint, decalType);
        }
Пример #13
0
        private static void AddGrassGeometry(
            RawPrimitive Into,
            int[] AmbientScratchSpace,
            BoxPrimitive Primitive,
            BoxPrimitive.FaceDescriptor faceDescriptor,
            Vector3[] VertexPositions,
            VertexColorInfo[] VertexColors,
            Color[] VertexTints,
            GrassType Decal)
        {
            var indexOffset = Into.VertexCount;
            var UV          = new Vector2(Decal.Tile.X * (1.0f / 16.0f), Decal.Tile.Y * (1.0f / 16.0f));
            var UVBounds    = new Vector4(UV.X + 0.001f, UV.Y + 0.001f, UV.X + (1.0f / 16.0f) - 0.001f, UV.Y + (1.0f / 16.0f) - 0.001f);

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
            {
                var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex];

                AmbientScratchSpace[faceVertex] = VertexColors[faceVertex].AmbientColor;

                Into.AddVertex(new ExtendedVertex(
                                   VertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(VertexPositions[faceVertex]),
                                   VertexColors[faceVertex].AsColor(),
                                   VertexTints[faceVertex],
                                   UV + new Vector2(vertex.Position.X / 16.0f, vertex.Position.Z / 16.0f),
                                   UVBounds));
            }

            bool flippedQuad = (AmbientScratchSpace[0] + AmbientScratchSpace[2]) > (AmbientScratchSpace[1] + AmbientScratchSpace[3]);

            for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount + faceDescriptor.IndexOffset; ++idx)
            {
                ushort offset  = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx];
                ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset];
                Into.AddIndex((short)(indexOffset + offset - offset0));
            }
        }
Пример #14
0
        private static void BuildVoxelFaceGeometry(
            RawPrimitive Into,
            VoxelChunk Chunk,
            Cache Cache,
            BoxPrimitive Primitive,
            VoxelHandle V,
            Color Tint,
            BoxPrimitive.BoxTextureCoords UVs,
            Matrix VertexTransform,
            int i,
            bool ApplyLighting)
        {
            var face  = (BoxFace)i;
            var delta = FaceDeltas[i];

            var faceVoxel = new VoxelHandle(Chunk.Manager, V.Coordinate + GlobalVoxelOffset.FromVector3(delta));

            if (!IsFaceVisible(V, faceVoxel, face))
            {
                return;
            }

            var faceDescriptor = Primitive.GetFace(face);
            var indexOffset    = Into.VertexCount;

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
            {
                var vertex      = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex];
                var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex];
                var vertexColor = new VertexColorInfo
                {
                    SunColor     = 255,
                    AmbientColor = 255,
                    DynamicColor = 255,
                };

                if (ApplyLighting)
                {
                    var cacheKey = GetCacheKey(V, voxelVertex);

                    if (!Cache.LightCache.TryGetValue(cacheKey, out vertexColor))
                    {
                        vertexColor = CalculateVertexLight(V, voxelVertex, Chunk.Manager);
                        Cache.LightCache.Add(cacheKey, vertexColor);
                    }

                    Cache.AmbientValues[faceVertex] = vertexColor.AmbientColor;
                }

                var rampOffset = Vector3.Zero;
                if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType))
                {
                    rampOffset = new Vector3(0, -V.Type.RampSize, 0);
                }

                var baseWorldPosition = V.WorldPosition + vertex.Position + rampOffset;
                var noise             = VertexNoise.GetNoiseVectorFromRepeatingTexture(baseWorldPosition);
                var localPosition     = Vector3.Transform(vertex.Position + rampOffset + noise, VertexTransform);

                Into.AddVertex(new ExtendedVertex(
                                   V.WorldPosition + localPosition,
                                   vertexColor.AsColor(),
                                   Tint,
                                   UVs.Uvs[faceDescriptor.VertexOffset + faceVertex],
                                   UVs.Bounds[faceDescriptor.IndexOffset / 6]));
            }

            bool flippedQuad = ApplyLighting && (Cache.AmbientValues[0] + Cache.AmbientValues[2] >
                                                 Cache.AmbientValues[1] + Cache.AmbientValues[3]);

            for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount +
                 faceDescriptor.IndexOffset; idx++)
            {
                ushort offset  = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx];
                ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset];
                Into.AddIndex((short)(indexOffset + offset - offset0));
            }
        }
Пример #15
0
        private static void BuildVoxelTopFaceGeometry(
            RawPrimitive Into,
            VoxelChunk Chunk,
            Cache Cache,
            BoxPrimitive Primitive,
            VoxelHandle V,
            BoxPrimitive.BoxTextureCoords UVs,
            int i)
        {
            var face  = (BoxFace)i;
            var delta = FaceDeltas[i];

            var faceVoxel = new VoxelHandle(Chunk.Manager, V.Coordinate + GlobalVoxelOffset.FromVector3(delta));

            if (!IsFaceVisible(V, faceVoxel, face))
            {
                return;
            }

            var faceDescriptor = Primitive.GetFace(face);
            int exploredVerts  = 0;
            var vertexColors   = new VertexColorInfo[4];
            var vertexTint     = new Color[4];

            // Find all verticies to use for geometry later, and for the fringe
            var vertexPositions = new Vector3[4];

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
            {
                var vertex      = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex];
                var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex];

                var rampOffset = Vector3.Zero;
                if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType))
                {
                    rampOffset = new Vector3(0, -V.Type.RampSize, 0);
                }

                var worldPosition = V.WorldPosition + vertex.Position + rampOffset;
                //worldPosition += VertexNoise.GetNoiseVectorFromRepeatingTexture(worldPosition);

                vertexPositions[faceVertex] = worldPosition;
            }

            if (V.IsExplored)
            {
                exploredVerts = 4;
            }
            else
            {
                for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; ++faceVertex)
                {
                    var  voxelVertex         = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex];
                    var  cacheKey            = GetCacheKey(V, voxelVertex);
                    bool anyNeighborExplored = true;

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


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

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; ++faceVertex)
            {
                var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex];
                var cacheKey    = GetCacheKey(V, voxelVertex);

                VertexColorInfo vertexColor;
                if (!Cache.LightCache.TryGetValue(cacheKey, out vertexColor))
                {
                    vertexColor = CalculateVertexLight(V, voxelVertex, Chunk.Manager);
                    Cache.LightCache.Add(cacheKey, vertexColor);
                }

                vertexColors[faceVertex] = vertexColor;

                vertexTint[faceVertex] = new Color(1.0f, 1.0f, 1.0f, 1.0f);
                if (exploredVerts != 4)
                {
                    bool anyNeighborExplored = true;
                    if (!Cache.ExploredCache.TryGetValue(cacheKey, out anyNeighborExplored))
                    {
                        throw new InvalidProgramException("Failed cache lookup");
                    }

                    if (!anyNeighborExplored)
                    {
                        vertexTint[faceVertex] = new Color(0.0f, 0.0f, 0.0f, 1.0f);
                    }
                }

                vertexTint[faceVertex] = new Color(vertexTint[faceVertex].ToVector4() * V.Type.Tint.ToVector4());
            }

            if (exploredVerts != 0)
            {
                var baseUVs = UVs.Uvs[11]; // EW

                var baseUVBounds = new Vector4(baseUVs.X + 0.001f, baseUVs.Y + 0.001f, baseUVs.X + (1.0f / 16.0f) - 0.001f, baseUVs.Y + (1.0f / 16.0f) - 0.001f);

                // Draw central top tile.
                AddTopFaceGeometry(Into,
                                   Cache.AmbientValues, Primitive,
                                   faceDescriptor,
                                   vertexPositions,
                                   vertexColors,
                                   vertexTint,
                                   Vector2.One,
                                   baseUVs, baseUVBounds);

                if (V.GrassType != 0)
                {
                    BuildGrassFringeGeometry(Into, Chunk, Cache, Primitive, V, vertexColors,
                                             vertexTint, vertexPositions, faceDescriptor, exploredVerts);
                }
            }
            else
            {
                if (!Debugger.Switches.HideSliceTop)
                {
                    var indexOffset = Into.VertexCount;

                    for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
                    {
                        Into.AddVertex(new ExtendedVertex(
                                           vertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(vertexPositions[faceVertex]),
                                           new Color(0, 0, 0, 255),
                                           new Color(0, 0, 0, 255),
                                           new Vector2(12.5f / 16.0f, 0.5f / 16.0f),
                                           new Vector4(12.0f / 16.0f, 0.0f, 13.0f / 16.0f, 1.0f / 16.0f)));
                    }

                    for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount +
                         faceDescriptor.IndexOffset; idx++)
                    {
                        ushort offset  = Primitive.Indexes[idx];
                        ushort offset0 = Primitive.Indexes[faceDescriptor.IndexOffset];
                        Into.AddIndex((short)(indexOffset + offset - offset0));
                    }
                }
            }
        }
Пример #16
0
        private static void BuildVoxelFaceGeometry(
            RawPrimitive Into,
            VoxelChunk Chunk,
            Cache Cache,
            BoxPrimitive Primitive,
            VoxelHandle V,
            Color Tint,
            BoxPrimitive.BoxTextureCoords UVs,
            Matrix VertexTransform,
            BoxFace BoxFace,
            bool ApplyLighting)
        {
            if (!IsFaceVisible(V, BoxFace, Chunk.Manager, out var neighbor))
            {
                return;
            }

            var faceDescriptor = Primitive.GetFace(BoxFace);
            var indexOffset    = Into.VertexCount;

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
            {
                var vertex      = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex];
                var voxelVertex = Primitive.VertexClassifications[faceDescriptor.VertexOffset + faceVertex];
                var vertexColor = new VertexColorInfo
                {
                    SunColor     = 255,
                    AmbientColor = 255,
                    DynamicColor = 255,
                };

                if (ApplyLighting)
                {
                    var cacheKey = GetCacheKey(V, voxelVertex);

                    if (!Cache.LightCache.TryGetValue(cacheKey, out vertexColor))
                    {
                        vertexColor = CalculateVertexLight(V, voxelVertex, Chunk.Manager);
                        Cache.LightCache.Add(cacheKey, vertexColor);
                    }

                    Cache.AmbientValues[faceVertex] = vertexColor.AmbientColor;

                    if (!V.IsExplored && !neighbor.IsValid) // Turns the outside of the world black when it's not explored.
                    {
                        Tint = new Color(0.0f, 0.0f, 0.0f, 1.0f);
                    }
                }

                var rampOffset = Vector3.Zero;
                if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType))
                {
                    rampOffset = new Vector3(0, -0.5f, 0);
                }

                var baseWorldPosition = V.WorldPosition + vertex.Position + rampOffset;
                var noise             = VertexNoise.GetNoiseVectorFromRepeatingTexture(baseWorldPosition);
                var localPosition     = Vector3.Transform(vertex.Position + rampOffset + noise, VertexTransform);

                Into.AddVertex(new ExtendedVertex(
                                   V.WorldPosition + localPosition,
                                   vertexColor.AsColor(),
                                   Tint,
                                   UVs.Uvs[faceDescriptor.VertexOffset + faceVertex],
                                   UVs.Bounds[faceDescriptor.IndexOffset / 6]));
            }

            // Sometimes flip the quad to smooth out lighting.
            bool flippedQuad = ApplyLighting && (Cache.AmbientValues[0] + Cache.AmbientValues[2] >
                                                 Cache.AmbientValues[1] + Cache.AmbientValues[3]);

            for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount +
                 faceDescriptor.IndexOffset; idx++)
            {
                ushort offset  = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx];
                ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset];
                Into.AddIndex((short)(indexOffset + offset - offset0));
            }
        }
Пример #17
0
        private static void BuildVoxelTopFaceGeometry(
            RawPrimitive Into,
            VoxelChunk Chunk,
            Cache Cache,
            BoxPrimitive Primitive,
            VoxelHandle V,
            BoxPrimitive.BoxTextureCoords UVs)
        {
            if (!IsFaceVisible(V, BoxFace.Top, Chunk.Manager, out var _))
            {
                return;
            }

            var faceDescriptor = Primitive.GetFace(BoxFace.Top);
            int exploredVerts  = 0;
            var vertexColors   = new VertexColorInfo[4];
            var vertexTint     = new Color[4];

            // Find all verticies to use for geometry later, and for the fringe
            var vertexPositions = new Vector3[4];

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
            {
                var vertex      = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex];
                var voxelVertex = Primitive.VertexClassifications[faceDescriptor.VertexOffset + faceVertex];

                var rampOffset = Vector3.Zero;
                if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType))
                {
                    rampOffset = new Vector3(0, -0.5f, 0);
                }

                var worldPosition = V.WorldPosition + vertex.Position + rampOffset;
                //worldPosition += VertexNoise.GetNoiseVectorFromRepeatingTexture(worldPosition);

                vertexPositions[faceVertex] = worldPosition;
            }

            // Figure out if this vertex is adjacent to any explored voxel.
            if (V.IsExplored)
            {
                exploredVerts = 4;
            }
            else
            {
                for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; ++faceVertex)
                {
                    var voxelVertex         = Primitive.VertexClassifications[faceDescriptor.VertexOffset + faceVertex];
                    var cacheKey            = GetCacheKey(V, voxelVertex);
                    var anyNeighborExplored = true;

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

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

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; ++faceVertex)
            {
                var voxelVertex = Primitive.VertexClassifications[faceDescriptor.VertexOffset + faceVertex];
                var cacheKey    = GetCacheKey(V, voxelVertex);

                VertexColorInfo vertexColor;
                if (!Cache.LightCache.TryGetValue(cacheKey, out vertexColor))
                {
                    vertexColor = CalculateVertexLight(V, voxelVertex, Chunk.Manager);
                    Cache.LightCache.Add(cacheKey, vertexColor);
                }

                vertexColors[faceVertex] = vertexColor;

                vertexTint[faceVertex] = new Color(1.0f, 1.0f, 1.0f, 1.0f);

                // Turn face solid black if there are no explored neighbors - this is an optimization; it means we do not need to apply a solid black decal.
                if (exploredVerts != 4)
                {
                    var anyNeighborExplored = true;
                    if (!Cache.ExploredCache.TryGetValue(cacheKey, out anyNeighborExplored))
                    {
                        throw new InvalidProgramException("Failed cache lookup");
                    }

                    if (!anyNeighborExplored)
                    {
                        vertexTint[faceVertex] = new Color(0.0f, 0.0f, 0.0f, 1.0f);
                    }
                }

                vertexTint[faceVertex] = new Color(vertexTint[faceVertex].ToVector4() * V.Type.Tint.ToVector4());
            }

            if (exploredVerts != 0)
            {
                var baseUVs = UVs.Uvs[11]; // EW

                var baseUVBounds = new Vector4(baseUVs.X + 0.001f, baseUVs.Y + 0.001f, baseUVs.X + (1.0f / 16.0f) - 0.001f, baseUVs.Y + (1.0f / 16.0f) - 0.001f);

                // Draw the base voxel
                AddTopFaceGeometry(Into,
                                   Cache.AmbientValues, Primitive,
                                   faceDescriptor,
                                   vertexPositions,
                                   vertexColors,
                                   vertexTint,
                                   Vector2.One,
                                   baseUVs, baseUVBounds);

                if (V.GrassType != 0)
                {
                    BuildGrassFringeGeometry(Into, Chunk, Cache, Primitive, V, vertexColors, vertexTint, vertexPositions, faceDescriptor);
                }

                if (V.DecalType != 0)
                {
                    BuildDecalGeometry(Into, Chunk, Cache, Primitive, V, vertexColors, vertexTint, vertexPositions, faceDescriptor, exploredVerts);
                }
            }
            else
            {
                // Apparently being unexplored hides all grass and decals. Is that the behavior we actually want?

                if (!Debugger.Switches.HideSliceTop)
                {
                    var indexOffset = Into.VertexCount;

                    for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
                    {
                        Into.AddVertex(new ExtendedVertex(
                                           vertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(vertexPositions[faceVertex]),
                                           new Color(0, 0, 0, 255),
                                           new Color(0, 0, 0, 255),
                                           new Vector2(12.5f / 16.0f, 0.5f / 16.0f),
                                           new Vector4(12.0f / 16.0f, 0.0f, 13.0f / 16.0f, 1.0f / 16.0f)));
                    }

                    for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount +
                         faceDescriptor.IndexOffset; idx++)
                    {
                        ushort offset  = Primitive.Indexes[idx];
                        ushort offset0 = Primitive.Indexes[faceDescriptor.IndexOffset];
                        Into.AddIndex((short)(indexOffset + offset - offset0));
                    }
                }
            }
        }
Пример #18
0
        public void InitializeFromChunk(VoxelChunk chunk)
        {
            if (chunk == null)
            {
                return;
            }

            BoxPrimitive bedrockModel = VoxelLibrary.GetPrimitive("Bedrock");
            var          sliceStack   = new List <RawPrimitive>();
            var          cache        = new Cache();

            for (var y = 0; y < chunk.Manager.ChunkData.MaxViewingLevel; ++y)
            {
                RawPrimitive sliceGeometry = null;

                lock (chunk.Data.SliceCache)
                {
                    var cachedSlice = chunk.Data.SliceCache[y];

                    if (chunk.Data.VoxelsPresentInSlice[y] == 0)
                    {
                        cache.Clear();

                        if (cachedSlice != null)
                        {
                            chunk.Data.SliceCache[y] = null;
                        }
                        continue;
                    }

                    if (cachedSlice != null)
                    {
                        cache.Clear();

                        sliceStack.Add(cachedSlice);

                        if (GameSettings.Default.GrassMotes)
                        {
                            chunk.RebuildMoteLayerIfNull(y);
                        }

                        continue;
                    }

                    sliceGeometry = new RawPrimitive
                    {
                        Vertices = new ExtendedVertex[128],
                        Indexes  = new short[128]
                    };

                    chunk.Data.SliceCache[y] = sliceGeometry;
                }

                if (GameSettings.Default.CalculateRamps)
                {
                    UpdateCornerRamps(chunk, y);
                    UpdateNeighborEdgeRamps(chunk, y);
                }

                if (GameSettings.Default.GrassMotes)
                {
                    chunk.RebuildMoteLayer(y);
                }

                BuildSliceGeometry(chunk, bedrockModel, cache, y, sliceGeometry);

                sliceStack.Add(sliceGeometry);
            }

            var combinedGeometry = RawPrimitive.Concat(sliceStack);

            Vertices    = combinedGeometry.Vertices;
            VertexCount = combinedGeometry.VertexCount;
            Indexes     = combinedGeometry.Indexes.Select(s => (ushort)s).ToArray();
            IndexCount  = combinedGeometry.IndexCount;

            chunk.PrimitiveMutex.WaitOne();
            chunk.NewPrimitive         = this;
            chunk.NewPrimitiveReceived = true;
            chunk.PrimitiveMutex.ReleaseMutex();
        }
Пример #19
0
        public void InitializeFromChunk(VoxelChunk chunk, DesignationSet DesignationSet, WorldManager World)
        {
            DebugHelper.AssertNotNull(chunk);
            DebugHelper.AssertNotNull(DesignationSet);
            DebugHelper.AssertNotNull(World);

            BoxPrimitive bedrockModel    = Library.GetVoxelPrimitive("Bedrock");
            var          sliceStack      = new List <RawPrimitive>();
            var          cache           = new Cache();
            int          maxViewingLevel = World.Renderer.PersistentSettings.MaxViewingLevel;

            for (var localY = 0; localY < maxViewingLevel - chunk.Origin.Y && localY < VoxelConstants.ChunkSizeY; ++localY) // Todo: Only iterate inside the chunk.
            {
                RawPrimitive sliceGeometry = null;

                lock (chunk.Data.SliceCache)
                {
                    var cachedSlice = chunk.Data.SliceCache[localY];

                    if (cachedSlice != null)
                    {
                        cache.Clear();

                        sliceStack.Add(cachedSlice);

                        if (GameSettings.Default.GrassMotes)
                        {
                            chunk.RebuildMoteLayerIfNull(localY);
                        }

                        continue;
                    }

                    sliceGeometry = new RawPrimitive
                    {
                        Vertices = null,
                        Indexes  = null
                    };

                    chunk.Data.SliceCache[localY] = sliceGeometry;
                }

                if (GameSettings.Default.CalculateRamps)
                {
                    UpdateCornerRamps(World.ChunkManager, chunk, localY);
                    UpdateNeighborEdgeRamps(World.ChunkManager, chunk, localY);
                }

                if (GameSettings.Default.GrassMotes)
                {
                    chunk.RebuildMoteLayer(localY);
                }

                DebugHelper.AssertNotNull(sliceGeometry);
                BuildSliceGeometry(chunk, bedrockModel, cache, localY, sliceGeometry, DesignationSet, World);

                sliceStack.Add(sliceGeometry);
            }

            var combinedGeometry = RawPrimitive.Concat(sliceStack);

            Vertices    = combinedGeometry.Vertices;
            VertexCount = combinedGeometry.VertexCount;
            Indexes     = combinedGeometry.Indexes.Select(s => (ushort)s).ToArray();
            IndexCount  = combinedGeometry.IndexCount;
        }
Пример #20
0
        public static RawPrimitive LoadObject(string[] File)
        {
            var parser    = new ObjLineGrammar();
            var verticies = new List <Vector3>();
            var texCoords = new List <Vector2>();
            var faces     = new List <Face>();

            foreach (var line in File)
            {
                if (String.IsNullOrEmpty(line))
                {
                    continue;
                }
                if (line.StartsWith("#"))
                {
                    continue;
                }

                var result = parser.ParseString(line);
                if (result.ResultType != Ancora.ResultType.Success)
                {
                    continue;
                }

                switch (result.Node.Children[0].Value.ToString())
                {
                case "v":
                    verticies.Add(new Vector3((float)result.Node.Children[1].Value, (float)result.Node.Children[2].Value, (float)result.Node.Children[3].Value));
                    break;

                case "vt":
                    texCoords.Add(new Vector2((float)result.Node.Children[1].Value, 1.0f - (float)result.Node.Children[2].Value));
                    break;

                case "f":
                {
                    var f = new Face();
                    for (var i = 1; i < result.Node.Children.Count; i += 3)
                    {
                        f.Add(new Corner {
                                Vertex = (int)(float)result.Node.Children[i].Value, TexCoord = (int)(float)result.Node.Children[i + 2].Value
                            });
                    }
                    faces.Add(f);
                }
                break;

                default:
                    break;
                }
            }

            var r = new RawPrimitive();

            foreach (var face in faces)
            {
                for (var i = 2; i < face.Count; ++i)
                {
                    r.AddTriangle(
                        new ExtendedVertex(verticies[face[0].Vertex - 1], Color.White, Color.White, texCoords[face[0].TexCoord - 1], new Vector4(0, 0, 1, 1)),
                        new ExtendedVertex(verticies[face[i - 1].Vertex - 1], Color.White, Color.White, texCoords[face[i - 1].TexCoord - 1], new Vector4(0, 0, 1, 1)),
                        new ExtendedVertex(verticies[face[i].Vertex - 1], Color.White, Color.White, texCoords[face[i].TexCoord - 1], new Vector4(0, 0, 1, 1)));
                }
            }

            return(r);
        }