コード例 #1
0
ファイル: ChunkBuilding.cs プロジェクト: Arekva/winecrash
        private void ConstructInternal()
        {
            if (this.Deleted)
            {
                return;
            }

            if (this.Blocks == null)
            {
                BuildEndFrame = true;
                return;
            }

            Stopwatch sw = new Stopwatch();

            sw.Start();
            cwest = WestNeighbor?.Blocks != null;
            if (cwest)
            {
                bwest = new ushort[Chunk.TotalBlocks];
                WestNeighbor.Blocks.CopyTo(bwest, 0);
            }
            ceast = (EastNeighbor?.Blocks != null);
            if (ceast)
            {
                beast = new ushort[Chunk.TotalBlocks];
                EastNeighbor.Blocks.CopyTo(beast, 0);
            }
            cnorth = (NorthNeighbor?.Blocks != null);
            if (cnorth)
            {
                bnorth = new ushort[Chunk.TotalBlocks];
                NorthNeighbor.Blocks.CopyTo(bnorth, 0);
            }
            csouth = (SouthNeighbor?.Blocks != null);
            if (csouth)
            {
                bsouth = new ushort[Chunk.TotalBlocks];
                SouthNeighbor.Blocks.CopyTo(bsouth, 0);
            }

            List <Vector3F> svertices  = new List <Vector3F>(1 << 18);
            List <Vector2F> suv        = new List <Vector2F>(1 << 18);
            List <Vector3F> snormals   = new List <Vector3F>(1 << 18);
            List <uint>     striangles = new List <uint>(1 << 18);
            uint            striangle  = 0;

            List <Vector3F> tvertices  = new List <Vector3F>(1 << 18);
            List <Vector2F> tuv        = new List <Vector2F>(1 << 18);
            List <Vector3F> tnormals   = new List <Vector3F>(1 << 18);
            List <uint>     ttriangles = new List <uint>(1 << 18);
            uint            ttriangle  = 0;

            Stack <BlockFaces> faces = new Stack <BlockFaces>(6);

            Block  block = null;
            ushort index = 0;

            if (this.Deleted)
            {
                return;
            }

            Vector3F thisWP = this.WObject.Position;

            for (int z = 0; z < Depth; z++)
            {
                for (int y = 0; y < Height; y++)
                {
                    for (int x = 0; x < Width; x++)
                    {
                        if (this.Deleted)
                        {
                            return;
                        }

                        index = this.Blocks[x + Width * y + Width * Height * z];

                        if (!constructblocks.TryGetValue(index, out block))
                        {
                            block = ItemCache.Get <Block>(index);
                            constructblocks.Add(index, block);
                        }

                        if (block.Identifier == "winecrash:air")
                        {
                            continue;                                      // ignore if air
                        }
                        bool transparent = block.Transparent;

                        if (block.DrawAllSides)
                        {
                            faces.Push(BlockFaces.Up);    // up
                            faces.Push(BlockFaces.Down);  // down
                            faces.Push(BlockFaces.West);  // west
                            faces.Push(BlockFaces.East);  // east
                            faces.Push(BlockFaces.North); // north
                            faces.Push(BlockFaces.South); // south
                        }
                        else
                        {
                            if (IsTransparent(block, x, y + 1, z, constructblocks))
                            {
                                faces.Push(BlockFaces.Up);                                                     // up
                            }
                            if (IsTransparent(block, x, y - 1, z, constructblocks))
                            {
                                faces.Push(BlockFaces.Down);                                                     // down
                            }
                            if (IsTransparent(block, x - 1, y, z, constructblocks))
                            {
                                faces.Push(BlockFaces.West);                                                     // west
                            }
                            if (IsTransparent(block, x + 1, y, z, constructblocks))
                            {
                                faces.Push(BlockFaces.East);                                                     // east
                            }
                            if (IsTransparent(block, x, y, z + 1, constructblocks))
                            {
                                faces.Push(BlockFaces.North);                                                     // north
                            }
                            if (IsTransparent(block, x, y, z - 1, constructblocks))
                            {
                                faces.Push(BlockFaces.South);                                                     // south
                            }
                        }

                        foreach (BlockFaces face in faces)
                        {
                            CreateVerticesCube(x, y, z, face, transparent ? tvertices : svertices);

                            /*int count = usedvertices.Count;
                             * for (int i = count - 6; i < count; i++)
                             * {
                             *  Vector3F worldPos = thisWP + usedvertices[i] - new Vector3F(572, 0, 459);
                             *
                             *  Vector3F final = worldPos.RotateAround(new Vector3F(0,-360, 0), new Quaternion(worldPos.X * 0.1,0,worldPos.Z * 0.1));
                             *
                             *
                             *  final += new Vector3F(572, 0, 459);
                             *  usedvertices[i] = final - thisWP;
                             * }*/

                            CreateUVsCube(face, transparent ? tuv : suv, index);

                            CreateNormalsCube(face, transparent ? tnormals : snormals);

                            if (transparent)
                            {
                                ttriangles.AddRange(new uint[6]
                                {
                                    ttriangle, ttriangle + 1, ttriangle + 2, ttriangle + 3, ttriangle + 4, ttriangle + 5
                                });

                                ttriangle += 6;
                            }
                            else
                            {
                                striangles.AddRange(new uint[6]
                                {
                                    striangle, striangle + 1, striangle + 2, striangle + 3, striangle + 4, striangle + 5
                                });

                                striangle += 6;
                            }
                        }

                        faces.Clear();
                    }
                }
            }


            sw.Stop();

            Debug.Log("Chunk build time: " + sw.Elapsed.TotalMilliseconds.ToString("F2") + "ms");

            if (svertices.Count != 0)
            {
                if (this.SolidRenderer.Mesh == null)
                {
                    this.SolidRenderer.Mesh = new Mesh("Chunk Mesh");
                }

                this.SolidRenderer.Mesh.Vertices  = svertices.ToArray();
                this.SolidRenderer.Mesh.Triangles = striangles.ToArray();
                this.SolidRenderer.Mesh.UVs       = suv.ToArray();
                this.SolidRenderer.Mesh.Normals   = snormals.ToArray();
                this.SolidRenderer.Mesh.Tangents  = new Vector4F[svertices.Count];

                this.SolidRenderer.Mesh.Apply(true);
            }
            else
            {
                this.SolidRenderer.Mesh?.Delete();
                this.SolidRenderer.Mesh = null;
            }
            if (tvertices.Count != 0)
            {
                if (this.TransparentRenderer.Mesh == null)
                {
                    this.TransparentRenderer.Mesh = new Mesh("Chunk Transparent Mesh");
                }

                this.TransparentRenderer.Mesh.Vertices  = tvertices.ToArray();
                this.TransparentRenderer.Mesh.Triangles = ttriangles.ToArray();
                this.TransparentRenderer.Mesh.UVs       = tuv.ToArray();
                this.TransparentRenderer.Mesh.Normals   = tnormals.ToArray();
                this.TransparentRenderer.Mesh.Tangents  = new Vector4F[tvertices.Count];

                this.TransparentRenderer.Mesh.Apply(true);
            }
            else
            {
                this.TransparentRenderer.Mesh?.Delete();
                this.TransparentRenderer.Mesh = null;
            }

            svertices  = null;
            striangles = null;
            suv        = null;
            snormals   = null;

            tvertices  = null;
            ttriangles = null;
            tuv        = null;
            tnormals   = null;

            cwest  = ceast = cnorth = csouth = false;
            bsouth = null;
            bnorth = null;
            beast  = null;
            bwest  = null;

            ConstructedOnce = true;
        }
