Beispiel #1
0
 private VoxelHandle(VoxelChunk Chunk, LocalVoxelCoordinate Coordinate)
 {
     this.Coordinate     = Chunk.ID + Coordinate;
     this._cache_Chunk   = Chunk;
     this._cache_Index   = VoxelConstants.DataIndexOf(Coordinate);
     this._cache_Local_Y = Coordinate.Y;
 }
Beispiel #2
0
        private ulong GetVoxelQuickCompare(VoxelHandle V)
        {
            var coord = V.Coordinate.GetGlobalChunkCoordinate();
            var index = VoxelConstants.DataIndexOf(V.Coordinate.GetLocalVoxelCoordinate());

            ulong q = 0;

            q |= (((ulong)coord.X & 0xFFFF) << 48);
            q |= (((ulong)coord.Y & 0xFFFF) << 32);
            q |= (((ulong)coord.Z & 0xFFFF) << 16);
            q |= ((ulong)index & 0xFFFF);
            return(q);
        }
Beispiel #3
0
        // This will loop through the whole world and draw out all liquid primatives that are handed to the function.
        public static void InitializePrimativesFromChunk(VoxelChunk chunk, List <LiquidPrimitive> primitivesToInit)
        {
            LiquidPrimitive[] lps = new LiquidPrimitive[(int)LiquidType.Count];

            if (!AddCaches(primitivesToInit, ref lps))
            {
                return;
            }

            LiquidType      curLiqType   = LiquidType.None;
            LiquidPrimitive curPrimitive = null;

            ExtendedVertex[] curVertices = null;
            ushort[]         curIndexes  = null;
            int[]            maxVertices = new int[lps.Length];
            int[]            maxIndexes  = new int[lps.Length];

            int  maxVertex  = 0;
            int  maxIndex   = 0;
            int  totalFaces = 6;
            bool fogOfWar   = GameSettings.Default.FogofWar;

            for (int y = 0; y < Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, VoxelConstants.ChunkSizeY); y++)
            {
                if (chunk.Data.LiquidPresent[y] == 0)
                {
                    continue;
                }

                for (int x = 0; x < VoxelConstants.ChunkSizeX; x++)
                {
                    for (int z = 0; z < VoxelConstants.ChunkSizeZ; z++)
                    {
                        var voxel = new VoxelHandle(chunk, new LocalVoxelCoordinate(x, y, z));
                        int index = VoxelConstants.DataIndexOf(new LocalVoxelCoordinate(x, y, z));
                        if (fogOfWar && !chunk.Data.IsExplored[index])
                        {
                            continue;
                        }

                        if (voxel.WaterCell.WaterLevel > 0)
                        {
                            var liqType = voxel.WaterCell.Type;

                            // We need to see if we changed types and should change the data we are writing to.
                            if (liqType != curLiqType)
                            {
                                LiquidPrimitive newPrimitive = lps[(int)liqType];
                                // We weren't passed a LiquidPrimitive object to work with for this type so we'll skip it.
                                if (newPrimitive == null)
                                {
                                    continue;
                                }

                                maxVertices[(int)curLiqType] = maxVertex;
                                maxIndexes[(int)curLiqType]  = maxIndex;

                                curVertices = newPrimitive.Vertices;
                                curIndexes  = newPrimitive.Indexes;

                                curLiqType   = liqType;
                                curPrimitive = newPrimitive;
                                maxVertex    = maxVertices[(int)liqType];
                                maxIndex     = maxIndexes[(int)liqType];
                            }

                            int facesToDraw = 0;
                            for (int i = 0; i < totalFaces; i++)
                            {
                                BoxFace face = (BoxFace)i;
                                // We won't draw the bottom face.  This might be needed down the line if we add transparent tiles like glass.
                                if (face == BoxFace.Bottom)
                                {
                                    continue;
                                }

                                var delta = faceDeltas[(int)face];

                                // Pull the current neighbor DestinationVoxel based on the face it would be touching.

                                var vox = VoxelHelpers.GetNeighbor(voxel, delta);

                                if (vox.IsValid)
                                {
                                    if (face == BoxFace.Top)
                                    {
                                        if (!(vox.WaterCell.WaterLevel == 0 || y == (int)chunk.Manager.ChunkData.MaxViewingLevel))
                                        {
                                            cache.drawFace[(int)face] = false;
                                            continue;
                                        }
                                    }
                                    else
                                    {
                                        if (vox.WaterCell.WaterLevel != 0 || !vox.IsEmpty)
                                        {
                                            cache.drawFace[(int)face] = false;
                                            continue;
                                        }
                                    }
                                }

                                cache.drawFace[(int)face] = true;
                                facesToDraw++;
                            }

                            // There's no faces to draw on this voxel.  Let's go to the next one.
                            if (facesToDraw == 0)
                            {
                                continue;
                            }

                            // Now we check to see if we need to resize the current Vertex array.
                            int vertexSizeIncrease = facesToDraw * 4;
                            int indexSizeIncrease  = facesToDraw * 6;

                            lock (curPrimitive.VertexLock)
                            {
                                // Check vertex array size
                                if (curVertices == null)
                                {
                                    curVertices           = new ExtendedVertex[256];
                                    curPrimitive.Vertices = curVertices;
                                }
                                else if (curVertices.Length <= maxVertex + vertexSizeIncrease)
                                {
                                    ExtendedVertex[] newVerts = new ExtendedVertex[MathFunctions.NearestPowerOf2(maxVertex + vertexSizeIncrease)];

                                    curVertices.CopyTo(newVerts, 0);
                                    curVertices           = newVerts;
                                    curPrimitive.Vertices = curVertices;
                                }

                                // Check index array size
                                if (curIndexes == null)
                                {
                                    curIndexes           = new ushort[256];
                                    curPrimitive.Indexes = curIndexes;
                                }
                                else if (curIndexes.Length <= maxIndex + indexSizeIncrease)
                                {
                                    ushort[] newIdxs = new ushort[MathFunctions.NearestPowerOf2(maxIndex + indexSizeIncrease)];

                                    curIndexes.CopyTo(newIdxs, 0);
                                    curIndexes           = newIdxs;
                                    curPrimitive.Indexes = curIndexes;
                                }
                            }

                            // Now we have a list of all the faces that will need to be drawn.  Let's draw  them.
                            CreateWaterFaces(voxel, chunk, x, y, z, curVertices, curIndexes, maxVertex, maxIndex);

                            // Finally increase the size so we can move on.
                            maxVertex += vertexSizeIncrease;
                            maxIndex  += indexSizeIncrease;
                        }
                    }
                }
            }

            // The last thing we need to do is make sure we set the current primative's maxVertices to the right value.
            maxVertices[(int)curLiqType] = maxVertex;
            maxIndexes[(int)curLiqType]  = maxIndex;

            // Now actually force the VertexBuffer to be recreated in each primative we worked with.
            for (int i = 0; i < lps.Length; i++)
            {
                LiquidPrimitive updatedPrimative = lps[i];
                if (updatedPrimative == null)
                {
                    continue;
                }

                maxVertex = maxVertices[i];
                maxIndex  = maxIndexes[i];

                if (maxVertex > 0)
                {
                    try
                    {
                        lock (updatedPrimative.VertexLock)
                        {
                            updatedPrimative.VertexCount  = maxVertex;
                            updatedPrimative.IndexCount   = maxIndex;
                            updatedPrimative.VertexBuffer = null;
                            updatedPrimative.IndexBuffer  = null;
                        }
                    }
                    catch (System.Threading.AbandonedMutexException e)
                    {
                        Console.Error.WriteLine(e.Message);
                    }
                }
                else
                {
                    try
                    {
                        lock (updatedPrimative.VertexLock)
                        {
                            updatedPrimative.VertexBuffer = null;
                            updatedPrimative.Vertices     = null;
                            updatedPrimative.IndexBuffer  = null;
                            updatedPrimative.Indexes      = null;
                            updatedPrimative.VertexCount  = 0;
                            updatedPrimative.IndexCount   = 0;
                        }
                    }
                    catch (System.Threading.AbandonedMutexException e)
                    {
                        Console.Error.WriteLine(e.Message);
                    }
                }
                updatedPrimative.IsBuilding = false;
            }

            cache.inUse = false;
            cache       = null;
        }