Exemple #1
0
        public void RecomputeNeighbors()
        {
            foreach (VoxelChunk chunk in ChunkMap.Select(chunks => chunks.Value))
            {
                chunk.Neighbors.Clear();
                chunk.EuclidianNeighbors.Clear();
            }

            foreach (KeyValuePair <Point3, VoxelChunk> chunks in ChunkMap)
            {
                VoxelChunk chunk = chunks.Value;

                Point3 successor = new Point3(0, 0, 0);
                for (successor.X = -1; successor.X < 2; successor.X++)
                {
                    for (successor.Z = -1; successor.Z < 2; successor.Z++)
                    {
                        for (successor.Y = -1; successor.Y < 2; successor.Y++)
                        {
                            Point3     sideChunkID = chunk.ID + successor;
                            VoxelChunk sideChunk;
                            ChunkMap.TryGetValue(sideChunkID, out sideChunk);
                            if (successor.Y == 0 && sideChunk != null)
                            {
                                if (!sideChunk.Neighbors.ContainsKey(chunk.ID) && chunk != sideChunk)
                                {
                                    chunk.Neighbors[chunk.ID] = chunk;
                                }
                                chunk.Neighbors[sideChunkID] = sideChunk;
                            }
                            chunk.EuclidianNeighbors[VoxelChunk.SuccessorToEuclidianLookupKey(successor)] = sideChunk;
                        }
                    }
                }
            }
        }
Exemple #2
0
        public bool GetNeighborBySuccessor(Vector3 succ, ref Voxel neighbor, bool requireQuickCompare = true)
        {
            Debug.Assert(neighbor != null, "Null reference passed");
            Debug.Assert(_chunk != null, "Voxel has no valid chunk reference");

            Vector3 newPos         = gridpos + succ;
            Point3  chunkSuccessor = Point3.Zero;
            bool    useSuccessor   = false;

            if (newPos.X >= _chunk.SizeX)
            {
                chunkSuccessor.X = 1;
                newPos.X         = 0;
                useSuccessor     = true;
            }
            else if (newPos.X < 0)
            {
                chunkSuccessor.X = -1;
                newPos.X         = _chunk.SizeX - 1;
                useSuccessor     = true;
            }

            if (newPos.Y >= _chunk.SizeY)
            {
                chunkSuccessor.Y = 1;
                newPos.Y         = 0;
                useSuccessor     = true;
            }
            else if (newPos.Y < 0)
            {
                chunkSuccessor.Y = -1;
                newPos.Y         = _chunk.SizeY - 1;
                useSuccessor     = true;
            }

            if (newPos.Z >= _chunk.SizeZ)
            {
                chunkSuccessor.Z = 1;
                newPos.Z         = 0;
                useSuccessor     = true;
            }
            else if (newPos.Z < 0)
            {
                chunkSuccessor.Z = -1;
                newPos.Z         = _chunk.SizeZ - 1;
                useSuccessor     = true;
            }

            VoxelChunk useChunk;

            if (useSuccessor)
            {
                useChunk = _chunk.EuclidianNeighbors[VoxelChunk.SuccessorToEuclidianLookupKey(chunkSuccessor)];
                if (useChunk == null)
                {
                    return(false);
                }
            }
            else
            {
                useChunk = _chunk;
            }
            neighbor.ChangeVoxel(useChunk, newPos, requireQuickCompare);
            return(true);
        }
Exemple #3
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;
            }
        }