コード例 #2
0
ファイル: Cube.cs プロジェクト: Arekva/winecrash
        internal override Mesh BuildModel()
        {
            if (this.Texture)
            {
                return(base.BuildModel());
            }
            else
            {
                float nbItems = ItemCache.TotalItems;
                float iindex  = ItemCache.GetIndex(this.Identifier);

                float yPercent = iindex;

                Vector2F shift = new Vector2F(0, yPercent);
                Vector2F scale = new Vector2D(1F / 6F, 1F / nbItems);

                Vector2F[] uvs = new Vector2F[36]
                {
                    // up
                    new Vector2F(scale.X * 2, scale.Y * yPercent),
                    new Vector2F(scale.X * 2, scale.Y * (yPercent + 1)),
                    new Vector2F(scale.X * 3, scale.Y * yPercent),
                    new Vector2F(scale.X * 3, scale.Y * yPercent),
                    new Vector2F(scale.X * 2, scale.Y * (yPercent + 1)),
                    new Vector2F(scale.X * 3, scale.Y * (yPercent + 1)),

                    // down
                    new Vector2F(scale.X * 4, scale.Y * (yPercent + 1)),
                    new Vector2F(scale.X * 4, scale.Y * yPercent),
                    new Vector2F(scale.X * 3, scale.Y * (yPercent + 1)),
                    new Vector2F(scale.X * 3, scale.Y * (yPercent + 1)),
                    new Vector2F(scale.X * 4, scale.Y * yPercent),
                    new Vector2F(scale.X * 3, scale.Y * yPercent),

                    // west
                    new Vector2F(scale.X * 2, scale.Y * yPercent),
                    new Vector2F(scale.X * 1, scale.Y * yPercent),
                    new Vector2F(scale.X * 2, scale.Y * (yPercent + 1)),
                    new Vector2F(scale.X * 2, scale.Y * (yPercent + 1)),
                    new Vector2F(scale.X * 1, scale.Y * yPercent),
                    new Vector2F(scale.X * 1, scale.Y * (yPercent + 1)),

                    // east
                    new Vector2F(scale.X * 1, scale.Y * (yPercent + 1)),
                    new Vector2F(scale.X * 1, scale.Y * yPercent),
                    new Vector2F(scale.X * 0, scale.Y * (yPercent + 1)),
                    new Vector2F(scale.X * 0, scale.Y * (yPercent + 1)),
                    new Vector2F(scale.X * 1, scale.Y * yPercent),
                    new Vector2F(scale.X * 0, scale.Y * yPercent),

                    // north
                    new Vector2F(scale.X * 5, scale.Y * yPercent),
                    new Vector2F(scale.X * 4, scale.Y * yPercent),
                    new Vector2F(scale.X * 5, scale.Y * (yPercent + 1)),
                    new Vector2F(scale.X * 5, scale.Y * (yPercent + 1)),
                    new Vector2F(scale.X * 4, scale.Y * yPercent),
                    new Vector2F(scale.X * 4, scale.Y * (yPercent + 1)),

                    // south
                    new Vector2F(scale.X * 6, scale.Y * (yPercent + 1)),
                    new Vector2F(scale.X * 6, scale.Y * yPercent),
                    new Vector2F(scale.X * 5, scale.Y * (yPercent + 1)),
                    new Vector2F(scale.X * 5, scale.Y * (yPercent + 1)),
                    new Vector2F(scale.X * 6, scale.Y * yPercent),
                    new Vector2F(scale.X * 5, scale.Y * yPercent),
                };

                Mesh m = new Mesh(this.Identifier + " 3D Render [Cube]")
                {
                    Vertices  = _CubeVertices,
                    UVs       = uvs,
                    Normals   = _CubeNormals,
                    Triangles = _CubeIndices,
                    Tangents  = new Vector4F[36]
                };
                m.Apply(true);

                return(m);
            }
        }
