public void AddChunkMeshes(Chunk chunk)
 {
     for (int i = 0; i < chunk.Meshes.Count; i++)
     {
         AddMesh(chunk.Meshes[i]);
     }
 }
Example #2
0
        public bool Contains(ref ChunkCoordinate coords, out Chunk chunk)
        {
            int x = coords.X & _dimMask;
            int z = coords.Z & _dimMask;

            chunk = Chunks[x, z];
            return (chunk != null) ? chunk.Coords.Equals(ref coords) : false;
        }
Example #3
0
        public void Store(Chunk chunk, ChunkManager manager)
        {
            int x = chunk.Coords.X & _dimMask;
            int z = chunk.Coords.Z & _dimMask;

            if (Chunks[x, z] != null)
            {
                LoadedChunks.Remove(Chunks[x, z]);
                manager.PrepareChunkForUnload(Chunks[x, z]);
            }

            Chunks[x, z] = chunk;

            LoadedChunks.Add(chunk);
            ChunksAddedSinceSort = true;
        }
 public void RemoveChunkMeshes(Chunk chunk)
 {
     for (int i = 0; i < chunk.Meshes.Count; i++)
     {
         RemoveMesh(chunk.Meshes[i]);
     }
 }
Example #5
0
 public bool Contains(Chunk chunk)
 {
     return LoadedChunks.Contains(chunk);
 }
Example #6
0
 public void ConsolidateFlags(Chunk chunk, byte neighbors)
 {
     if (chunk.State >= ChunkState.Loading) NeighborsInMemoryFlag |= neighbors;
     if (chunk.State >= ChunkState.Loaded) LightDependenciesFlag |= neighbors;
     if (chunk.State >= ChunkState.PendingBuild) BuildDependenciesFlag |= neighbors;
 }
Example #7
0
        public void NeighborChangedStateCallback(ChunkManager manager, Chunk chunk, ChunkState state)
        {
            switch (state)
            {
                case ChunkState.Loaded:
                    {
                        LightDependenciesFlag |= Coords.Neighbors(ref chunk.Coords);
                        break;
                    }
                case ChunkState.PendingLight:
                    break;
                case ChunkState.Lighting:
                    break;
                case ChunkState.PendingBuild:
                    {
                        BuildDependenciesFlag |= Coords.Neighbors(ref chunk.Coords);
                        break;
                    }
                case ChunkState.Built:
                    break;
                case ChunkState.PendingRebuild:
                    break;
                case ChunkState.Unloading:
                    {
                        byte val = Coords.Neighbors(ref chunk.Coords);
                        if((NeighborsInMemoryFlag & val) == val) NeighborsInMemoryFlag -= val;
                        if((LightDependenciesFlag & val) == val) LightDependenciesFlag -= val;
                        if((BuildDependenciesFlag & val) == val) BuildDependenciesFlag -= val;

                        StateChanged -= chunk.NeighborChangedStateCallback;
                        chunk.StateChanged -= NeighborChangedStateCallback;

                        break;
                    }
            }
        }
