private static bool ShouldRamp(VoxelVertex vertex, RampType rampType)
        {
            bool toReturn = false;

            if ((rampType & RampType.TopFrontRight) == RampType.TopFrontRight)
            {
                toReturn = (vertex == VoxelVertex.FrontTopRight);
            }

            if ((rampType & RampType.TopBackRight) == RampType.TopBackRight)
            {
                toReturn = toReturn || (vertex == VoxelVertex.BackTopRight);
            }

            if ((rampType & RampType.TopFrontLeft) == RampType.TopFrontLeft)
            {
                toReturn = toReturn || (vertex == VoxelVertex.FrontTopLeft);
            }

            if ((rampType & RampType.TopBackLeft) == RampType.TopBackLeft)
            {
                toReturn = toReturn || (vertex == VoxelVertex.BackTopLeft);
            }

            return(toReturn);
        }
        public static bool ShouldSlope(VoxelVertex vertex, VoxelHandle Voxel)
        {
            bool toReturn = false;

            if ((Voxel.RampType & RampType.TopFrontRight) == RampType.TopFrontRight)
            {
                toReturn = (vertex == VoxelVertex.FrontTopRight);
            }

            if ((Voxel.RampType & RampType.TopBackRight) == RampType.TopBackRight)
            {
                toReturn = toReturn || (vertex == VoxelVertex.BackTopRight);
            }

            if ((Voxel.RampType & RampType.TopFrontLeft) == RampType.TopFrontLeft)
            {
                toReturn = toReturn || (vertex == VoxelVertex.FrontTopLeft);
            }

            if ((Voxel.RampType & RampType.TopBackLeft) == RampType.TopBackLeft)
            {
                toReturn = toReturn || (vertex == VoxelVertex.BackTopLeft);
            }

            return(toReturn);
        }
示例#3
0
        public static bool ShouldRamp(VoxelVertex vertex, RampType rampType)
        {
            bool toReturn = false;

            if (Voxel.HasFlag(rampType, RampType.TopFrontRight))
            {
                toReturn = (vertex == VoxelVertex.BackTopRight);
            }

            if (Voxel.HasFlag(rampType, RampType.TopBackRight))
            {
                toReturn = toReturn || (vertex == VoxelVertex.FrontTopRight);
            }

            if (Voxel.HasFlag(rampType, RampType.TopFrontLeft))
            {
                toReturn = toReturn || (vertex == VoxelVertex.BackTopLeft);
            }

            if (Voxel.HasFlag(rampType, RampType.TopBackLeft))
            {
                toReturn = toReturn || (vertex == VoxelVertex.FrontTopLeft);
            }


            return(toReturn);
        }
示例#4
0
        public static bool ShouldRamp(VoxelVertex vertex, RampType rampType)
        {
            bool toReturn = false;

            if(Voxel.HasFlag(rampType, RampType.TopFrontRight))
            {
                toReturn = (vertex == VoxelVertex.BackTopRight);
            }

            if(Voxel.HasFlag(rampType, RampType.TopBackRight))
            {
                toReturn = toReturn || (vertex == VoxelVertex.FrontTopRight);
            }

            if(Voxel.HasFlag(rampType, RampType.TopFrontLeft))
            {
                toReturn = toReturn || (vertex == VoxelVertex.BackTopLeft);
            }

            if(Voxel.HasFlag(rampType, RampType.TopBackLeft))
            {
                toReturn = toReturn || (vertex == VoxelVertex.FrontTopLeft);
            }

            return toReturn;
        }
示例#5
0
        public static VertexColorInfo CalculateVertexLight(VoxelHandle Vox, VoxelVertex Vertex, ChunkManager Chunks, SliceCache Cache)
        {
            var r = new VertexColorInfo();

            var cacheKey = SliceCache.GetCacheKey(Vox, Vertex);

            if (!Cache.LightCache.TryGetValue(cacheKey, out r))
            {
                r = CalculateVertexLight(Vox, Vertex, Chunks);
                Cache.LightCache.Add(cacheKey, r);
            }

            return(r);
        }
示例#6
0
 public BoxPrimitive(GraphicsDevice device, float width, float height, float depth, BoxTextureCoords uvs)
 {
     Width  = width;
     Height = height;
     Depth  = depth;
     Deltas = new VoxelVertex[NumVertices];
     UVs    = uvs;
     CreateVerticies();
     ResetBuffer(device);
     BoundingBox = new BoundingBox(new Vector3(0.0f, 0.0f, 0.0f), new Vector3(width, height, depth));
     for (int i = 0; i < NumVertices; i++)
     {
         Deltas[i] = VoxelChunk.GetNearestDelta(Vertices[i].Position);
     }
 }
示例#7
0
 private static bool IsBottom(VoxelVertex vertex)
 {
     switch (vertex)
     {
         case VoxelVertex.BackBottomLeft:
             return true;
         case VoxelVertex.BackBottomRight:
             return true;
         case VoxelVertex.FrontBottomLeft:
             return true;
         case VoxelVertex.FrontBottomRight:
             return true;
         default:
             return false;
     }
     
 }
示例#8
0
        private static float GetAmbienceBoost(VoxelVertex vertex)
        {
            switch (vertex)
            {
            case VoxelVertex.FrontTopLeft:
            case VoxelVertex.FrontTopRight:
            case VoxelVertex.BackTopLeft:
            case VoxelVertex.BackTopRight:
                return(0.25f);

            case VoxelVertex.BackBottomRight:
            case VoxelVertex.FrontBottomRight:
                return(0.15f);

            default:
                return(0.0f);
            }
        }