コード例 #3
0
ファイル: ChunkBuilding.cs プロジェクト: Arekva/winecrash
        private bool IsTransparent(Block currentBlock, int x, int y, int z, Dictionary <ushort, Block> cache)
        {
            //if outside world, yes
            if (y < 0 || y > 255)
            {
                return(true);
            }

            if (x < 0) // check west neighbor
            {
                if (cwest)
                {
                    transpid = this.bwest[15 + Width * y + Width * Height * z];
                }
            }

            else if (x > 15) // check east neighbor
            {
                if (ceast)
                {
                    transpid = this.beast[0 + Width * y + Width * Height * z];
                }
            }

            else if (z > 15) //check south neighbor
            {
                if (cnorth)
                {
                    transpid = this.bnorth[x + Width * y + Width * Height * 0];
                }
            }

            else if (z < 0)
            {
                if (csouth)
                {
                    transpid = this.bsouth[x + Width * y + Width * Height * 15];
                }
            }

            else
            {
                transpid = this.GetBlockIndex(x, y, z);
            }

            if (!cache.TryGetValue(transpid, out transblock))
            {
                transblock = ItemCache.Get <Block>(transpid);
                cache.Add(transpid, transblock);
            }


            if (currentBlock == transblock)
            {
                return(transblock.Transparent && transblock.DrawInternalFaces);
            }
            else
            {
                return(transblock.Transparent);
            }
        }