Example #8
0
        //WARN: When load dist is a power of 2 chunks constantly ask to load more chunks.
        public void QueueNeighbors(Chunk chunk)
        {
            Chunk neighborchunk;
            ChunkCoordinate neighborcoords;
            Vector3 newpos;
            bool contains;

            //+x
            //Get new chunkcoords
            chunk.Coords.Add(1, 0, out neighborcoords);
            contains = ChunkStorage.Contains(ref neighborcoords, out neighborchunk);
            if ((chunk.NeighborsInMemoryFlag & 1) != 1)
            {
                if (!contains)
                {
                    //Shift this chunks position to get the new chunks relative position
                    newpos.X = chunk.Position.X + Chunk.WIDTH;
                    newpos.Y = chunk.Position.Y;
                    newpos.Z = chunk.Position.Z;
                    //Create a new chunk
                    neighborchunk = new Chunk(this, ref neighborcoords, ref newpos);
                    //Update flag and connect event chain to neighbor
                    chunk.NeighborsInMemoryFlag |= 1;
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                    //Add new chunk to manager
                    AddChunk(neighborchunk);
                }
                else if (contains)//Chunk is already in memory connect to it
                {
                    //Update flag and connect event chain to neighbor
                    chunk.ConsolidateFlags(neighborchunk, 1);
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                }
            }
            //-x
            //Get new chunkcoords
            chunk.Coords.Add(-1, 0, out neighborcoords);
            contains = ChunkStorage.Contains(ref neighborcoords, out neighborchunk);
            if ((chunk.NeighborsInMemoryFlag & 2) != 2)
            {
                if (!contains)
                {
                    //Shift this chunks position to get the new chunks relative position
                    newpos.X = chunk.Position.X - Chunk.WIDTH;
                    newpos.Y = chunk.Position.Y;
                    newpos.Z = chunk.Position.Z;
                    //Create a new chunk
                    neighborchunk = new Chunk(this, ref neighborcoords, ref newpos);
                    //Update flag and connect event chain to neighbor
                    chunk.NeighborsInMemoryFlag |= 2;
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                    //Add new chunk to manager
                    AddChunk(neighborchunk);
                }
                else if (contains)//Chunk is already in memory connect to it
                {
                    //Update flag and connect event chain to neighbor
                    chunk.ConsolidateFlags(neighborchunk, 2);
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                }
            }
            //+z
            //Get new chunkcoords
            chunk.Coords.Add(0, 1, out neighborcoords);
            contains = ChunkStorage.Contains(ref neighborcoords, out neighborchunk);
            if ((chunk.NeighborsInMemoryFlag & 4) != 4)
            {
                if (!contains)
                {
                    //Shift this chunks position to get the new chunks relative position
                    newpos.X = chunk.Position.X;
                    newpos.Y = chunk.Position.Y;
                    newpos.Z = chunk.Position.Z + Chunk.WIDTH;
                    //Create a new chunk
                    neighborchunk = new Chunk(this, ref neighborcoords, ref newpos);
                    //Update flag and connect event chain to neighbor
                    chunk.NeighborsInMemoryFlag |= 4;
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                    //Add new chunk to manager
                    AddChunk(neighborchunk);
                }
                else if (contains)//Chunk is already in memory connect to it
                {
                    //Update flag and connect event chain to neighbor
                    chunk.ConsolidateFlags(neighborchunk, 4);
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                }
            }
            //-z
            //Get new chunkcoords
            chunk.Coords.Add(0, -1, out neighborcoords);
            contains = ChunkStorage.Contains(ref neighborcoords, out neighborchunk);
            if ((chunk.NeighborsInMemoryFlag & 8) != 8)
            {
                if (!contains)
                {
                    //Shift this chunks position to get the new chunks relative position
                    newpos.X = chunk.Position.X;
                    newpos.Y = chunk.Position.Y;
                    newpos.Z = chunk.Position.Z - Chunk.WIDTH;
                    //Create a new chunk
                    neighborchunk = new Chunk(this, ref neighborcoords, ref newpos);
                    //Update flag and connect event chain to neighbor
                    chunk.NeighborsInMemoryFlag |= 8;
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                    //Add new chunk to manager
                    AddChunk(neighborchunk);
                }
                else if (contains)//Chunk is already in memory connect to it
                {
                    //Update flag and connect event chain to neighbor
                    chunk.ConsolidateFlags(neighborchunk, 8);
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                }
            }
            //+x +z
            //Get new chunkcoords
            chunk.Coords.Add(1, 1, out neighborcoords);
            contains = ChunkStorage.Contains(ref neighborcoords, out neighborchunk);
            if ((chunk.NeighborsInMemoryFlag & 16) != 16)
            {
                if (!contains)
                {
                    //Shift this chunks position to get the new chunks relative position
                    newpos.X = chunk.Position.X + Chunk.WIDTH;
                    newpos.Y = chunk.Position.Y;
                    newpos.Z = chunk.Position.Z + Chunk.WIDTH;
                    //Create a new chunk
                    neighborchunk = new Chunk(this, ref neighborcoords, ref newpos);
                    //Update flag and connect event chain to neighbor
                    chunk.NeighborsInMemoryFlag |= 16;
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                    //Add new chunk to manager
                    AddChunk(neighborchunk);
                }
                else if (contains)//Chunk is already in memory connect to it
                {
                    //Update flag and connect event chain to neighbor
                    chunk.ConsolidateFlags(neighborchunk, 16);
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                }
            }
            //-x +z
            //Get new chunkcoords
            chunk.Coords.Add(-1, 1, out neighborcoords);
            contains = ChunkStorage.Contains(ref neighborcoords, out neighborchunk);
            if ((chunk.NeighborsInMemoryFlag & 32) != 32)
            {
                if (!contains)
                {
                    //Shift this chunks position to get the new chunks relative position
                    newpos.X = chunk.Position.X - Chunk.WIDTH;
                    newpos.Y = chunk.Position.Y;
                    newpos.Z = chunk.Position.Z + Chunk.WIDTH;
                    //Create a new chunk
                    neighborchunk = new Chunk(this, ref neighborcoords, ref newpos);
                    //Update flag and connect event chain to neighbor
                    chunk.NeighborsInMemoryFlag |= 32;
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                    //Add new chunk to manager
                    AddChunk(neighborchunk);
                }
                else if (contains)//Chunk is already in memory connect to it
                {
                    //Update flag and connect event chain to neighbor
                    chunk.ConsolidateFlags(neighborchunk, 32);
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                }
            }
            //+x -z
            //Get new chunkcoords
            chunk.Coords.Add(1, -1, out neighborcoords);
            contains = ChunkStorage.Contains(ref neighborcoords, out neighborchunk);
            if ((chunk.NeighborsInMemoryFlag & 64) != 64)
            {
                if (!contains)
                {
                    //Shift this chunks position to get the new chunks relative position
                    newpos.X = chunk.Position.X + Chunk.WIDTH;
                    newpos.Y = chunk.Position.Y;
                    newpos.Z = chunk.Position.Z - Chunk.WIDTH;
                    //Create a new chunk
                    neighborchunk = new Chunk(this, ref neighborcoords, ref newpos);
                    //Update flag and connect event chain to neighbor
                    chunk.NeighborsInMemoryFlag |= 64;
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                    //Add new chunk to manager
                    AddChunk(neighborchunk);
                }
                else if (contains)//Chunk is already in memory connect to it
                {
                    //Update flag and connect event chain to neighbor
                    chunk.ConsolidateFlags(neighborchunk, 64);
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                }
            }
            //-x -z
            //Get new chunkcoords
            chunk.Coords.Add(-1, -1, out neighborcoords);
            contains = ChunkStorage.Contains(ref neighborcoords, out neighborchunk);
            if ((chunk.NeighborsInMemoryFlag & 128) != 128)
            {
                if (!contains)
                {
                    //Shift this chunks position to get the new chunks relative position
                    newpos.X = chunk.Position.X - Chunk.WIDTH;
                    newpos.Y = chunk.Position.Y;
                    newpos.Z = chunk.Position.Z - Chunk.WIDTH;
                    //Create a new chunk
                    neighborchunk = new Chunk(this, ref neighborcoords, ref newpos);
                    //Update flag and connect event chain to neighbor
                    chunk.NeighborsInMemoryFlag |= 128;
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                    //Add new chunk to manager
                    AddChunk(neighborchunk);
                }
                else if (contains) //Chunk is already in memory connect to it
                {
                    //Update flag and connect event chain to neighbor
                    chunk.ConsolidateFlags(neighborchunk, 128);
                    neighborchunk.StateChanged += chunk.NeighborChangedStateCallback;
                    chunk.StateChanged += neighborchunk.NeighborChangedStateCallback;
                }
            }
        }