示例#9
0
        public static VertexColorInfo CalculateVertexLight(VoxelHandle Vox, VoxelVertex Vertex, ChunkManager chunks)
        {
            var neighborsEmpty   = 0;
            var neighborsChecked = 0;

            var color = new VertexColorInfo();

            color.DynamicColor = 0;
            color.SunColor     = 0;

            foreach (var c in VoxelHelpers.EnumerateVertexNeighbors(Vox.Coordinate, Vertex))
            {
                var v = chunks.CreateVoxelHandle(c);
                if (!v.IsValid)
                {
                    continue;
                }

                color.SunColor += v.Sunlight ? 255 : 0;

                if (!v.IsEmpty || !v.IsExplored)
                {
                    if (v.Type.EmitsLight)
                    {
                        color.DynamicColor = 255;
                    }

                    neighborsEmpty   += 1;
                    neighborsChecked += 1;
                }
                else
                {
                    neighborsChecked += 1;
                }
            }

            var boost         = GetAmbienceBoost(Vertex);
            var proportionHit = (float)neighborsEmpty / (float)neighborsChecked;

            color.AmbientColor = (int)Math.Min((1.0f - proportionHit) * 255.0f, 255);
            color.SunColor     = (int)Math.Min((float)color.SunColor / (float)neighborsChecked + boost * 255.0f, 255);

            return(color);
        }
示例#10
0
        private static VoxelVertex GetNearestDelta(Vector3 position)
        {
            InitializeDeltas();

            float       bestDist = float.MaxValue;
            VoxelVertex bestKey  = 0;

            for (int i = 0; i < 8; i++)
            {
                float dist = (position - vertexDeltas[i]).LengthSquared();
                if (dist < bestDist)
                {
                    bestDist = dist;
                    bestKey  = (VoxelVertex)(i);
                }
            }

            return(bestKey);
        }
示例#11
0
        private static VoxelVertex GetNearestDelta(Vector3 position)
        {
            InitializeVoxelVertexDeltas();

            var         shortestDistance   = float.MaxValue;
            VoxelVertex closestVoxelVertex = 0;

            for (int i = 0; i < 8; i++)
            {
                var distance = (position - VoxelVertexDeltas[i]).LengthSquared();
                if (distance < shortestDistance)
                {
                    shortestDistance   = distance;
                    closestVoxelVertex = (VoxelVertex)(i);
                }
            }

            return(closestVoxelVertex);
        }
示例#12
0
        private static GlobalVoxelCoordinate GetCacheKey(VoxelHandle Handle, VoxelVertex Vertex)
        {
            var coord = Handle.Coordinate;

            if ((Vertex & VoxelVertex.Front) == VoxelVertex.Front)
            {
                coord = new GlobalVoxelCoordinate(coord.X, coord.Y, coord.Z + 1);
            }

            if ((Vertex & VoxelVertex.Top) == VoxelVertex.Top)
            {
                coord = new GlobalVoxelCoordinate(coord.X, coord.Y + 1, coord.Z);
            }

            if ((Vertex & VoxelVertex.Right) == VoxelVertex.Right)
            {
                coord = new GlobalVoxelCoordinate(coord.X + 1, coord.Y, coord.Z);
            }

            return(coord);
        }
示例#13
0
 public static bool IsTopVertex(VoxelVertex v)
 {
     return(v == VoxelVertex.BackTopLeft || v == VoxelVertex.FrontTopLeft || v == VoxelVertex.FrontTopRight || v == VoxelVertex.BackTopRight);
 }