コード例 #4
0
ファイル: World.cs プロジェクト: Arekva/winecrash
        private static ushort[] PaintLandmass(Vector2I chunkCoords, ushort[] indices, out Vector3I[] surfaces)
        {
            ushort airID     = ItemCache.GetIndex("winecrash:air");
            ushort stoneID   = ItemCache.GetIndex("winecrash:stone");
            ushort grassID   = ItemCache.GetIndex("winecrash:grass");
            ushort dirtID    = ItemCache.GetIndex("winecrash:dirt");
            ushort sandID    = ItemCache.GetIndex("winecrash:sand");
            ushort waterID   = ItemCache.GetIndex("winecrash:water");
            ushort bedrockID = ItemCache.GetIndex("winecrash:bedrock");

            //ushort[] indices = new ushort[Chunk.Width * Chunk.Height * Chunk.Depth];

            Vector3F shift = Vector3F.Zero;

            Vector3F basePos = new Vector3F((chunkCoords.X * Chunk.Width) + shift.X, shift.Y, (chunkCoords.Y * Chunk.Depth) + shift.Z);

            ConcurrentBag <Vector3I> allSurfaces = new ConcurrentBag <Vector3I>();

            // for each x and z, for y from top to bottom:
            for (int i = 0; i < Chunk.Width * Chunk.Depth; i++)
            {
                //Parallel.For(0, Chunk.Width /** Chunk.Height*/ * Chunk.Depth, i =>
                //{
                // get the x / z position
                WMath.FlatTo2D(i, Chunk.Width, out int x, out int z);

                int  surfaceHeight = Chunk.Height - 1;
                bool heightFound   = false;
                for (int y = Chunk.Height - 1; y > -1; y--)
                {
                    int idx = WMath.Flatten3D(x, y, z, Chunk.Width, Chunk.Height);


                    // if height already have been found, check back if
                    // there is a surface or not (3D terrain, like grass under arches or so)
                    if (heightFound)
                    {
                        if (indices[idx] == airID) // if air found, reset height
                        {
                            surfaceHeight = y;
                            heightFound   = false;
                        }
                    }
                    else
                    {
                        surfaceHeight = y;
                        if (indices[idx] != airID)
                        {
                            heightFound = true;
                            allSurfaces.Add(new Vector3I(x, y, z));
                        }
                    }

                    // second pass: check the difference between surface and
                    // the current block height.
                    if (heightFound)
                    {
                        int deltaHeight = surfaceHeight - y;

                        bool ocean = surfaceHeight < 64;

                        // surface => grass
                        if (deltaHeight == 0)
                        {
                            indices[idx] = ocean ? sandID : grassID;
                        }
                        // dirt, under the grass
                        else if (deltaHeight < 3)
                        {
                            indices[idx] = ocean ? sandID : dirtID;
                        }
                    }

                    if (y < 64 && indices[idx] == airID)
                    {
                        indices[idx] = waterID;
                    }

                    if (y < 3)
                    {
                        double chance = Winecrash.Random.NextDouble();

                        if (y == 2 && chance < 0.33)
                        {
                            indices[idx] = bedrockID;
                        }
                        else if (y == 1 && chance < 0.66)
                        {
                            indices[idx] = bedrockID;
                        }
                        else if (y == 0)
                        {
                            indices[idx] = bedrockID;
                        }
                    }
                }

                //Vector3F finalPos = new Vector3F((basePos.X + x) * baseLandmassScale, basePos.Y + y,
                //    (basePos.Z + z) * baseLandmassScale) * globalScale;
                //});
            }

            surfaces = allSurfaces.ToArray();

            return(indices);
        }