Example #9
0
 public void Reload()
 {
     ChunkStorage.UnloadAll(this);
     Vector3 positionInChunk = -Vector3.Up * Chunk.HEIGHT * 0.9f;
     ChunkCoordinate chunkPlayerIsIn = new ChunkCoordinate(0, 0, 8000);
     Chunk seed = new Chunk(this, ref chunkPlayerIsIn, ref positionInChunk);
     ChunkStorage.Store(seed, this);
     _loadQueue.TryAdd(seed);
     Monitor.Pulse(_loadQueue);
 }
Example #10
0
 public void PrepareChunkForUnload(Chunk chunk)
 {
     chunk.ChangeState(this, ChunkState.Unloading);
     DrawList.Remove(chunk);
     ChunkRenderer.RemoveChunkMeshes(chunk);
 }
Example #11
0
 public void AddChunk(Chunk chunk)
 {
     if (chunk == null) throw new NullReferenceException("Chunk cannot be null.");
     ChunkStorage.Store(chunk, this);
     _loadQueue.TryAdd(chunk);
     _chunksQueuedThisFrame++;
 }
Example #12
0
        public ChunkManager(Game game, ChunkCoordinate chunkPlayerIsIn, Vector3 positionInChunk, bool useThreading)
        {
            _graphics = game.GraphicsDevice;
            ChunkRenderer = new ChunkMeshRenderer(game);

            UseThreading = useThreading;

            int width = 1;
            while (width < 2*CHUNK_LOAD_DIST) width *= 2;
            ChunkStorage = new ChunkStorage(width);
            //WARN: When load dist is a power of 2 queue chunks infinitely adds delegates to the ChunkStateChange event resulting in an eventual
            //out of memory exception.
            CHUNK_LOAD_DIST = width / 2-1;
            CHUNK_LIGHT_DIST = CHUNK_LOAD_DIST;// -1;
            CHUNK_BUILD_DIST = CHUNK_LIGHT_DIST;// -1;
            width *= Chunk.WIDTH;
            CubeStorage = new CubeStorage(width, Chunk.HEIGHT, width);

            _loadQueue = new ConcurrentSerialQueue<Chunk>();
            _vertexBuffer = new CubeVertex[1000];

            LightQueue = new ConcurrentSerialQueue<Chunk>();
            BuildQueue = new ConcurrentSerialQueue<Chunk>();
            RebuildQueue = new Queue<Chunk>();
            UnloadQueue = new ConcurrentSerialQueue<Chunk>();
            DrawList = new List<Chunk>();

            _timeSinceQueue = TIME_BETWEEN_QUEUES;
            _timeSinceLoad = TIME_BETWEEN_LOADS;
            _timeSinceLight = TIME_BETWEEN_LIGHTS * 0.5f;
            _timeSinceBuild = 0.0f;

            _running = true;
            _running = true;
            _running = true;
            _running = true;

            watch1 = new Stopwatch();
            watch2 = new Stopwatch();

            Thread thread = new Thread(LoadChunks);
            thread.IsBackground = true;
            thread.SetApartmentState(ApartmentState.MTA);
            thread.Name = "LoadThread1";
            thread.Priority = ThreadPriority.Lowest;
            thread.Start();

            //thread = new Thread(LoadChunks);
            //thread.IsBackground = true;
            //thread.SetApartmentState(ApartmentState.MTA);
            //thread.Name = "LoadThread2";
            //thread.Priority = ThreadPriority.Lowest;
            //thread.Start();

            thread = new Thread(LightChunks);
            thread.IsBackground = true;
            thread.SetApartmentState(ApartmentState.MTA);
            thread.Name = "LightThread";
            thread.Priority = ThreadPriority.Lowest;
            thread.Start();

            thread = new Thread(BuildChunkVertices);
            thread.IsBackground = true;
            thread.SetApartmentState(ApartmentState.MTA);
            thread.Name = "BuildThread";
            thread.Priority = ThreadPriority.Lowest;
            thread.Start();

            //Initialize chunk loading.
            positionInChunk = -positionInChunk;
            Chunk seed = new Chunk(this, ref chunkPlayerIsIn, ref positionInChunk);
            _loadQueue.TryAdd(seed);
            ChunkStorage.Store(seed, this);
        }