示例#14
0
        public void InitializeFromChunk(VoxelChunk chunk, GraphicsDevice graphics)
        {
            if (chunk == null)
            {
                return;
            }

            rebuildMutex.WaitOne();
            if (isRebuilding)
            {
                rebuildMutex.ReleaseMutex();
                return;
            }

            isRebuilding = true;
            rebuildMutex.ReleaseMutex();


            accumulatedVertices.Clear();
            accumulatedIndices.Clear();
            faceExists.Clear();
            drawFace.Clear();

            Voxel v           = chunk.MakeVoxel(0, 0, 0);
            Voxel voxelOnFace = chunk.MakeVoxel(0, 0, 0);

            Voxel[] manhattanNeighbors = new Voxel[4];
            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int y = 0; y < Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, chunk.SizeY); y++)
                {
                    for (int z = 0; z < chunk.SizeZ; z++)
                    {
                        v.GridPosition = new Vector3(x, y, z);


                        if (v.IsEmpty || !v.IsVisible)
                        {
                            continue;
                        }

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

                        if (primitive == null)
                        {
                            continue;
                        }

                        BoxPrimitive.BoxTextureCoords uvs = primitive.UVs;

                        if (v.Type.HasTransitionTextures)
                        {
                            uvs = v.ComputeTransitionTexture(manhattanNeighbors);
                        }


                        Voxel worldVoxel = new Voxel();
                        for (int i = 0; i < 6; i++)
                        {
                            BoxFace face  = (BoxFace)i;
                            Vector3 delta = FaceDeltas[face];
                            faceExists[face] = chunk.IsCellValid(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z);
                            drawFace[face]   = true;

                            if (faceExists[face])
                            {
                                voxelOnFace.GridPosition = new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z);
                                drawFace[face]           = voxelOnFace.IsEmpty || !voxelOnFace.IsVisible || (voxelOnFace.Type.CanRamp && voxelOnFace.RampType != RampType.None && IsSideFace(face) && ShouldDrawFace(face, voxelOnFace.RampType, v.RampType));
                            }
                            else
                            {
                                bool success = chunk.Manager.ChunkData.GetNonNullVoxelAtWorldLocation(new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z) + chunk.Origin, ref worldVoxel);
                                drawFace[face] = !success || worldVoxel.IsEmpty || !worldVoxel.IsVisible || (worldVoxel.Type.CanRamp && worldVoxel.RampType != RampType.None && IsSideFace(face) && ShouldDrawFace(face, worldVoxel.RampType, v.RampType));
                            }
                        }


                        for (int i = 0; i < 6; i++)
                        {
                            BoxFace face = (BoxFace)i;
                            if (!drawFace[face])
                            {
                                continue;
                            }
                            int faceIndex   = 0;
                            int faceCount   = 0;
                            int vertexIndex = 0;
                            int vertexCount = 0;
                            primitive.GetFace(face, uvs, out faceIndex, out faceCount, out vertexIndex, out vertexCount);
                            Vector2 texScale = uvs.Scales[i];

                            int indexOffset = accumulatedVertices.Count;
                            for (int vertOffset = 0; vertOffset < vertexCount; vertOffset++)
                            {
                                ExtendedVertex vert      = primitive.Vertices[vertOffset + vertexIndex];
                                VoxelVertex    bestKey   = VoxelChunk.GetNearestDelta(vert.Position);
                                Color          color     = v.Chunk.Data.GetColor(x, y, z, bestKey);
                                Vector3        offset    = Vector3.Zero;
                                Vector2        texOffset = Vector2.Zero;

                                if (v.Type.CanRamp && ShouldRamp(bestKey, v.RampType))
                                {
                                    offset = new Vector3(0, -v.Type.RampSize, 0);

                                    if (face != BoxFace.Top && face != BoxFace.Bottom)
                                    {
                                        texOffset = new Vector2(0, v.Type.RampSize * (texScale.Y));
                                    }
                                }


                                ExtendedVertex newVertex = new ExtendedVertex((vert.Position + v.Position + VertexNoise.GetNoiseVectorFromRepeatingTexture(vert.Position + v.Position) + offset),
                                                                              color,
                                                                              uvs.Uvs[vertOffset + vertexIndex] + texOffset, uvs.Bounds[faceIndex / 6]);
                                accumulatedVertices.Add(newVertex);
                            }

                            for (int idx = faceIndex; idx < faceCount + faceIndex; idx++)
                            {
                                int vertexOffset = primitive.Indices[idx];
                                accumulatedIndices.Add((short)(indexOffset + (vertexOffset - primitive.Indices[faceIndex])));
                            }
                        }
                    }
                }
            }


            Vertices = new ExtendedVertex[accumulatedVertices.Count];
            accumulatedVertices.CopyTo(Vertices);
            IndexBuffer = new IndexBuffer(graphics, typeof(short), accumulatedIndices.Count, BufferUsage.WriteOnly);
            IndexBuffer.SetData(accumulatedIndices.ToArray());

            ResetBuffer(graphics);
            isRebuilding = false;

            //chunk.PrimitiveMutex.WaitOne();
            chunk.NewPrimitive         = this;
            chunk.NewPrimitiveReceived = true;
            //chunk.PrimitiveMutex.ReleaseMutex();
        }
示例#15
0
        private static IEnumerable <ExtendedVertex> CreateWaterFace(Voxel voxel, BoxFace face, VoxelChunk chunk, int x, int y, int z, int totalDepth, bool top)
        {
            List <ExtendedVertex> toReturn = new List <ExtendedVertex>();
            int idx        = 0;
            int c          = 0;
            int vertOffset = 0;
            int numVerts   = 0;

            m_canconicalPrimitive.GetFace(face, m_canconicalPrimitive.UVs, out idx, out c, out vertOffset, out numVerts);

            for (int i = idx; i < idx + c; i++)
            {
                toReturn.Add(m_canconicalPrimitive.Vertices[m_canconicalPrimitive.Indices[i]]);
            }

            Vector3      origin          = chunk.Origin + new Vector3(x, y, z);
            List <Voxel> neighborsVertex = new List <Voxel>();

            for (int i = 0; i < toReturn.Count; i++)
            {
                VoxelVertex currentVertex = VoxelChunk.GetNearestDelta(toReturn[i].Position);
                chunk.GetNeighborsVertex(currentVertex, voxel, neighborsVertex);
                int   index             = chunk.Data.IndexAt(x, y, z);
                float averageWaterLevel = chunk.Data.Water[index].WaterLevel;
                float count             = 1.0f;
                float emptyNeighbors    = 0.0f;

                foreach (byte level in neighborsVertex.Select(vox => vox.WaterLevel))
                {
                    averageWaterLevel += level;
                    count++;

                    if (level < 1)
                    {
                        emptyNeighbors++;
                    }
                }

                averageWaterLevel = averageWaterLevel / count;

                float   averageWaterHeight = (float)averageWaterLevel / 255.0f;
                float   puddleness         = 0;
                Vector2 uv;

                float foaminess = emptyNeighbors / count;

                if (foaminess <= 0.5f)
                {
                    foaminess = 0.0f;
                }

                if (totalDepth < 5)
                {
                    foaminess  = 0.75f;
                    puddleness = 0;
                    uv         = new Vector2((toReturn[i].Position.X + origin.X) / 80.0f, (toReturn[i].Position.Z + origin.Z) / 80.0f);
                }
                else
                {
                    uv = new Vector2((toReturn[i].Position.X + origin.X) / 80.0f, (toReturn[i].Position.Z + origin.Z) / 80.0f);
                }
                Vector4 bounds = new Vector4(0, 0, 1, 1);

                if (chunk.Data.Water[index].IsFalling || !top)
                {
                    averageWaterHeight = 1.0f;
                }

                if (face == BoxFace.Top)
                {
                    toReturn[i] = new ExtendedVertex(toReturn[i].Position + origin + new Vector3(0, (averageWaterHeight * 0.4f - 1.0f), 0),
                                                     new Color(foaminess, puddleness, (float)totalDepth / 512.0f, 1.0f),
                                                     Color.White,
                                                     uv, bounds);
                }
                else
                {
                    Vector3 offset = Vector3.Zero;
                    switch (face)
                    {
                    case BoxFace.Back:
                    case BoxFace.Front:
                        uv        = new Vector2((Math.Abs(toReturn[i].Position.X + origin.X) / 80.0f), (Math.Abs(toReturn[i].Position.Y + origin.Y) / 80.0f));
                        foaminess = 1.0f;
                        offset    = new Vector3(0, -0.5f, 0);
                        break;

                    case BoxFace.Right:
                    case BoxFace.Left:
                        uv        = new Vector2((Math.Abs(toReturn[i].Position.Z + origin.Z) / 80.0f), (Math.Abs(toReturn[i].Position.Y + origin.Y) / 80.0f));
                        foaminess = 1.0f;
                        offset    = new Vector3(0, -0.5f, 0);
                        break;

                    case BoxFace.Top:
                        offset = new Vector3(0, -0.5f, 0);
                        break;
                    }

                    toReturn[i] = new ExtendedVertex(toReturn[i].Position + origin + offset, new Color(foaminess, 0.0f, 1.0f, 1.0f), Color.White, uv, bounds);
                }
            }

            return(toReturn);
        }
