Exemple #1
0
        /*
         *      void Update () {
         *
         *              foreach (Chunk chunk in ChunksMap) {
         *                      if (chunk == null) {
         *                              continue;
         *                      }
         *                      foreach (ChunkSlice slice in chunk.Slices) {
         *                              if (slice.IsEmpty) {
         *                                      continue;
         *                              }
         *                              slice.FrustrumCulling();
         *                      }
         *              }
         *      }
         */

        void FixedUpdate()
        {
            ++accumulator;

            if (accumulator == 2)            // Each 100ms (1 FixedStep is 50ms)
            {
                lock (ChunkQueueLock)
                {
                    Queue <ChunkSliceBuildEntry> temp = ChunkSlicesWorkingQueue;
                    ChunkSlicesWorkingQueue = ChunkSlicesToBuild;
                    ChunkSlicesToBuild      = temp;
                }

                for (int i = 0; ChunkSlicesWorkingQueue.Count != 0 && i < 40; ++i)
                {
                    ChunkSliceBuildEntry chunkEntry = ChunkSlicesWorkingQueue.Dequeue();
                    BuildChunkSliceMesh(chunkEntry);

                    if (ChunkSlicesWorkingQueue.Count == 0 && Player.Instance == null)
                    {
                        Server.Instance.spawnPlayer(new Vector3(0, 160, 0), Quaternion.identity);
                        Menu.Instance.showPanel("PlayerPanel");
                    }
                }

                lock (SliceLock)
                {
                    Queue <ChunkSlicesDeleteEntry> temp = SlicesToDeleteWorking;
                    SlicesToDeleteWorking = SlicesToDelete;
                    SlicesToDelete        = temp;
                }

                for (int i = 0; SlicesToDeleteWorking.Count != 0; ++i)
                {
                    ChunkSlicesDeleteEntry sliceToDelete = SlicesToDeleteWorking.Dequeue();


                    /*for(int s = 0; s < sliceToDelete.indexesToDelete.Length; ++s)
                     * {
                     *      int index = sliceToDelete.indexesToDelete[s];
                     *      ChunkSlice slice = sliceToDelete.parentChunk.Slices[index];
                     *      if(slice.IsEmpty)
                     *              sliceToDelete.parentChunk.Slices[index] = null;
                     *
                     *      UnityEngine.Object.Destroy(sliceToDelete.parentChunk.ChunkSliceObjects[index]);
                     *      sliceToDelete.parentChunk.ChunkSliceObjects[index] = null;
                     * }*/
                }

                accumulator = 0;
            }
        }
        public void RenderChunk(Chunk chunk)
        {
            WorldBehaviour world = chunk.World;

            /*	Stopwatch watch = new Stopwatch();
             *      watch.Start();
             */

            int minSliceIndex = chunk.MinSliceIndex;
            int lowestY       = chunk.LowestY;

            Chunk frontChunk = world.GetChunk(chunk.X, chunk.Z - 1);
            Chunk backChunk  = world.GetChunk(chunk.X, chunk.Z + 1);
            Chunk leftChunk  = world.GetChunk(chunk.X - 1, chunk.Z);
            Chunk rightChunk = world.GetChunk(chunk.X + 1, chunk.Z);

            if (frontChunk != null && frontChunk.MinSliceIndex < minSliceIndex)
            {
                minSliceIndex = frontChunk.MinSliceIndex;
                lowestY       = frontChunk.LowestY;
            }

            if (backChunk != null && backChunk.MinSliceIndex < minSliceIndex)
            {
                minSliceIndex = backChunk.MinSliceIndex;
                lowestY       = backChunk.LowestY;
            }

            if (leftChunk != null && leftChunk.MinSliceIndex < minSliceIndex)
            {
                minSliceIndex = leftChunk.MinSliceIndex;
                lowestY       = leftChunk.MinSliceIndex;
            }

            if (rightChunk != null && rightChunk.MinSliceIndex < minSliceIndex)
            {
                minSliceIndex = rightChunk.MinSliceIndex;
                lowestY       = rightChunk.MinSliceIndex;
            }


            for (int i = Chunk.NumSlices - 1; i >= 0; --i)
            {
                ChunkSlice chunkSlice = chunk.Slices[i];

                if (i < minSliceIndex)
                {
                    for (int index = i; index >= 0; --index)
                    {
                        indexesToDelete.Add(index);
                    }
                    break;
                }

                if (chunkSlice.IsEmpty)
                {
                    indexesToDelete.Add(i);
                    continue;
                }

                float epsilon = 0.00f;

                /*watch.Reset();
                *  watch.Start();*/

                int minHeight = chunk.MinSliceIndex == chunkSlice.Index ? (chunk.LowestY & Chunk.SliceHeightLimit) : 0;

                for (int x = 0; x < 16; x++)
                {
                    for (int z = 0; z < 16; z++)
                    {
                        for (int y = Chunk.SliceHeight - 1; y >= 0 && y >= minHeight; --y)
                        {
                            byte block = chunkSlice[x, y, z];
                            int  light = 0;
                            byte top;

                            if (block == 0)
                            {
                                continue;
                            }

                            if (y + 1 > Chunk.SliceHeightLimit)
                            {
                                if (i + 1 > Chunk.MaxSliceIndex)
                                {
                                    top = 0;
                                }
                                else
                                {
                                    ChunkSlice topSlice = chunk.Slices[i + 1];
                                    top   = topSlice[x, (y + 1) & Chunk.SliceHeightLimit, z];
                                    light = topSlice.GetSkylight(x, (y + 1) & Chunk.SliceHeightLimit, z);
                                }
                            }
                            else
                            {
                                top   = chunkSlice[x, y + 1, z];
                                light = chunkSlice.GetSkylight(x, y + 1, z);
                            }

                            // we are checking the top face of the block, so see if the top is exposed
                            if (top == 0)
                            {
                                if (WorldBehaviour.mode == 2)
                                {
                                    spawnBrick(block, new Vector3(x, y, z));
                                }
                                else if (WorldBehaviour.mode == 3)
                                {
                                    addBrickFace("top", block, x, y, z);
                                }
                                else
                                {
                                    int vertexIndex = vertices.Count;
                                    vertices.Add(new Vector3(x, y + 1, z));
                                    vertices.Add(new Vector3(x, y + 1, z + 1));
                                    vertices.Add(new Vector3(x + 1, y + 1, z + 1));
                                    vertices.Add(new Vector3(x + 1, y + 1, z));

                                    triangles.Add(vertexIndex);
                                    triangles.Add(vertexIndex + 1);
                                    triangles.Add(vertexIndex + 2);

                                    triangles.Add(vertexIndex + 2);
                                    triangles.Add(vertexIndex + 3);
                                    triangles.Add(vertexIndex);


                                    float attenuation = (light / 15.0f);
                                    Color withLight   = new Color(topColor.r * attenuation, topColor.g * attenuation, topColor.b * attenuation, 1);
                                    colors.Add(withLight);
                                    colors.Add(withLight);
                                    colors.Add(withLight);
                                    colors.Add(withLight);

                                    Rect coords = BlockUVs.GetUVFromTypeAndFace((BlockType)block, BlockFace.Top);

                                    float yMax = coords.y + coords.height - epsilon;
                                    float xMax = coords.x + coords.width - epsilon;
                                    float xMin = coords.x + epsilon;
                                    float yMin = coords.y + epsilon;

                                    uvs.Add(new Vector2(xMin, yMax));
                                    uvs.Add(new Vector2(xMin, yMin));
                                    uvs.Add(new Vector2(xMax, yMin));
                                    uvs.Add(new Vector2(xMax, yMax));
                                }
                            }

                            int front;
                            if (z - 1 < 0)
                            {
                                int worldX = (chunk.X << 4) + x;
                                int worldZ = (chunk.Z << 4) - 1;
                                int worldY = (chunkSlice.Index * ChunkSlice.SizeY) + y;

                                front = (byte)world.GetBlockType(worldX, worldY, worldZ);
                            }
                            else
                            {
                                front = chunkSlice[x, y, z - 1];
                            }

                            if (front == 0)
                            {
                                if (WorldBehaviour.mode == 2)
                                {
                                    spawnBrick(block, new Vector3(x, y, z));
                                }
                                else if (WorldBehaviour.mode == 3)
                                {
                                    addBrickFace("front", block, x, y, z);
                                }
                                else
                                {
                                    int vertexIndex = vertices.Count;
                                    vertices.Add(new Vector3(x, y, z));
                                    vertices.Add(new Vector3(x, y + 1, z));
                                    vertices.Add(new Vector3(x + 1, y + 1, z));
                                    vertices.Add(new Vector3(x + 1, y, z));

                                    triangles.Add(vertexIndex);
                                    triangles.Add(vertexIndex + 1);
                                    triangles.Add(vertexIndex + 2);

                                    triangles.Add(vertexIndex + 2);
                                    triangles.Add(vertexIndex + 3);
                                    triangles.Add(vertexIndex);

                                    colors.Add(firstSideColor);
                                    colors.Add(firstSideColor);
                                    colors.Add(firstSideColor);
                                    colors.Add(firstSideColor);

                                    Rect coords = BlockUVs.GetUVFromTypeAndFace((BlockType)block, BlockFace.Side);

                                    float yMax = coords.y + coords.height - epsilon;
                                    float xMax = coords.x + coords.width - epsilon;
                                    float xMin = coords.x + epsilon;
                                    float yMin = coords.y + epsilon;

                                    uvs.Add(new Vector2(xMin, yMin));
                                    uvs.Add(new Vector2(xMin, yMax));
                                    uvs.Add(new Vector2(xMax, yMax));
                                    uvs.Add(new Vector2(xMax, yMin));
                                }
                            }

                            int right;

                            if (x + 1 > 15)
                            {
                                int worldX = (chunk.X << 4) + 16;
                                int worldZ = (chunk.Z << 4) + z;
                                int worldY = (chunkSlice.Index * ChunkSlice.SizeY) + y;

                                right = (byte)world.GetBlockType(worldX, worldY, worldZ);
                            }
                            else
                            {
                                right = chunkSlice[x + 1, y, z];
                            }

                            if (right == 0)
                            {
                                if (WorldBehaviour.mode == 2)
                                {
                                    spawnBrick(block, new Vector3(x, y, z));
                                }
                                else if (WorldBehaviour.mode == 3)
                                {
                                    addBrickFace("right", block, x, y, z);
                                }
                                else
                                {
                                    int vertexIndex = vertices.Count;
                                    vertices.Add(new Vector3(x + 1, y, z));
                                    vertices.Add(new Vector3(x + 1, y + 1, z));
                                    vertices.Add(new Vector3(x + 1, y + 1, z + 1));
                                    vertices.Add(new Vector3(x + 1, y, z + 1));

                                    triangles.Add(vertexIndex);
                                    triangles.Add(vertexIndex + 1);
                                    triangles.Add(vertexIndex + 2);

                                    triangles.Add(vertexIndex + 2);
                                    triangles.Add(vertexIndex + 3);
                                    triangles.Add(vertexIndex);

                                    colors.Add(secondSideColor);
                                    colors.Add(secondSideColor);
                                    colors.Add(secondSideColor);
                                    colors.Add(secondSideColor);

                                    Rect coords = BlockUVs.GetUVFromTypeAndFace((BlockType)block, BlockFace.Side);

                                    float yMax = coords.y + coords.height - epsilon;
                                    float xMax = coords.x + coords.width - epsilon;
                                    float xMin = coords.x + epsilon;
                                    float yMin = coords.y + epsilon;

                                    uvs.Add(new Vector2(xMin, yMin));
                                    uvs.Add(new Vector2(xMin, yMax));
                                    uvs.Add(new Vector2(xMax, yMax));
                                    uvs.Add(new Vector2(xMax, yMin));
                                }
                            }

                            int back;

                            if (z + 1 > 15)
                            {
                                int worldX = (chunk.X << 4) + x;
                                int worldZ = (chunk.Z << 4) + 16;
                                int worldY = (chunkSlice.Index * ChunkSlice.SizeY) + y;

                                back = (byte)world.GetBlockType(worldX, worldY, worldZ);
                            }
                            else
                            {
                                back = chunkSlice[x, y, z + 1];
                            }

                            if (back == 0)
                            {
                                if (WorldBehaviour.mode == 2)
                                {
                                    spawnBrick(block, new Vector3(x, y, z));
                                }
                                else if (WorldBehaviour.mode == 3)
                                {
                                    addBrickFace("back", block, x, y, z);
                                }
                                else
                                {
                                    int vertexIndex = vertices.Count;
                                    vertices.Add(new Vector3(x + 1, y, z + 1));
                                    vertices.Add(new Vector3(x + 1, y + 1, z + 1));
                                    vertices.Add(new Vector3(x, y + 1, z + 1));
                                    vertices.Add(new Vector3(x, y, z + 1));

                                    triangles.Add(vertexIndex);
                                    triangles.Add(vertexIndex + 1);
                                    triangles.Add(vertexIndex + 2);

                                    triangles.Add(vertexIndex + 2);
                                    triangles.Add(vertexIndex + 3);
                                    triangles.Add(vertexIndex);

                                    colors.Add(firstSideColor);
                                    colors.Add(firstSideColor);
                                    colors.Add(firstSideColor);
                                    colors.Add(firstSideColor);

                                    Rect coords = BlockUVs.GetUVFromTypeAndFace((BlockType)block, BlockFace.Side);

                                    float yMax = coords.y + coords.height - epsilon;
                                    float xMax = coords.x + coords.width - epsilon;
                                    float xMin = coords.x + epsilon;
                                    float yMin = coords.y + epsilon;

                                    uvs.Add(new Vector2(xMin, yMin));
                                    uvs.Add(new Vector2(xMin, yMax));
                                    uvs.Add(new Vector2(xMax, yMax));
                                    uvs.Add(new Vector2(xMax, yMin));
                                }
                            }

                            int left;

                            if (x - 1 < 0)
                            {
                                int worldX = (chunk.X << 4) - 1;
                                int worldZ = (chunk.Z << 4) + z;
                                int worldY = (chunkSlice.Index * ChunkSlice.SizeY) + y;

                                left = (byte)world.GetBlockType(worldX, worldY, worldZ);
                            }
                            else
                            {
                                left = chunkSlice[x - 1, y, z];
                            }

                            if (left == 0)
                            {
                                if (WorldBehaviour.mode == 2)
                                {
                                    spawnBrick(block, new Vector3(x, y, z));
                                }
                                else if (WorldBehaviour.mode == 3)
                                {
                                    addBrickFace("left", block, x, y, z);
                                }
                                else
                                {
                                    int vertexIndex = vertices.Count;
                                    vertices.Add(new Vector3(x, y, z + 1));
                                    vertices.Add(new Vector3(x, y + 1, z + 1));
                                    vertices.Add(new Vector3(x, y + 1, z));
                                    vertices.Add(new Vector3(x, y, z));

                                    triangles.Add(vertexIndex);
                                    triangles.Add(vertexIndex + 1);
                                    triangles.Add(vertexIndex + 2);

                                    triangles.Add(vertexIndex + 2);
                                    triangles.Add(vertexIndex + 3);
                                    triangles.Add(vertexIndex);

                                    colors.Add(secondSideColor);
                                    colors.Add(secondSideColor);
                                    colors.Add(secondSideColor);
                                    colors.Add(secondSideColor);

                                    Rect coords = BlockUVs.GetUVFromTypeAndFace((BlockType)block, BlockFace.Side);

                                    float yMax = coords.y + coords.height - epsilon;
                                    float xMax = coords.x + coords.width - epsilon;
                                    float xMin = coords.x + epsilon;
                                    float yMin = coords.y + epsilon;

                                    uvs.Add(new Vector2(xMin, yMin));
                                    uvs.Add(new Vector2(xMin, yMax));
                                    uvs.Add(new Vector2(xMax, yMax));
                                    uvs.Add(new Vector2(xMax, yMin));
                                }
                            }

                            byte bottom;

                            if (y - 1 < 0)
                            {
                                bottom = 1;
                            }
                            else
                            {
                                bottom = chunkSlice[x, y - 1, z];
                            }

                            if (bottom == 0)
                            {
                                if (WorldBehaviour.mode == 2)
                                {
                                    spawnBrick(block, new Vector3(x, y, z));
                                }
                                else if (WorldBehaviour.mode == 3)
                                {
                                    addBrickFace("bottom", block, x, y, z);
                                }
                                else
                                {
                                    int vertexIndex = vertices.Count;
                                    vertices.Add(new Vector3(x, y, z + 1));
                                    vertices.Add(new Vector3(x, y, z));
                                    vertices.Add(new Vector3(x + 1, y, z));
                                    vertices.Add(new Vector3(x + 1, y, z + 1));

                                    triangles.Add(vertexIndex);
                                    triangles.Add(vertexIndex + 1);
                                    triangles.Add(vertexIndex + 2);

                                    triangles.Add(vertexIndex + 2);
                                    triangles.Add(vertexIndex + 3);
                                    triangles.Add(vertexIndex);

                                    colors.Add(bottomColor);
                                    colors.Add(bottomColor);
                                    colors.Add(bottomColor);
                                    colors.Add(bottomColor);

                                    Rect  coords = BlockUVs.GetUVFromTypeAndFace((BlockType)block, BlockFace.Bottom);
                                    float yMax   = coords.y + coords.height - epsilon;
                                    float xMax   = coords.x + coords.width - epsilon;
                                    float xMin   = coords.x + epsilon;
                                    float yMin   = coords.y + epsilon;

                                    uvs.Add(new Vector2(xMin, yMin));
                                    uvs.Add(new Vector2(xMin, yMax));
                                    uvs.Add(new Vector2(xMax, yMax));
                                    uvs.Add(new Vector2(xMax, yMin));
                                }
                            }
                        }
                    }
                }

                /*watch.Stop();
                 * long elapsedPreMesh = watch.ElapsedMilliseconds;
                 * watch.Start();*/


                ChunkSliceBuildEntry chunkEntry = new ChunkSliceBuildEntry();
                chunkEntry.Vertices    = vertices.ToArray();
                chunkEntry.Triangles   = triangles.ToArray();
                chunkEntry.Colors      = colors.ToArray();
                chunkEntry.Uvs         = uvs.ToArray();
                chunkEntry.ParentChunk = chunk;
                chunkEntry.SliceIndex  = i;

                chunkEntry.ColliderVertices  = colliderVertices.ToArray();
                chunkEntry.ColliderTriangles = colliderTriangles.ToArray();

                if (WorldBehaviour.mode == 2)
                {
                    Dictionary <byte, Vector3[]> meshList = new Dictionary <byte, Vector3[]>();
                    foreach (byte block in meshes.Keys)
                    {
                        meshList.Add(block, meshes[block].ToArray());
                    }

                    chunkEntry.meshes = meshList;
                }

                vertices.Clear();
                triangles.Clear();
                colors.Clear();
                uvs.Clear();
                meshes.Clear();
                added.Clear();

                colliderVertices.Clear();
                colliderTriangles.Clear();

                lock (WorldBehaviour.ChunkQueueLock)
                    WorldBehaviour.ChunkSlicesToBuild.Enqueue(chunkEntry);

                //watch.Stop();
                //elapsedPostSet = watch.ElapsedMilliseconds;

                /*UnityEngine.Debug.Log("Elapsed Mesh Prepare " + elapsedPreMesh + "ms");
                 * UnityEngine.Debug.Log("Elapsed Mesh Build " + (elapsedPostMesh - elapsedPreMesh) + "ms");
                 * UnityEngine.Debug.Log("Elapsed Mesh Set " + (elapsedPostSet - elapsedPostMesh) + "ms");
                 * UnityEngine.Debug.Log("Total Elapsed " + (elapsedPostSet));*/
            }
            if (indexesToDelete.Count > 0)
            {
                lock (WorldBehaviour.SliceLock)
                {
                    ChunkSlicesDeleteEntry chunkSliceEntry = new ChunkSlicesDeleteEntry();
                    chunkSliceEntry.indexesToDelete = indexesToDelete.ToArray();
                    chunkSliceEntry.parentChunk     = chunk;

                    WorldBehaviour.SlicesToDelete.Enqueue(chunkSliceEntry);
                }
            }
            //watch.Stop();
            //UnityEngine.Debug.Log ("Total Elapsed " + ((double)watch.ElapsedTicks / (double)Stopwatch.Frequency) + "ms");
        }