Example #13
0
        public void BuildVertices(CubeVertex[] vertexBuffer, GraphicsDevice graphics, Chunk parent, CubeStorage store)
        {
            if (SideCountNeeded) CollectSubmeshStats(parent, store);
            if (vertexBuffer.Length < SidesRenderable * 6f) vertexBuffer = new CubeVertex[(int)(SidesRenderable * 6.1f)];

            Cube current;
            Cube n0;
            Cube n1;
            Cube n2;
            Cube n3;
            Cube n4;
            Cube n5;
            Cube n6;
            Cube n7;
            Cube n8;

            Vector3 offset;
            Vector3 posNNN;
            Vector3 posNNP;
            Vector3 posNPN;
            Vector3 posNPP;
            Vector3 posPNN;
            Vector3 posPNP;
            Vector3 posPPN;
            Vector3 posPPP;

            int ind = 0;
            int worldX = 0;
            int worldZ = 0;
            int reg=0;

            //int vert1light = 0;
            //int vert2light = 0;
            //int vert3light = 0;
            //int vert4light = 0;

            int maxY = Chunk.HEIGHT - 1;

            for (int x = 0; x < Chunk.WIDTH; x++)
            {
                worldX = x + parent.Coords.X * Chunk.WIDTH;
                for (int z = 0; z < Chunk.WIDTH; z++)
                {
                    worldZ = z + parent.Coords.Z * Chunk.WIDTH;
                    for (int y = _yStartIndex; y <= _yEndIndex; y++)
                    {
                        store.GetCube(worldX, y, worldZ, out current);

                        //log.Write("worldCoords", "{" + worldX.ToString() + "," + y.ToString() + "," + worldZ.ToString() + "}", "");

                        if (!current.IsRenderable) continue;

                        offset.X = x;
                        offset.Y = y - _yStartIndex;
                        offset.Z = z;

                        Vector3.Add(ref CubeVertex.CORNER_NNN, ref offset, out posNNN);
                        Vector3.Add(ref CubeVertex.CORNER_NNP, ref offset, out posNNP);
                        Vector3.Add(ref CubeVertex.CORNER_NPN, ref offset, out posNPN);
                        Vector3.Add(ref CubeVertex.CORNER_NPP, ref offset, out posNPP);
                        Vector3.Add(ref CubeVertex.CORNER_PNN, ref offset, out posPNN);
                        Vector3.Add(ref CubeVertex.CORNER_PNP, ref offset, out posPNP);
                        Vector3.Add(ref CubeVertex.CORNER_PPN, ref offset, out posPPN);
                        Vector3.Add(ref CubeVertex.CORNER_PPP, ref offset, out posPPP);

                        //-x
                        reg = worldX - 1;
                        store.GetCube(reg, y, worldZ, out n0);

                        if (n0.IsTransparent)
                        {
                            store.CheckYGetCube(reg, y + 1, worldZ, out n1);
                            store.CheckYGetCube(reg, y + 1, worldZ + 1, out n2);
                            store.GetCube(reg, y, worldZ + 1, out n3);
                            store.CheckYGetCube(reg, y - 1, worldZ + 1, out n4);
                            store.CheckYGetCube(reg, y - 1, worldZ, out n5);
                            store.CheckYGetCube(reg, y - 1, worldZ - 1, out n6);
                            store.GetCube(reg, y, worldZ - 1, out n7);
                            store.CheckYGetCube(reg, y + 1, worldZ - 1, out n8);

                            vertexBuffer[ind++] = new CubeVertex(ref posNPN, ref CubeVertex.N_NEG_X, ref CubeVertex.TC00, ref current, ref n0, ref n1, ref n7, ref n8);
                            vertexBuffer[ind++] = new CubeVertex(ref posNPP, ref CubeVertex.N_NEG_X, ref CubeVertex.TC10, ref current, ref n0, ref n1, ref n2, ref n3);
                            vertexBuffer[ind++] = new CubeVertex(ref posNNN, ref CubeVertex.N_NEG_X, ref CubeVertex.TC01, ref current, ref n0, ref n5, ref n6, ref n7);
                            vertexBuffer[ind++] = new CubeVertex(ref posNNN, ref CubeVertex.N_NEG_X, ref CubeVertex.TC01, ref current, ref n0, ref n5, ref n6, ref n7);
                            vertexBuffer[ind++] = new CubeVertex(ref posNPP, ref CubeVertex.N_NEG_X, ref CubeVertex.TC10, ref current, ref n0, ref n1, ref n2, ref n3);
                            vertexBuffer[ind++] = new CubeVertex(ref posNNP, ref CubeVertex.N_NEG_X, ref CubeVertex.TC11, ref current, ref n0, ref n3, ref n4, ref n5);
                        }

                        //+x
                        reg = worldX + 1;
                        store.GetCube(reg, y, worldZ, out n0);

                        if (n0.IsTransparent)
                        {
                            store.CheckYGetCube(reg, y + 1, worldZ, out n1);
                            store.CheckYGetCube(reg, y + 1, worldZ + 1, out n2);
                            store.GetCube(reg, y, worldZ + 1, out n3);
                            store.CheckYGetCube(reg, y - 1, worldZ + 1, out n4);
                            store.CheckYGetCube(reg, y - 1, worldZ, out n5);
                            store.CheckYGetCube(reg, y - 1, worldZ - 1, out n6);
                            store.GetCube(reg, y, worldZ - 1, out n7);
                            store.CheckYGetCube(reg, y + 1, worldZ - 1, out n8);

                            vertexBuffer[ind++] = new CubeVertex(ref posPPP, ref CubeVertex.N_POS_X, ref CubeVertex.TC00, ref current, ref n0, ref n1, ref n2, ref n3);
                            vertexBuffer[ind++] = new CubeVertex(ref posPPN, ref CubeVertex.N_POS_X, ref CubeVertex.TC10, ref current, ref n0, ref n1, ref n7, ref n8);
                            vertexBuffer[ind++] = new CubeVertex(ref posPNP, ref CubeVertex.N_POS_X, ref CubeVertex.TC01, ref current, ref n0, ref n3, ref n4, ref n5);
                            vertexBuffer[ind++] = new CubeVertex(ref posPNP, ref CubeVertex.N_POS_X, ref CubeVertex.TC01, ref current, ref n0, ref n3, ref n4, ref n5);
                            vertexBuffer[ind++] = new CubeVertex(ref posPPN, ref CubeVertex.N_POS_X, ref CubeVertex.TC10, ref current, ref n0, ref n1, ref n7, ref n8);
                            vertexBuffer[ind++] = new CubeVertex(ref posPNN, ref CubeVertex.N_POS_X, ref CubeVertex.TC11, ref current, ref n0, ref n5, ref n6, ref n7);
                        }

                        //-y
                        reg = y - 1;
                        if (y != 0) store.GetCube(worldX, reg, worldZ, out n0);
                        else n0 = Cube.NULL;

                        if (n0.IsTransparent && n0.Material != CubeMaterial.None)
                        {
                            store.GetCube(worldX + 1, reg, worldZ, out n1);
                            store.GetCube(worldX + 1, reg, worldZ + 1, out n2);
                            store.GetCube(worldX, reg, worldZ + 1, out n3);
                            store.GetCube(worldX - 1, reg, worldZ + 1, out n4);
                            store.GetCube(worldX - 1, reg, worldZ, out n5);
                            store.GetCube(worldX - 1, reg, worldZ - 1, out n6);
                            store.GetCube(worldX, reg, worldZ - 1, out n7);
                            store.GetCube(worldX + 1, reg, worldZ - 1, out n8);

                            vertexBuffer[ind++] = new CubeVertex(ref posNNP, ref CubeVertex.N_NEG_Y, ref CubeVertex.TC00, ref current, ref n0, ref n3, ref n4, ref n5);
                            vertexBuffer[ind++] = new CubeVertex(ref posPNP, ref CubeVertex.N_NEG_Y, ref CubeVertex.TC10, ref current, ref n0, ref n1, ref n2, ref n3);
                            vertexBuffer[ind++] = new CubeVertex(ref posNNN, ref CubeVertex.N_NEG_Y, ref CubeVertex.TC01, ref current, ref n0, ref n5, ref n6, ref n7);
                            vertexBuffer[ind++] = new CubeVertex(ref posNNN, ref CubeVertex.N_NEG_Y, ref CubeVertex.TC01, ref current, ref n0, ref n5, ref n6, ref n7);
                            vertexBuffer[ind++] = new CubeVertex(ref posPNP, ref CubeVertex.N_NEG_Y, ref CubeVertex.TC10, ref current, ref n0, ref n1, ref n2, ref n3);
                            vertexBuffer[ind++] = new CubeVertex(ref posPNN, ref CubeVertex.N_NEG_Y, ref CubeVertex.TC11, ref current, ref n0, ref n1, ref n7, ref n8);
                        }

                        //+y
                        reg = y + 1;
                        if (y != maxY) store.GetCube(worldX, reg, worldZ, out n0);
                        else n0 = Cube.NULL;

                        if (n0.IsTransparent && n0.Material != CubeMaterial.None)
                        {
                            store.GetCube(worldX + 1, reg, worldZ, out n1);
                            store.GetCube(worldX + 1, reg, worldZ + 1, out n2);
                            store.GetCube(worldX, reg, worldZ + 1, out n3);
                            store.GetCube(worldX - 1, reg, worldZ + 1, out n4);
                            store.GetCube(worldX - 1, reg, worldZ, out n5);
                            store.GetCube(worldX - 1, reg, worldZ - 1, out n6);
                            store.GetCube(worldX, reg, worldZ - 1, out n7);
                            store.GetCube(worldX + 1, reg, worldZ - 1, out n8);

                            vertexBuffer[ind++] = new CubeVertex(ref posNPN, ref CubeVertex.N_POS_Y, ref CubeVertex.TC00, ref current, ref n0, ref n5, ref n6, ref n7);
                            vertexBuffer[ind++] = new CubeVertex(ref posPPN, ref CubeVertex.N_POS_Y, ref CubeVertex.TC10, ref current, ref n0, ref n1, ref n7, ref n8);
                            vertexBuffer[ind++] = new CubeVertex(ref posNPP, ref CubeVertex.N_POS_Y, ref CubeVertex.TC01, ref current, ref n0, ref n3, ref n4, ref n5);
                            vertexBuffer[ind++] = new CubeVertex(ref posNPP, ref CubeVertex.N_POS_Y, ref CubeVertex.TC01, ref current, ref n0, ref n3, ref n4, ref n5);
                            vertexBuffer[ind++] = new CubeVertex(ref posPPN, ref CubeVertex.N_POS_Y, ref CubeVertex.TC10, ref current, ref n0, ref n1, ref n7, ref n8);
                            vertexBuffer[ind++] = new CubeVertex(ref posPPP, ref CubeVertex.N_POS_Y, ref CubeVertex.TC11, ref current, ref n0, ref n1, ref n2, ref n3);
                        }

                        //-z
                        reg = worldZ - 1;
                        store.GetCube(worldX, y, reg, out n0);

                        if (n0.IsTransparent)
                        {
                            store.GetCube(worldX + 1, y, reg, out n1);
                            store.CheckYGetCube(worldX + 1, y + 1, reg, out n2);
                            store.CheckYGetCube(worldX, y + 1, reg, out n3);
                            store.CheckYGetCube(worldX - 1, y + 1, reg, out n4);
                            store.GetCube(worldX - 1, y, reg, out n5);
                            store.CheckYGetCube(worldX - 1, y - 1, reg, out n6);
                            store.CheckYGetCube(worldX, y - 1, reg, out n7);
                            store.CheckYGetCube(worldX + 1, y - 1, reg, out n8);

                            vertexBuffer[ind++] = new CubeVertex(ref posPPN, ref CubeVertex.N_NEG_Z, ref CubeVertex.TC00, ref current, ref n0, ref n1, ref n2, ref n3);
                            vertexBuffer[ind++] = new CubeVertex(ref posNPN, ref CubeVertex.N_NEG_Z, ref CubeVertex.TC10, ref current, ref n0, ref n3, ref n4, ref n5);
                            vertexBuffer[ind++] = new CubeVertex(ref posPNN, ref CubeVertex.N_NEG_Z, ref CubeVertex.TC01, ref current, ref n0, ref n1, ref n7, ref n8);
                            vertexBuffer[ind++] = new CubeVertex(ref posPNN, ref CubeVertex.N_NEG_Z, ref CubeVertex.TC01, ref current, ref n0, ref n1, ref n7, ref n8);
                            vertexBuffer[ind++] = new CubeVertex(ref posNPN, ref CubeVertex.N_NEG_Z, ref CubeVertex.TC10, ref current, ref n0, ref n3, ref n4, ref n5);
                            vertexBuffer[ind++] = new CubeVertex(ref posNNN, ref CubeVertex.N_NEG_Z, ref CubeVertex.TC11, ref current, ref n0, ref n5, ref n6, ref n7);
                        }

                        //+z
                        reg = worldZ + 1;
                        store.GetCube(worldX, y, reg, out n0);

                        if (n0.IsTransparent)
                        {
                            store.GetCube(worldX + 1, y, reg, out n1);
                            store.CheckYGetCube(worldX + 1, y + 1, reg, out n2);
                            store.CheckYGetCube(worldX, y + 1, reg, out n3);
                            store.CheckYGetCube(worldX - 1, y + 1, reg, out n4);
                            store.GetCube(worldX - 1, y, reg, out n5);
                            store.CheckYGetCube(worldX - 1, y - 1, reg, out n6);
                            store.CheckYGetCube(worldX, y - 1, reg, out n7);
                            store.CheckYGetCube(worldX + 1, y - 1, reg, out n8);

                            vertexBuffer[ind++] = new CubeVertex(ref posNPP, ref CubeVertex.N_POS_Z, ref CubeVertex.TC00, ref current, ref n0, ref n3, ref n4, ref n5);
                            vertexBuffer[ind++] = new CubeVertex(ref posPPP, ref CubeVertex.N_POS_Z, ref CubeVertex.TC10, ref current, ref n0, ref n1, ref n2, ref n3);
                            vertexBuffer[ind++] = new CubeVertex(ref posNNP, ref CubeVertex.N_POS_Z, ref CubeVertex.TC01, ref current, ref n0, ref n5, ref n6, ref n7);
                            vertexBuffer[ind++] = new CubeVertex(ref posNNP, ref CubeVertex.N_POS_Z, ref CubeVertex.TC01, ref current, ref n0, ref n5, ref n6, ref n7);
                            vertexBuffer[ind++] = new CubeVertex(ref posPPP, ref CubeVertex.N_POS_Z, ref CubeVertex.TC10, ref current, ref n0, ref n1, ref n2, ref n3);
                            vertexBuffer[ind++] = new CubeVertex(ref posPNP, ref CubeVertex.N_POS_Z, ref CubeVertex.TC11, ref current, ref n0, ref n1, ref n7, ref n8);
                        }
                    }
                }
            }

            if (ind > 0)
            {
                VertexBuffer = new VertexBuffer(graphics, typeof(CubeVertex), ind, BufferUsage.None);
                VertexBuffer.SetData<CubeVertex>(vertexBuffer,0,ind);
                Empty = false;
            }
            else Empty = true;
        }