示例#16
0
        public void InitializeFromChunk(VoxelChunk chunk, GraphicsDevice graphics)
        {
            if (chunk == null)
            {
                return;
            }

            rebuildMutex.WaitOne();
            if (isRebuilding)
            {
                rebuildMutex.ReleaseMutex();
                return;
            }

            isRebuilding = true;
            rebuildMutex.ReleaseMutex();
            int[] ambientValues = new int[4];
            int   maxIndex      = 0;
            int   maxVertex     = 0;
            Voxel v             = chunk.MakeVoxel(0, 0, 0);
            Voxel voxelOnFace   = chunk.MakeVoxel(0, 0, 0);

            Voxel[]      manhattanNeighbors = new Voxel[4];
            BoxPrimitive bedrockModel       = VoxelLibrary.GetPrimitive("Bedrock");
            Voxel        worldVoxel         = new Voxel();

            if (Vertices == null)
            {
                Vertices = new ExtendedVertex[1024];
            }

            if (Indexes == null)
            {
                Indexes = new ushort[512];
            }

            for (int y = 0; y < Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, chunk.SizeY); y++)
            {
                for (int x = 0; x < chunk.SizeX; x++)
                {
                    for (int z = 0; z < chunk.SizeZ; z++)
                    {
                        v.GridPosition = new Vector3(x, y, z);


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

                        BoxPrimitive primitive = VoxelLibrary.GetPrimitive(v.Type);
                        if (v.IsExplored && primitive == null)
                        {
                            continue;
                        }
                        if (!v.IsExplored)
                        {
                            primitive = bedrockModel;
                        }

                        Color tint = v.Type.Tint;
                        BoxPrimitive.BoxTextureCoords uvs = primitive.UVs;

                        if (v.Type.HasTransitionTextures && v.IsExplored)
                        {
                            uvs = v.ComputeTransitionTexture(manhattanNeighbors);
                        }

                        for (int i = 0; i < 6; i++)
                        {
                            BoxFace face  = (BoxFace)i;
                            Vector3 delta = FaceDeltas[(int)face];
                            faceExists[(int)face] = chunk.IsCellValid(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z);
                            drawFace[(int)face]   = true;

                            if (faceExists[(int)face])
                            {
                                voxelOnFace.GridPosition = new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z);
                                drawFace[(int)face]      = (voxelOnFace.IsExplored && voxelOnFace.IsEmpty) || !voxelOnFace.IsVisible ||
                                                           (voxelOnFace.Type.CanRamp && voxelOnFace.RampType != RampType.None && IsSideFace(face) &&
                                                            ShouldDrawFace(face, voxelOnFace.RampType, v.RampType));
                            }
                            else
                            {
                                bool success = chunk.Manager.ChunkData.GetNonNullVoxelAtWorldLocation(new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z) + chunk.Origin, ref worldVoxel);
                                drawFace[(int)face] = !success || (worldVoxel.IsExplored && worldVoxel.IsEmpty) || !worldVoxel.IsVisible ||
                                                      (worldVoxel.Type.CanRamp && worldVoxel.RampType != RampType.None &&
                                                       IsSideFace(face) &&
                                                       ShouldDrawFace(face, worldVoxel.RampType, v.RampType));
                            }
                        }


                        for (int i = 0; i < 6; i++)
                        {
                            BoxFace face = (BoxFace)i;
                            if (!drawFace[(int)face])
                            {
                                continue;
                            }


                            int faceIndex   = 0;
                            int faceCount   = 0;
                            int vertexIndex = 0;
                            int vertexCount = 0;
                            primitive.GetFace(face, uvs, out faceIndex, out faceCount, out vertexIndex, out vertexCount);
                            Vector2 texScale = uvs.Scales[i];

                            int indexOffset = maxVertex;
                            for (int vertOffset = 0; vertOffset < vertexCount; vertOffset++)
                            {
                                ExtendedVertex vert    = primitive.Vertices[vertOffset + vertexIndex];
                                VoxelVertex    bestKey = primitive.Deltas[vertOffset + vertexIndex];
                                Color          color   = v.Chunk.Data.GetColor(x, y, z, bestKey);
                                ambientValues[vertOffset] = color.G;
                                Vector3 offset    = Vector3.Zero;
                                Vector2 texOffset = Vector2.Zero;

                                if (v.Type.CanRamp && ShouldRamp(bestKey, v.RampType))
                                {
                                    offset = new Vector3(0, -v.Type.RampSize, 0);

                                    if (face != BoxFace.Top && face != BoxFace.Bottom)
                                    {
                                        texOffset = new Vector2(0, v.Type.RampSize * (texScale.Y));
                                    }
                                }

                                if (maxVertex >= Vertices.Length)
                                {
                                    ExtendedVertex[] newVertices = new ExtendedVertex[Vertices.Length * 2];
                                    Vertices.CopyTo(newVertices, 0);
                                    Vertices = newVertices;
                                }

                                Vertices[maxVertex] = new ExtendedVertex(vert.Position + v.Position +
                                                                         VertexNoise.GetNoiseVectorFromRepeatingTexture(
                                                                             vert.Position + v.Position) + offset,
                                                                         color,
                                                                         tint,
                                                                         uvs.Uvs[vertOffset + vertexIndex] + texOffset,
                                                                         uvs.Bounds[faceIndex / 6]);
                                maxVertex++;
                            }

                            bool flippedQuad = ambientValues[0] + ambientValues[2] >
                                               ambientValues[1] + ambientValues[3];
                            for (int idx = faceIndex; idx < faceCount + faceIndex; idx++)
                            {
                                if (maxIndex >= Indexes.Length)
                                {
                                    ushort[] indexes = new ushort[Indexes.Length * 2];
                                    Indexes.CopyTo(indexes, 0);
                                    Indexes = indexes;
                                }

                                ushort vertexOffset  = flippedQuad ? primitive.FlippedIndexes[idx] : primitive.Indexes[idx];
                                ushort vertexOffset0 = flippedQuad? primitive.FlippedIndexes[faceIndex] : primitive.Indexes[faceIndex];
                                Indexes[maxIndex] =
                                    (ushort)((int)indexOffset + (int)((int)vertexOffset - (int)vertexOffset0));
                                maxIndex++;
                            }
                        }
                    }
                }
            }
            MaxIndex  = maxIndex;
            MaxVertex = maxVertex;
            GenerateLightmap(chunk.Manager.ChunkData.Tilemap.Bounds);
            isRebuilding = false;

            //chunk.PrimitiveMutex.WaitOne();
            chunk.NewPrimitive         = this;
            chunk.NewPrimitiveReceived = true;
            //chunk.PrimitiveMutex.ReleaseMutex();
        }