コード例 #5
0
ファイル: World.cs プロジェクト: Arekva/winecrash
        private static ushort[] GenerateLandmass(Vector2I chunkCoords)
        {
            float globalScale = 1.0F;

            float baseLandmassScale = 0.005F; // lower => wider. yeah ik.
            float detailBias        = 0.0F;

            float oceanLevel         = 63;
            float landDeformity      = 40;
            float oceanDeformity     = 20;
            float landMaxHeight      = oceanLevel + landDeformity;
            float oceanMaxDepth      = oceanLevel - oceanDeformity;
            float mountainsDeformity = 10;
            float moutainsScale      = 0.01F;

            float maxLevel = 63 + 40;

            // this is meant to be used as a 2D base for continents     apparently unused \/
            IModule3D baseLandmass = new ImprovedPerlin(World.Seed.Value, NoiseQuality.Best);
            var       billow       = new Billow
            {
                Primitive3D = baseLandmass,
                OctaveCount = 5.0F,
                Frequency   = 0.9F,
            };
            IModule3D detailsLandmass = new ImprovedPerlin(World.Seed.Value * 123456, NoiseQuality.Best);

            detailsLandmass = new ScaleBias(detailsLandmass, .2F, detailBias);
            baseLandmass    = new Add(billow, detailsLandmass);
            //LibNoise.Modifier.Exponent baseLandExp = new Exponent(baseLandmass, 1.0F);

            //var combiner = new LibNoise.Combiner.Add(baseLandmass1, baseLandmass1);
            float oceanCoverage = 0.5F;

            ushort airID   = ItemCache.GetIndex("winecrash:air");
            ushort stoneID = ItemCache.GetIndex("winecrash:stone");

            ushort[] indices = new ushort[Chunk.Width * Chunk.Height * Chunk.Depth];

            Vector3F shift = Vector3F.Zero;

            Vector3F basePos = new Vector3F((chunkCoords.X * Chunk.Width) + shift.X, shift.Y, (chunkCoords.Y * Chunk.Depth) + shift.Z);

            for (int i = 0; i < Chunk.Width * Chunk.Height * Chunk.Depth; i++)
            {
                //Parallel.For(0, Chunk.Width * Chunk.Height * Chunk.Depth, i =>
                //{
                indices[i] = airID;

                // get, from index, the x,y,z coordinates of the block. Then move it from the basePos x scale.
                WMath.FlatTo3D(i, Chunk.Width, Chunk.Height, out int x, out int y, out int z);

                if (y > maxLevel)
                {
                    continue;
                }

                Vector3F finalPos = new Vector3F((basePos.X + x) * baseLandmassScale, basePos.Y + y,
                                                 (basePos.Z + z) * baseLandmassScale) * globalScale;

                float landMassPct = baseLandmass.GetValue(finalPos.X, 0, finalPos.Z);
                // retreive the 2D base land value (as seen from top). If under land cap, it's ocean.
                bool isLand = landMassPct > oceanCoverage;

                float landPct  = (float)Math.Pow(WMath.Remap(landMassPct, oceanCoverage, 1.0F, 0.0F, 1.0F), 2F);
                float waterPct = WMath.Remap(landMassPct, 0.0F, oceanCoverage, 0.0F, 1.0F);

                float landMassHeight      = oceanLevel + (landPct * landDeformity);
                int   finalLandMassHeight = (int)landMassHeight;

                float waterHeight      = oceanMaxDepth + (waterPct * oceanDeformity);
                int   finalWaterHeight = (int)waterHeight;

                if (isLand)
                {
                    if (y < finalLandMassHeight)
                    {
                        indices[i] = stoneID;
                    }
                }
                else if (y == oceanLevel - 1)
                {
                    //indices[i] = waterID;
                }
                else if (y < oceanLevel - 1)
                {
                    if (y > finalWaterHeight)
                    {
                        //indices[i] = waterID;
                    }
                    else
                    {
                        indices[i] = stoneID;
                    }
                }


                // debug: display this as grass / sand.


                //indices[i] = y == 63 ? (isLand ? grassID : sandID) : (y > 63 ? airID : debugID);//debug.GetValue(finalPos.X, finalPos.Y, finalPos.Z) < cap ? stoneID : airID;
                //});
            }

            return(indices);
        }
コード例 #6
0
        public ushort[] LoadBlocks()
        {
            ushort[] blocks     = new ushort[Chunk.Width * Chunk.Height * Chunk.Depth];
            int      chunkindex = 0;

            for (int z = 0; z < Chunk.Depth; z++)
            {
                for (int y = 0; y < Chunk.Height; y++)
                {
                    for (int x = 0; x < Chunk.Width; x++)
                    {
                        blocks[x + Chunk.Width * y + Chunk.Width * Chunk.Height * z] = ItemCache.GetIndex(Palette[Indices[chunkindex++]]);
                    }
                }
            }

            return(blocks);
        }
