public void RebuildMesh()
    {
        ChunkLightmap lightmap = _world.GetLightmap(_chunk.Key);

        var appearances = new System.Collections.Generic.Dictionary <BlockType, BlockAppearance>();

        // air
        appearances.Add(BlockType.Empty, new BlockAppearance());
        // stone
        BlockAppearance tmp = new BlockAppearance();

        for (int i = 0; i < 6; i++)
        {
            tmp.UVRects[i] = _atlas.Rects[0];
            tmp.Colors[i]  = new Color(0.4f, 0.4f, 0.4f);
        }
        appearances.Add(new BlockType(2), tmp);
        // dirt
        tmp = new BlockAppearance();
        for (int i = 0; i < 6; i++)
        {
            if (i != (int)BlockFace.Top)
            {
                tmp.UVRects[i] = _atlas.Rects[1];
            }
            else
            {
                tmp.UVRects[i] = _atlas.Rects[3];
            }
        }
        appearances.Add(new BlockType(1), tmp);
        // grass
        tmp = new BlockAppearance();
        for (int i = 0; i < 6; i++)
        {
            tmp.UVRects[i] = _atlas.Rects[2];
        }
        tmp.UVRects[(int)BlockFace.Top]    = _atlas.Rects[4];
        tmp.UVRects[(int)BlockFace.Bottom] = _atlas.Rects[1];

        appearances.Add(new BlockType(3), tmp);

        Profiler.BeginSample("RebuildMesh");
        for (int x = 0; x < 16; x++)
        {
            for (int y = 0; y < 16; y++)
            {
                for (int z = 0; z < 16; z++)
                {
                    BlockType block = _chunk.GetBlock(x, y, z);
                    if (block.isTransparent() == false && _chunk.IsBlockVisible(x, y, z))
                    {
                        BlockAppearance appearance;
                        if (!appearances.TryGetValue(block, out appearance))
                        {
                            appearance = new BlockAppearance();
                        }

                        CubeBuilder.buildCube(_meshBuilder, new Vector3i(x, y, z), _chunk, lightmap, appearance);
                    }
                }
            }
        }

        _mesh.Clear();
        _meshBuilder.BuildMesh(_mesh);
        _meshBuilder.Clear();
        _dirty = false;
        Profiler.EndSample();
    }
Exemple #2
0
    public static void buildCube(MeshBuilder mb, Vector3i pos, Chunk chunk, ChunkLightmap lightmap, BlockAppearance appearance)
    {
        // FIXME foo...
        Color brown = new Color(0.65f, 0.4f, 0.2f);
        //Color[] foo = {brown*0.8f, brown*0.8f, Color.green, brown*0.5f, brown, brown};
        //Color[] foo = {brown, brown, Color.green, brown, brown, brown};

        BlockType block = chunk.GetBlock(pos);

        for (int i = 0; i < 6; i++)
        {
            if (!chunk.IsBlockFaceVisible(pos, (BlockFace)i))
            {
                continue;
            }

            Rect  UVs  = appearance.UVRects[i];
            Color tint = appearance.Colors[i];

            Vector3i normal = cubeNormals[i];

            mb.UVs.Add(new Vector2(UVs.xMin, UVs.yMin));
            mb.UVs.Add(new Vector2(UVs.xMax, UVs.yMin));
            mb.UVs.Add(new Vector2(UVs.xMin, UVs.yMax));
            mb.UVs.Add(new Vector2(UVs.xMax, UVs.yMax));

            float[] ao = new float[4];

            for (int v = 0; v < 4; v++)
            {
                Vector3i vertex = cubeVertices[cubeFaces[i, v]];

                // for sake of simplicity, get diagonal light value too even though it could be blocked by the two adjacent blocks
                if (i == 0 || i == 1)
                {
                    // x
                    ao[v] = lightmap.GetLightValue(pos + new Vector3i(-1 + normal.x + 1, -1 + vertex.y, -1 + vertex.z)) +
                            lightmap.GetLightValue(pos + new Vector3i(-1 + normal.x + 1, -1 + vertex.y + 1, -1 + vertex.z)) +
                            lightmap.GetLightValue(pos + new Vector3i(-1 + normal.x + 1, -1 + vertex.y, -1 + vertex.z + 1)) +
                            lightmap.GetLightValue(pos + new Vector3i(-1 + normal.x + 1, -1 + vertex.y + 1, -1 + vertex.z + 1));
                }
                else if (i == 2 || i == 3)
                {
                    // y
                    ao[v] = lightmap.GetLightValue(pos + new Vector3i(-1 + vertex.x, -1 + normal.y + 1, -1 + vertex.z)) +
                            lightmap.GetLightValue(pos + new Vector3i(-1 + vertex.x + 1, -1 + normal.y + 1, -1 + vertex.z)) +
                            lightmap.GetLightValue(pos + new Vector3i(-1 + vertex.x, -1 + normal.y + 1, -1 + vertex.z + 1)) +
                            lightmap.GetLightValue(pos + new Vector3i(-1 + vertex.x + 1, -1 + normal.y + 1, -1 + vertex.z + 1));
                }
                else
                {
                    // z
                    ao[v] = lightmap.GetLightValue(pos + new Vector3i(-1 + vertex.x, -1 + vertex.y, -1 + normal.z + 1)) +
                            lightmap.GetLightValue(pos + new Vector3i(-1 + vertex.x + 1, -1 + vertex.y, -1 + normal.z + 1)) +
                            lightmap.GetLightValue(pos + new Vector3i(-1 + vertex.x, -1 + vertex.y + 1, -1 + normal.z + 1)) +
                            lightmap.GetLightValue(pos + new Vector3i(-1 + vertex.x + 1, -1 + vertex.y + 1, -1 + normal.z + 1));
                }
                vertex += pos;

                mb.Vertices.Add((Vector3)vertex);
                mb.Normals.Add((Vector3)normal);

                float aoFactor = Mathf.Clamp(ao[v], 0, 4);
                aoFactor /= 4;

                Color color = tint * aoFactor;

                mb.Colors32.Add(color);
            }
            // prefer the bright edge in the middle, suitable for outdoors but bad for drastic light level transitions into darkness
            if (ao[0] + ao[3] < ao[1] + ao[2])
            {
                mb.AddTriangle(-2, -3, -4);
                mb.AddTriangle(-3, -2, -1);
            }
            else
            {
                mb.AddTriangle(-2, -1, -4);
                mb.AddTriangle(-1, -3, -4);
            }
        }
    }