示例#17
0
        public static void CalculateVertexLight(Voxel vox, VoxelVertex face,
            ChunkManager chunks, List<Voxel> neighbors, ref VertexColorInfo color)
        {
            float numHit = 1;
            float numChecked = 1;

            int index = vox.Index;
            color.DynamicColor = 0;
            color.SunColor += vox.Chunk.Data.SunColors[index];
            vox.Chunk.GetNeighborsVertex(face, vox, neighbors);

            foreach(Voxel v in neighbors)
            {
                if(!chunks.ChunkData.ChunkMap.ContainsKey(v.Chunk.ID))
                {
                    continue;
                }

                VoxelChunk c = chunks.ChunkData.ChunkMap[v.Chunk.ID];
                color.SunColor += c.Data.SunColors[v.Index];
                if(VoxelLibrary.IsSolid(v))
                {
                    if (v.Type.EmitsLight) color.DynamicColor = 255;
                    numHit++;
                    numChecked++;
                }
                else
                {
                    numChecked++;
                }
            }

            float proportionHit = numHit / numChecked;
            color.AmbientColor = (int) Math.Min((1.0f - proportionHit) * 255.0f, 255);
            color.SunColor = (int) Math.Min((float) color.SunColor / (float) numChecked, 255);
        }
示例#18
0
 public int VertIndex(int x, int y, int z, VoxelVertex v)
 {
     int cornerX = x;
     int cornerY = y;
     int cornerZ = z;
     switch (v)
     {
         // -x, -y, -z
         case VoxelVertex.BackBottomLeft:
             cornerX += 0;
             cornerY += 0;
             cornerZ += 0;
             break;
         // +x, -y, -z
         case VoxelVertex.BackBottomRight:
             cornerX += 1;
             cornerY += 0;
             cornerZ += 0;
             break;
         // -x, +y, -z
         case VoxelVertex.BackTopLeft:
             cornerX += 0;
             cornerY += 1;
             cornerZ += 0;
             break;
         // +x, +y, -z
         case VoxelVertex.BackTopRight:
             cornerX += 1;
             cornerY += 1;
             cornerZ += 0;
             break;
         // -x, -y, +z
         case VoxelVertex.FrontBottomLeft:
             cornerX += 0;
             cornerY += 0;
             cornerZ += 1;
             break;
         // +x, -y, +z
         case VoxelVertex.FrontBottomRight:
             cornerX += 1;
             cornerY += 0;
             cornerZ += 1;
             break;
         // -x, +y, +z
         case VoxelVertex.FrontTopLeft:
             cornerX += 0;
             cornerY += 1;
             cornerZ += 1;
             break;
         // +x, +y, +z
         case VoxelVertex.FrontTopRight:
             cornerX += 1;
             cornerY += 1;
             cornerZ += 1;
             break;
     }
     return CornerIndexAt(cornerX, cornerY, cornerZ);
 }