コード例 #7
0
ファイル: Item.cs プロジェクト: Arekva/winecrash
        internal virtual Mesh BuildModel()
        {
            if (this.Identifier == "winecrash:air")
            {
                return(PlayerEntity.PlayerRightArmMesh);
            }

            Texture texture = this.Texture ?? Texture.Blank;

            List <Vector3F> vertices  = new List <Vector3F>();
            List <Vector2F> uvs       = new List <Vector2F>();
            List <Vector3F> normals   = new List <Vector3F>();
            List <uint>     triangles = new List <uint>();

            Stack <BlockFaces> faces = new Stack <BlockFaces>(6);
            uint   triangle          = 0;
            Block  block             = null;
            ushort index             = 0;

            Vector3F deltas = new Vector3F(1.0F / texture.Size.X, 1.0F / texture.Size.Y);

            deltas.Z = Math.Min(deltas.X, deltas.Y);


            float nbItems = ItemCache.TotalItems;
            float iindex  = ItemCache.GetIndex(this.Identifier);

            float yPercent = iindex;


            Vector2F shift = new Vector2F(0, yPercent);
            Vector2F scale = new Vector2D(1F / 6F, 1F / nbItems);

            Vector3F up      = Vector3F.Up;
            Vector3F down    = Vector3F.Down;
            Vector3F left    = Vector3F.Left;
            Vector3F right   = Vector3F.Right;
            Vector3F forward = Vector3F.Forward;
            Vector3F south   = Vector3F.Backward;

            void CreateUVs(float minXPos, float minYPos, BlockFaces face)
            {
                float maxXPos = minXPos + deltas.X;
                float maxYPos = minYPos + deltas.Y;

                switch (face)
                {
                case BlockFaces.Up:
                {
                    uvs.AddRange(new[]
                        {
                            new Vector2F(minXPos, minYPos + yPercent) * scale, //0
                            new Vector2F(minXPos, maxYPos + yPercent) * scale, //incr
                            new Vector2F(maxXPos, minYPos + yPercent) * scale, //2

                            new Vector2F(maxXPos, minYPos + yPercent) * scale, //3
                            new Vector2F(minXPos, maxYPos + yPercent) * scale, //4
                            new Vector2F(maxXPos, maxYPos + yPercent) * scale, //5
                        });
                }
                break;

                case BlockFaces.Down:
                {
                    uvs.AddRange(new[]
                        {
                            new Vector2F(maxXPos, maxYPos + yPercent) * scale, //top left
                            new Vector2F(maxXPos, minYPos + yPercent) * scale, //bottom left
                            new Vector2F(minXPos, maxYPos + yPercent) * scale, //top right

                            new Vector2F(minXPos, maxYPos + yPercent) * scale, //top right
                            new Vector2F(maxXPos, minYPos + yPercent) * scale, //bottom left
                            new Vector2F(maxXPos, minYPos + yPercent) * scale, //top left
                        });
                }
                break;

                case BlockFaces.North:
                {
                    uvs.AddRange(new[]
                        {
                            new Vector2F(maxXPos, minYPos + yPercent) * scale, //5
                            new Vector2F(minXPos, minYPos + yPercent) * scale, //4
                            new Vector2F(maxXPos, maxYPos + yPercent) * scale, //3

                            new Vector2F(maxXPos, maxYPos + yPercent) * scale, //2
                            new Vector2F(minXPos, minYPos + yPercent) * scale, //incr
                            new Vector2F(minXPos, maxYPos + yPercent) * scale, //0
                        });
                }
                break;

                case BlockFaces.South:
                {
                    uvs.AddRange(new[]
                        {
                            new Vector2F(maxXPos, maxYPos + yPercent) * scale, //0 topleft
                            new Vector2F(maxXPos, minYPos + yPercent) * scale, //2 bottom left
                            new Vector2F(minXPos, maxYPos + yPercent) * scale, //incr top right

                            new Vector2F(minXPos, maxYPos + yPercent) * scale, // 4 top right
                            new Vector2F(maxXPos, minYPos + yPercent) * scale, //3 bottom left
                            new Vector2F(minXPos, minYPos + yPercent) * scale, //5 bottom right
                        });
                }
                break;


                case BlockFaces.West:
                {
                    uvs.AddRange(new[]
                        {
                            new Vector2F(maxXPos, minYPos + yPercent) * scale, //5
                            new Vector2F(minXPos, minYPos + yPercent) * scale, //4
                            new Vector2F(maxXPos, maxYPos + yPercent) * scale, //3

                            new Vector2F(maxXPos, maxYPos + yPercent) * scale, //2
                            new Vector2F(minXPos, minYPos + yPercent) * scale, //incr
                            new Vector2F(minXPos, maxYPos + yPercent) * scale, //0
                        });
                }
                break;

                case BlockFaces.East:
                {
                    uvs.AddRange(new[]
                        {
                            new Vector2F(maxXPos, maxYPos + yPercent) * scale, //5
                            new Vector2F(maxXPos, minYPos + yPercent) * scale, //3
                            new Vector2F(minXPos, maxYPos + yPercent) * scale, //4

                            new Vector2F(minXPos, maxYPos + yPercent) * scale, //incr
                            new Vector2F(maxXPos, minYPos + yPercent) * scale, //2
                            new Vector2F(minXPos, minYPos + yPercent) * scale, //0
                        });
                }
                break;
                }
            }

            void CreateVertices(float minXPos, float minYPos, BlockFaces face)
            {
                float maxXPos    = minXPos + deltas.X;
                float maxYPos    = minYPos + deltas.Y;
                float halfZdelta = deltas.Z / 2.0F;

                const float scaleFactor = 1.5F;

                switch (face)
                {
                case BlockFaces.Up:
                {
                    vertices.AddRange(new[]
                        {
                            new Vector3F(minXPos - 0.5F, maxYPos - 0.5F, -halfZdelta) * scaleFactor,
                            new Vector3F(minXPos - 0.5F, maxYPos - 0.5F, halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, maxYPos - 0.5F, -halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, maxYPos - 0.5F, -halfZdelta) * scaleFactor,
                            new Vector3F(minXPos - 0.5F, maxYPos - 0.5F, halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, maxYPos - 0.5F, halfZdelta) * scaleFactor
                        });
                }
                break;

                case BlockFaces.Down:
                {
                    vertices.AddRange(new[]
                        {
                            new Vector3F(minXPos - 0.5F, minYPos - 0.5F, halfZdelta) * scaleFactor,
                            new Vector3F(minXPos - 0.5F, minYPos - 0.5F, -halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, minYPos - 0.5F, halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, minYPos - 0.5F, halfZdelta) * scaleFactor,
                            new Vector3F(minXPos - 0.5F, minYPos - 0.5F, -halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, minYPos - 0.5F, -halfZdelta) * scaleFactor
                        });
                }
                break;

                case BlockFaces.West:
                {
                    vertices.AddRange(new[]
                        {
                            new Vector3F(minXPos - 0.5F, minYPos - 0.5F, -halfZdelta) * scaleFactor,
                            new Vector3F(minXPos - 0.5F, minYPos - 0.5F, halfZdelta) * scaleFactor,
                            new Vector3F(minXPos - 0.5F, maxYPos - 0.5F, -halfZdelta) * scaleFactor,
                            new Vector3F(minXPos - 0.5F, maxYPos - 0.5F, -halfZdelta) * scaleFactor,
                            new Vector3F(minXPos - 0.5F, minYPos - 0.5F, halfZdelta) * scaleFactor,
                            new Vector3F(minXPos - 0.5F, maxYPos - 0.5F, halfZdelta) * scaleFactor
                        });
                }
                break;

                case BlockFaces.East:
                {
                    vertices.AddRange(new[]
                        {
                            new Vector3F(maxXPos - 0.5F, maxYPos - 0.5F, halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, minYPos - 0.5F, halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, maxYPos - 0.5F, -halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, maxYPos - 0.5F, -halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, minYPos - 0.5F, halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, minYPos - 0.5F, -halfZdelta) * scaleFactor
                        });
                }
                break;

                case BlockFaces.North:
                {
                    vertices.AddRange(new[]
                        {
                            new Vector3F(minXPos - 0.5F, minYPos - 0.5F, halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, minYPos - 0.5F, halfZdelta) * scaleFactor,
                            new Vector3F(minXPos - 0.5F, maxYPos - 0.5F, halfZdelta) * scaleFactor,
                            new Vector3F(minXPos - 0.5F, maxYPos - 0.5F, halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, minYPos - 0.5F, halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, maxYPos - 0.5F, halfZdelta) * scaleFactor
                        });
                }
                break;

                case BlockFaces.South:
                {
                    vertices.AddRange(new[]
                        {
                            new Vector3F(maxXPos - 0.5F, maxYPos - 0.5F, -halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, minYPos - 0.5F, -halfZdelta) * scaleFactor,
                            new Vector3F(minXPos - 0.5F, maxYPos - 0.5F, -halfZdelta) * scaleFactor,
                            new Vector3F(minXPos - 0.5F, maxYPos - 0.5F, -halfZdelta) * scaleFactor,
                            new Vector3F(maxXPos - 0.5F, minYPos - 0.5F, -halfZdelta) * scaleFactor,
                            new Vector3F(minXPos - 0.5F, minYPos - 0.5F, -halfZdelta) * scaleFactor
                        });
                }
                break;
                }
            }

            void CreateNormals(BlockFaces face)
            {
                switch (face)
                {
                case BlockFaces.Up:
                {
                    normals.AddRange(new[]
                        {
                            up, up, up, up, up, up
                        });
                }
                break;

                case BlockFaces.Down:
                {
                    normals.AddRange(new[]
                        {
                            down, down, down, down, down, down
                        });
                }
                break;

                case BlockFaces.West:
                {
                    normals.AddRange(new[]
                        {
                            left, left, left, left, left, left
                        });
                }
                break;

                case BlockFaces.East:
                {
                    normals.AddRange(new[]
                        {
                            right, right, right, right, right, right
                        });
                }
                break;

                case BlockFaces.North:
                {
                    normals.AddRange(new[]
                        {
                            forward, forward, forward, forward, forward, forward
                        });
                }
                break;

                case BlockFaces.South:
                {
                    normals.AddRange(new[]
                        {
                            south, south, south, south, south, south
                        });
                }
                break;
                }
            }

            for (int y = 0; y < texture.Size.Y; y++)
            {
                for (int x = 0; x < texture.Size.X; x++)
                {
                    if (!IsTransparent(texture, x, y))
                    {
                        float xminpos = deltas.X * x;
                        float yminpos = deltas.Y * y;

                        float xmaxpos = xminpos + deltas.X;
                        float xmaspos = yminpos + deltas.Y;

                        if (IsTransparent(texture, x, y + 1))
                        {
                            faces.Push(BlockFaces.Up);
                        }
                        if (IsTransparent(texture, x, y - 1))
                        {
                            faces.Push(BlockFaces.Down);
                        }
                        if (IsTransparent(texture, x - 1, y))
                        {
                            faces.Push(BlockFaces.West);
                        }
                        if (IsTransparent(texture, x + 1, y))
                        {
                            faces.Push(BlockFaces.East);
                        }

                        faces.Push(BlockFaces.North);
                        faces.Push(BlockFaces.South);

                        foreach (BlockFaces face in faces)
                        {
                            CreateVertices(xminpos, yminpos, face);
                            CreateUVs(xminpos, yminpos, face);
                            CreateNormals(face);

                            triangles.AddRange(new uint[6]
                            {
                                triangle, triangle + 1, triangle + 2, triangle + 3, triangle + 4, triangle + 5
                            });
                            triangle += 6;
                        }

                        faces.Clear();
                    }
                }
            }

            Mesh mesh = null;

            if (vertices.Count != 0)
            {
                mesh = new Mesh(this.Identifier + " 3D Render [Standard]")
                {
                    Vertices  = vertices.ToArray(),
                    Triangles = triangles.ToArray(),
                    UVs       = uvs.ToArray(),
                    Normals   = normals.ToArray(),
                    Tangents  = new Vector4F[vertices.Count]
                };

                mesh.Apply(true);
            }

            vertices  = null;
            triangles = null;
            uvs       = null;
            normals   = null;

            return(mesh);
        }