Esempio n. 1
0
        public static void PlaceStructure(Structure structure, Vector3I position, bool eraseSolid = false)
        {
            Vector3I shift   = structure.Root;
            Vector3I origin  = position - shift;
            Vector3I extents = structure.Size;

            ConcurrentDictionary <Vector2I, Chunk> chunkCache = new ConcurrentDictionary <Vector2I, Chunk>();

            ushort[] blocks = structure.Blocks;

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

            Parallel.For(0, blocks.Length, i =>
            {
                WMath.FlatTo3D(i, extents.X, extents.Y, out int localX, out int localY, out int localZ);

                Vector3I globalBpos = new Vector3I(localX, localY, localZ) + origin;

                GlobalToLocal(globalBpos, out Vector2I cpos, out Vector3I bpos);

                Chunk c;
                if (!chunkCache.TryGetValue(cpos, out c))
                {
                    c = GetChunk(cpos, "winecrash:overworld");
                    chunkCache.TryAdd(cpos, c);
                }

                if (c && (eraseSolid || c.GetBlockIndex(bpos.X, bpos.Y, bpos.Z) == airID))
                {
                    c.SetBlock(bpos.X, bpos.Y, bpos.Z, blocks[i]);
                }
            });
Esempio n. 2
0
        private static ushort[] Populate(Vector2I chunkCoords, ushort[] indices, Vector3I[] surfaces)
        {
            double treeDensity = 0.005D;

            int chunkHash = chunkCoords.GetHashCode() * Seed.Value;

            Random    treeRandom = new Random(chunkHash);
            Structure tree       = Structure.Get("Tree");

            ushort dirtID  = ItemCache.GetIndex("winecrash:dirt");
            ushort grassID = ItemCache.GetIndex("winecrash:grass");
            ushort debugID = ItemCache.GetIndex("winecrash:direction");

            // do trees
            for (int i = 0; i < surfaces.Length; i++)
            {
                int  flatten = WMath.Flatten3D(surfaces[i].X, surfaces[i].Y, surfaces[i].Z, Chunk.Width, Chunk.Height);
                bool doTree  = treeRandom.NextDouble() < treeDensity;

                if ((indices[flatten] == dirtID || indices[flatten] == grassID) && doTree)
                {
                    indices[flatten] = dirtID;

                    PlaceStructure(tree, LocalToGlobal(chunkCoords, new Vector3D(surfaces[i].X, surfaces[i].Y + 1, surfaces[i].Z)), false);
                }
            }

            return(indices);
        }
Esempio n. 3
0
        public Structure(string name, Vector3I size, Vector3I root, string[] palette, int[] data) : base(name)
        {
            this.Size = size;
            this.Root = root;

            ushort[] paletteIDs = new ushort[palette.Length];
            _Blocks = new ushort[data.Length];

            //create palette ids
            for (int i = 0; i < palette.Length; i++)
            {
                paletteIDs[i] = ItemCache.GetIndex(palette[i]);
            }

            //create blocks
            for (int i = 0; i < data.Length; i++)
            {
                _Blocks[i] = paletteIDs[data[i]];
            }

            _Cache.Add(this);
        }
Esempio n. 4
0
        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);
            }
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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);
        }
Esempio n. 7
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);
        }
Esempio n. 8
0
        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);
        }