示例#19
0
        private static void CreateWaterFaces(
            VoxelHandle voxel,
            VoxelChunk chunk,
            int x, int y, int z,
            ExtendedVertex[] vertices,
            ushort[] Indexes,
            int startVertex,
            int startIndex)
        {
            // Reset the appropriate parts of the cache.
            cache.Reset();

            // These are reused for every face.
            var   origin           = voxel.WorldPosition;
            float centerWaterlevel = voxel.LiquidLevel;

            var  below       = VoxelHelpers.GetVoxelBelow(voxel);
            bool belowFilled = false;
            bool belowLiquid = below.IsValid && below.LiquidLevel > 0;
            bool belowRamps  = below.IsValid && below.RampType != RampType.None;

            if ((below.IsValid && !below.IsEmpty) || belowLiquid)
            {
                belowFilled = true;
            }

            float[] foaminess = new float[4];

            for (int i = 0; i < cache.drawFace.Length; i++)
            {
                if (!cache.drawFace[i])
                {
                    continue;
                }
                BoxFace face = (BoxFace)i;

                var faceDescriptor = primitive.GetFace(face);
                int indexOffset    = startVertex;

                for (int vertOffset = 0; vertOffset < faceDescriptor.VertexCount; vertOffset++)
                {
                    VoxelVertex currentVertex = primitive.Deltas[faceDescriptor.VertexOffset + vertOffset];

                    // These will be filled out before being used   lh  .
                    //float foaminess1;
                    foaminess[vertOffset] = 0.0f;
                    bool shoreLine = false;

                    Vector3 pos        = Vector3.Zero;
                    Vector3 rampOffset = Vector3.Zero;
                    var     uv         = primitive.UVs.Uvs[vertOffset + faceDescriptor.VertexOffset];
                    // We are going to have to reuse some vertices when drawing a single so we'll store the position/foaminess
                    // for quick lookup when we find one of those reused ones.
                    // When drawing multiple faces the Vertex overlap gets bigger, which is a bonus.
                    if (!cache.vertexCalculated[(int)currentVertex])
                    {
                        float count             = 1.0f;
                        float emptyNeighbors    = 0.0f;
                        float averageWaterLevel = centerWaterlevel;

                        var vertexSucc = VoxelHelpers.VertexNeighbors[(int)currentVertex];

                        // Run through the successors and count up the water in each voxel.
                        for (int v = 0; v < vertexSucc.Length; v++)
                        {
                            var neighborVoxel = new VoxelHandle(chunk.Manager, voxel.Coordinate + vertexSucc[v]);
                            if (!neighborVoxel.IsValid)
                            {
                                continue;
                            }

                            // Now actually do the math.
                            count++;
                            if (neighborVoxel.LiquidLevel < 1)
                            {
                                emptyNeighbors++;
                            }
                            if (neighborVoxel.LiquidType == LiquidType.None && !neighborVoxel.IsEmpty)
                            {
                                shoreLine = true;
                            }
                        }

                        foaminess[vertOffset] = emptyNeighbors / count;

                        if (foaminess[vertOffset] <= 0.5f)
                        {
                            foaminess[vertOffset] = 0.0f;
                        }
                        // Check if it should ramp.
                        else if (!shoreLine)
                        {
                            //rampOffset.Y = -0.4f;
                        }

                        pos = primitive.Vertices[vertOffset + faceDescriptor.VertexOffset].Position;
                        if ((currentVertex & VoxelVertex.Top) == VoxelVertex.Top)
                        {
                            if (belowFilled)
                            {
                                pos.Y -= 0.6f;// Minimum ramp position
                            }
                            var neighbors = VoxelHelpers.EnumerateVertexNeighbors2D(voxel.Coordinate, currentVertex)
                                            .Select(c => new VoxelHandle(chunk.Manager, c))
                                            .Where(h => h.IsValid)
                                            .Select(h => MathFunctions.Clamp((float)h.LiquidLevel / 8.0f, 0.25f, 1.0f));

                            if (neighbors.Count() > 0)
                            {
                                if (belowFilled)
                                {
                                    pos.Y *= neighbors.Average();
                                }
                            }
                        }
                        else
                        {
                            uv.Y -= 0.6f;
                        }

                        pos += VertexNoise.GetNoiseVectorFromRepeatingTexture(voxel.WorldPosition +
                                                                              primitive.Vertices[vertOffset + faceDescriptor.VertexOffset].Position);

                        if (!belowFilled)
                        {
                            pos = (pos - Vector3.One * 0.5f);
                            pos.Normalize();
                            pos *= 0.35f;
                            pos += Vector3.One * 0.5f;
                        }
                        else if ((belowLiquid || belowRamps) && IsBottom(currentVertex))
                        {
                            if (belowRamps)
                            {
                                pos -= Vector3.Up * 0.5f;
                            }
                            else
                            {
                                pos -= Vector3.Up * 0.8f;
                            }
                        }

                        pos += origin + rampOffset;
                        // Store the vertex information for future use when we need it again on this or another face.
                        cache.vertexCalculated[(int)currentVertex] = true;
                        cache.vertexFoaminess[(int)currentVertex]  = foaminess[vertOffset];
                        cache.vertexPositions[(int)currentVertex]  = pos;
                    }
                    else
                    {
                        // We've already calculated this one.  Time for a cheap grab from the lookup.
                        foaminess[vertOffset] = cache.vertexFoaminess[(int)currentVertex];
                        pos = cache.vertexPositions[(int)currentVertex];
                    }

                    vertices[startVertex].Set(pos,
                                              new Color(foaminess[vertOffset], 0.0f, 1.0f, 1.0f),
                                              Color.White,
                                              uv,
                                              new Vector4(0, 0, 1, 1));

                    startVertex++;
                }

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

                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];

                    Indexes[startIndex] = (ushort)(indexOffset + offset - offset0);
                    startIndex++;
                }
            }
            // End cache.drawFace loop
        }