Example #14
0
        public void CollectSubmeshStats(Chunk parent, CubeStorage store)
        {
            Cube current;
            Cube neighbor;
            int worldX = 0;
            int worldZ = 0;

            int maxY = Chunk.HEIGHT - 1;

            for (int x = 0; x < Chunk.WIDTH; x++)
            {
                worldX = x + parent.Coords.X * Chunk.WIDTH;
                for (int z = 0; z < Chunk.WIDTH; z++)
                {
                    worldZ = z + parent.Coords.Z * Chunk.WIDTH;
                    for (int y = _yStartIndex; y <= _yEndIndex; y++)
                    {
                        store.GetCube(worldX, y, worldZ, out current);
                        if (!current.IsRenderable) continue;

                        RenderableBlocks += 1;

                        //-x
                        store.GetCube(worldX - 1, y, worldZ, out neighbor);
                        if (neighbor.IsTransparent) SidesRenderable++;

                        //+x
                        store.GetCube(worldX + 1, y, worldZ, out neighbor);

                        if (neighbor.IsTransparent) SidesRenderable++;

                        //-y
                        if (y != 0) store.GetCube(worldX, y - 1, worldZ, out neighbor);
                        else neighbor = Cube.NULL;
                        if (neighbor.IsTransparent && neighbor.Material != CubeMaterial.None) SidesRenderable++;

                        //+y
                        if (y != maxY) store.GetCube(worldX, y + 1, worldZ, out neighbor);
                        else neighbor = Cube.NULL;
                        if (neighbor.IsTransparent && neighbor.Material != CubeMaterial.None) SidesRenderable++;

                        //-z
                        store.GetCube(worldX, y, worldZ - 1, out neighbor);
                        if (neighbor.IsTransparent) SidesRenderable++;

                        //+z
                        store.GetCube(worldX, y, worldZ + 1, out neighbor);
                        if (neighbor.IsTransparent) SidesRenderable++;
                    }
                }
            }
        }