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; }
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); } }
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); } }
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); }
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); }
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); }
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); }