示例#20
0
 public Color GetColor(int x, int y, int z, VoxelVertex v)
 {
     return VertexColors[VertIndex(x, y, z, v)];
 }
示例#21
0
        public void GetSharedVertices(Voxel v, VoxelVertex vertex, List<KeyValuePair<Voxel, List<VoxelVertex>>> vertices, List<Voxel> neighbors )
        {
            vertices.Clear();

            GetNeighborsVertex(vertex, v, neighbors);

            Vector3 myDelta = vertexDeltas[(int) vertex];
            foreach(Voxel neighbor in neighbors)
            {
                if(neighbor == null || neighbor.IsEmpty)
                {
                    continue;
                }

                List<VoxelVertex> vertsNeighbor = new List<VoxelVertex>();
                Vector3 otherDelta = v.Position - neighbor.Position + myDelta;
                vertsNeighbor.Add(GetNearestDelta(otherDelta));

                vertices.Add(new KeyValuePair<Voxel, List<VoxelVertex>>(neighbor, vertsNeighbor));
            }
        }
示例#22
0
 public void GetNeighborsVertexDiag(VoxelVertex vertex, int x, int y, int z, List<Voxel> toReturn)
 {
     GetNeighborsSuccessors(VertexSuccessorsDiag[vertex], x, y, z, toReturn);
 }
示例#23
0
 //-------------------------
 public void GetNeighborsVertex(VoxelVertex vertex, Voxel v, List<Voxel> toReturn)
 {
     Vector3 grid = v.GridPosition;
     GetNeighborsVertex(vertex, (int) grid.X, (int) grid.Y, (int) grid.Z, toReturn);
 }
示例#24
0
        private static void CreateWaterFace(Voxel voxel,
                                            BoxFace face,
                                            VoxelChunk chunk,
                                            int x, int y, int z,
                                            bool top,
                                            ExtendedVertex[] vertices,
                                            int startVertex)
        {
            int idx         = 0;
            int vertexCount = 0;
            int vertOffset  = 0;
            int numVerts    = 0;

            primitive.GetFace(face, primitive.UVs, out idx, out vertexCount, out vertOffset, out numVerts);

            for (int i = idx; i < idx + vertexCount; i++)
            {
                vertices[i + startVertex - idx] = primitive.Vertices[primitive.Indexes[i]];
            }

            Vector3      origin          = chunk.Origin + new Vector3(x, y, z);
            List <Voxel> neighborsVertex = new List <Voxel>();

            for (int i = 0; i < vertexCount; i++)
            {
                VoxelVertex currentVertex = VoxelChunk.GetNearestDelta(vertices[i + startVertex].Position);
                chunk.GetNeighborsVertex(currentVertex, voxel, neighborsVertex);
                int   index             = chunk.Data.IndexAt(x, y, z);
                float averageWaterLevel = chunk.Data.Water[index].WaterLevel;
                float count             = 1.0f;
                float emptyNeighbors    = 0.0f;

                foreach (byte level in neighborsVertex.Select(vox => vox.WaterLevel))
                {
                    averageWaterLevel += level;
                    count++;

                    if (level < 1)
                    {
                        emptyNeighbors++;
                    }
                }

                averageWaterLevel = averageWaterLevel / count;

                float averageWaterHeight = (float)averageWaterLevel / 8.0f;
                float foaminess          = emptyNeighbors / count;

                if (foaminess <= 0.5f)
                {
                    foaminess = 0.0f;
                }

                /*
                 * if(chunk.Data.Water[index].IsFalling || !top)
                 * {
                 *  averageWaterHeight = 1.0f;
                 * }
                 */

                Vector3 pos = vertices[i + startVertex].Position;
                pos.Y *= averageWaterHeight;
                pos   += origin;

                switch (face)
                {
                case BoxFace.Back:
                case BoxFace.Front:
                    vertices[i + startVertex].Set(pos,
                                                  new Color(foaminess, 0.0f, 1.0f, 1.0f),
                                                  Color.White,
                                                  new Vector2(pos.X, pos.Y),
                                                  new Vector4(0, 0, 1, 1));
                    break;

                case BoxFace.Right:
                case BoxFace.Left:
                    vertices[i + startVertex].Set(pos,
                                                  new Color(foaminess, 0.0f, 1.0f, 1.0f),
                                                  Color.White,
                                                  new Vector2(pos.Z, pos.Y),
                                                  new Vector4(0, 0, 1, 1));
                    break;

                case BoxFace.Top:
                    vertices[i + startVertex].Set(pos,
                                                  new Color(foaminess, 0.0f, 1.0f, 1.0f),
                                                  Color.White,
                                                  new Vector2(pos.X, pos.Z),
                                                  new Vector4(0, 0, 1, 1));
                    break;
                }
            }
        }
示例#25
0
 public static bool IsTopVertex(VoxelVertex v)
 {
     return v == VoxelVertex.BackTopLeft || v == VoxelVertex.FrontTopLeft || v == VoxelVertex.FrontTopRight || v == VoxelVertex.BackTopRight;
 }