Exemple #3
0
        // muertet
        public void BuildChunkSliceMesh(ChunkSliceBuildEntry chunkEntry)
        {
            GameObject chunkSliceObject = chunkEntry.ParentChunk.ChunkSliceObjects[chunkEntry.SliceIndex];
            MeshFilter filter           = chunkSliceObject.GetComponent <MeshFilter>();

            if (mode == 2)
            {
                List <CombineInstance> combinedMeshes = new List <CombineInstance>();

                foreach (byte block in chunkEntry.meshes.Keys)
                {
                    List <CombineInstance> combined = new List <CombineInstance>();

                    foreach (Vector3 pos in chunkEntry.meshes[block])
                    {
                        Matrix4x4 matrix = new Matrix4x4();
                        matrix.SetColumn(0, obj.right);
                        matrix.SetColumn(1, obj.up);
                        matrix.SetColumn(2, obj.forward);
                        matrix.SetColumn(3, new Vector4(pos.x, pos.y, pos.z, 1));

                        CombineInstance combine = new CombineInstance();
                        combine.mesh      = cubeMesh;
                        combine.transform = matrix;

                        combined.Add(combine);
                    }

                    Mesh combinedMesh = new Mesh();
                    combinedMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
                    try {
                        combinedMesh.CombineMeshes(combined.ToArray());

                        CombineInstance blockCombined = new CombineInstance();
                        blockCombined.mesh      = combinedMesh;
                        blockCombined.transform = chunkSliceObject.transform.localToWorldMatrix;
                        combinedMeshes.Add(blockCombined);
                    } catch (Exception e) {
                        Debug.Log("Fail " + e.Message);
                        chunkEntry.ParentChunk.ClearDirtySlices();
                        return;
                    }
                }

                try {
                    Mesh finalMesh = new Mesh();
                    finalMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
                    finalMesh.CombineMeshes(combinedMeshes.ToArray(), false);

                    filter.mesh = finalMesh;
                } catch (Exception e) {
                    Debug.Log("Fail " + e.Message);
                    chunkEntry.ParentChunk.ClearDirtySlices();
                    return;
                }
            }
            else
            {
                // Build the Mesh:
                Mesh mesh = new Mesh();

                if (chunkEntry.Vertices.Length > 65535)
                {
                    mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
                }

                mesh.vertices = chunkEntry.Vertices;
                //mesh.SetIndices(chunkEntry.Triangles, MeshTopology.Quads, 0);

                mesh.triangles = chunkEntry.Triangles;

                mesh.uv = chunkEntry.Uvs;

                mesh.colors = chunkEntry.Colors;

                mesh.RecalculateNormals();
                mesh.RecalculateBounds();

                filter.mesh = mesh;

                // generate a much simpler collider mesh
                mesh           = new Mesh();
                mesh.vertices  = chunkEntry.ColliderVertices;
                mesh.triangles = chunkEntry.ColliderTriangles;

                mesh.RecalculateNormals();
                mesh.RecalculateBounds();

                chunkSliceObject.GetComponent <MeshCollider>().sharedMesh = mesh;
            }
            chunkEntry.ParentChunk.ClearDirtySlices();
        }