示例#26
0
        private static void CreateWaterFaces(Voxel voxel,
                                             VoxelChunk chunk,
                                             int x, int y, int z,
                                             ExtendedVertex[] vertices,
                                             int startVertex)
        {
            // Reset the appropriate parts of the cache.
            cache.Reset();

            // These are reused for every face.
            Vector3 origin           = chunk.Origin + new Vector3(x, y, z);
            int     index            = chunk.Data.IndexAt(x, y, z);
            float   centerWaterlevel = chunk.Data.Water[chunk.Data.IndexAt(x, y, z)].WaterLevel;

            for (int faces = 0; faces < cache.drawFace.Length; faces++)
            {
                if (!cache.drawFace[faces])
                {
                    continue;
                }
                BoxFace face = (BoxFace)faces;

                // Let's get the vertex/index positions for the current face.
                int idx         = 0;
                int vertexCount = 0;
                int vertOffset  = 0;
                int numVerts    = 0;
                primitive.GetFace(face, primitive.UVs, out idx, out vertexCount, out vertOffset, out numVerts);

                for (int i = 0; i < vertexCount; i++)
                {
                    // Used twice so we'll store it for later use.
                    int         primitiveIndex = primitive.Indexes[i + idx];
                    VoxelVertex currentVertex  = primitive.Deltas[primitiveIndex];

                    // These two will be filled out before being used.
                    float   foaminess;
                    Vector3 pos;

                    // We are going to have to reuse some vertices when drawing a single so we'll store the position/foaminess
                    // for quick lookup when we find one of those reused ones.
                    // When drawing multiple faces the Vertex overlap gets bigger, which is a bonus.
                    if (!cache.vertexCalculated[(int)currentVertex])
                    {
                        float count             = 1.0f;
                        float emptyNeighbors    = 0.0f;
                        float averageWaterLevel = centerWaterlevel;

                        List <Vector3> vertexSucc = VoxelChunk.VertexSuccessors[currentVertex];

                        // Run through the successors and count up the water in each voxel.
                        for (int v = 0; v < vertexSucc.Count; v++)
                        {
                            Vector3 succ = vertexSucc[v];
                            // We are going to use a lookup key so calculate it now.
                            int key = VoxelChunk.SuccessorToEuclidianLookupKey(succ);

                            // If we haven't gotten this Voxel yet then retrieve it.
                            // This allows us to only get a particular voxel once a function call instead of once per vertexCount/per face.
                            if (!cache.retrievedNeighbors[key])
                            {
                                Voxel neighbor = cache.neighbors[key];
                                cache.validNeighbors[key]     = voxel.GetNeighborBySuccessor(succ, ref neighbor, false);
                                cache.retrievedNeighbors[key] = true;
                            }
                            // Only continue if it's a valid (non-null) voxel.
                            if (!cache.validNeighbors[key])
                            {
                                continue;
                            }

                            // Now actually do the math.
                            Voxel vox = cache.neighbors[key];
                            averageWaterLevel += vox.WaterLevel;
                            count++;
                            if (vox.WaterLevel < 1)
                            {
                                emptyNeighbors++;
                            }
                        }

                        averageWaterLevel = averageWaterLevel / count;

                        float averageWaterHeight = averageWaterLevel / WaterManager.maxWaterLevel;
                        foaminess = emptyNeighbors / count;

                        if (foaminess <= 0.5f)
                        {
                            foaminess = 0.0f;
                        }

                        pos    = primitive.Vertices[primitiveIndex].Position;
                        pos.Y *= averageWaterHeight;
                        pos   += origin;

                        // Store the vertex information for future use when we need it again on this or another face.
                        cache.vertexCalculated[(int)currentVertex] = true;
                        cache.vertexFoaminess[(int)currentVertex]  = foaminess;
                        cache.vertexPositions[(int)currentVertex]  = pos;
                    }
                    else
                    {
                        // We've already calculated this one.  Time for a cheap grab from the lookup.
                        foaminess = cache.vertexFoaminess[(int)currentVertex];
                        pos       = cache.vertexPositions[(int)currentVertex];
                    }

                    switch (face)
                    {
                    case BoxFace.Back:
                    case BoxFace.Front:
                        vertices[i + startVertex].Set(pos,
                                                      new Color(foaminess, 0.0f, 1.0f, 1.0f),
                                                      Color.White,
                                                      new Vector2(pos.X, pos.Y),
                                                      new Vector4(0, 0, 1, 1));
                        break;

                    case BoxFace.Right:
                    case BoxFace.Left:
                        vertices[i + startVertex].Set(pos,
                                                      new Color(foaminess, 0.0f, 1.0f, 1.0f),
                                                      Color.White,
                                                      new Vector2(pos.Z, pos.Y),
                                                      new Vector4(0, 0, 1, 1));
                        break;

                    case BoxFace.Top:
                        vertices[i + startVertex].Set(pos,
                                                      new Color(foaminess, 0.0f, 1.0f, 1.0f),
                                                      Color.White,
                                                      new Vector2(pos.X, pos.Z),
                                                      new Vector4(0, 0, 1, 1));
                        break;
                    }
                }
                startVertex += 6;
            }
        }
示例#27
0
 public static IEnumerable <GlobalVoxelCoordinate> EnumerateVertexNeighbors2D(
     GlobalVoxelCoordinate Coordinate, VoxelVertex Vertex)
 {
     return(EnumerateNeighbors(VertexNeighbors2D[(int)Vertex], Coordinate));
 }
示例#28
0
 public void SetColor(int x, int y, int z, VoxelVertex v, Color color)
 {
     VertexColors[VertIndex(x, y, z, v)] = color;
 }