public unsafe void SaveChunk(BlockTerrain.Chunk chunk) { if (!chunk.isEdited) { return; } lock (locker) { Point2 p = new Point2(chunk.chunkx, chunk.chunky); long value; if (chunkOffsets.TryGetValue(p, out value)) { stream.Seek(value, SeekOrigin.Begin); WriteChunkHeader(stream, chunk.chunkx, chunk.chunky); fixed(byte *bptr = &buffer[0]) { int *iptr = (int *)bptr; for (int x = 0; x < 16; x++) { for (int y = 0; y < 16; y++) { int index = BlockTerrain.GetCellIndex(15 - x, 0, y); int h = 0; while (h < 128) { *iptr = chunk.GetCellValue(index); iptr++; h++; index++; } } } } stream.Write(buffer, 0, 131072); fixed(byte *bptr = &buffer[0]) { int *iptr = (int *)bptr; for (int x = 0; x < 16; x++) { int index = BlockTerrain.GetShiftIndex(15 - x, 0); int h = 0; while (h < 16) { *iptr = chunk.GetShiftValue(index); iptr++; h++; index++; } } } stream.Write(buffer, 0, 1024); } } }
public void GenerateNormalBlocks(BlockTerrain.Chunk chunk) { bool[] isTransparent = BlocksData.IsTransparent; INormalBlock[] normalBlocks = BlocksData.NormalBlocks; for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { for (int y = 0; y < 128; y++) { int value = chunk.GetCellValue(x, y, z); int content = BlockTerrain.GetContent(value); if (isTransparent[content]) { normalBlocks[content].GenerateTerrain(x, y, z, value, chunk, this); } } } } }
public void GenerateCubeBlocks(BlockTerrain.Chunk chunk) { bool[] isTransparent = BlocksData.IsTransparent; IStandardCubeBlock[] cubeBlocks = BlocksData.StandardCubeBlocks; INormalBlock[] normalBlocks = BlocksData.NormalBlocks; for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { for (int y = 0; y < 128; y++) { int value = chunk.GetCellValue(x, y, z); int content = BlockTerrain.GetContent(value); if (isTransparent[content]) { normalBlocks[content].GenerateTerrain(x, y, z, value, chunk, this); } else { Vector3 v000 = new Vector3(x, y, z); Vector3 v001 = new Vector3(x, y, z + 1.0f); Vector3 v010 = new Vector3(x, y + 1.0f, z); Vector3 v011 = new Vector3(x, y + 1.0f, z + 1.0f); Vector3 v100 = new Vector3(x + 1.0f, y, z); Vector3 v101 = new Vector3(x + 1.0f, y, z + 1.0f); Vector3 v110 = new Vector3(x + 1.0f, y + 1.0f, z); Vector3 v111 = new Vector3(x + 1.0f, y + 1.0f, z + 1.0f); var cellFace = new CellFace(); var block = cubeBlocks[content]; int neighbor = chunk.GetCellContent(x - 1, y, z); if (neighbor != BlockTerrain.NULL_BLOCK_CONTENT && BlocksData.IsTransparent[neighbor]) { block.GenerateTerrain(x, y, z, value, CellFace.BACK, chunk, ref cellFace); Terrain.NormalQuad(v000, v001, v011, v010, cellFace.TextureSlot, cellFace.Color); } neighbor = chunk.GetCellContent(x, y - 1, z); if (neighbor != BlockTerrain.NULL_BLOCK_CONTENT && BlocksData.IsTransparent[neighbor]) { block.GenerateTerrain(x, y, z, value, CellFace.BOTTOM, chunk, ref cellFace); Terrain.NormalQuad(v001, v000, v100, v101, cellFace.TextureSlot, cellFace.Color); } neighbor = chunk.GetCellContent(x, y, z - 1); if (neighbor != BlockTerrain.NULL_BLOCK_CONTENT && BlocksData.IsTransparent[neighbor]) { block.GenerateTerrain(x, y, z, value, CellFace.LEFT, chunk, ref cellFace); Terrain.NormalQuad(v100, v000, v010, v110, cellFace.TextureSlot, cellFace.Color); } neighbor = chunk.GetCellContent(x + 1, y, z); if (neighbor != BlockTerrain.NULL_BLOCK_CONTENT && BlocksData.IsTransparent[neighbor]) { block.GenerateTerrain(x, y, z, value, CellFace.FRONT, chunk, ref cellFace); Terrain.NormalQuad(v101, v100, v110, v111, cellFace.TextureSlot, cellFace.Color); } neighbor = chunk.GetCellContent(x, y + 1, z); if (neighbor != BlockTerrain.NULL_BLOCK_CONTENT && BlocksData.IsTransparent[neighbor]) { block.GenerateTerrain(x, y, z, value, CellFace.TOP, chunk, ref cellFace); Terrain.NormalQuad(v011, v111, v110, v010, cellFace.TextureSlot, cellFace.Color); } neighbor = chunk.GetCellContent(x, y, z + 1); if (neighbor != BlockTerrain.NULL_BLOCK_CONTENT && BlocksData.IsTransparent[neighbor]) { block.GenerateTerrain(x, y, z, value, CellFace.RIGHT, chunk, ref cellFace); Terrain.NormalQuad(v001, v101, v111, v011, cellFace.TextureSlot, cellFace.Color); } } } } } }
public void GenerateChunkMesh(BlockTerrain.Chunk chunk) { bool[] isTrans = BlocksData.IsTransparent; IStandardCubeBlock[] blocks = BlocksData.StandardCubeBlocks; CellFace[] mask; int u, v, n, w, h, j, i, l, k; int[] off; int[] x; int[] dim = new int[] { 16, 128, 16 }; for (int d = 0; d < 3; d++) { off = new int[] { 0, 0, 0 }; x = new int[] { 0, 0, 0 }; u = (d + 1) % 3; v = (d + 2) % 3; off[d] = 1; //face = d; mask = new CellFace[dim[u] * dim[v]]; for (x[d] = -1; x[d] < dim[d];) { //Debug.LogFormat("x[d]: {0}", x[d]); for (n = 0; n < mask.Length; n++) { mask[n].TextureSlot = -1; } n = 0; for (x[v] = 0; x[v] < dim[v]; x[v]++) { for (x[u] = 0; x[u] < dim[u]; x[u]++) { int va = chunk.GetCellValue(x[0], x[1], x[2]); int vb = chunk.GetCellValue(x[0] + off[0], x[1] + off[1], x[2] + off[2]); if (va == BlockTerrain.NULL_BLOCK_VALUE || vb == BlockTerrain.NULL_BLOCK_VALUE) { break; } int ca = BlockTerrain.GetContent(va); int cb = BlockTerrain.GetContent(vb); //Debug.LogFormat("{0} and {1}: {2}, {3}", new Point3(x[0], x[1], x[2]), new Point3(x[0] + off[0], x[1] + off[1], x[2] + off[2]), a.Name, b.Name); if (isTrans[ca]) { if (!isTrans[cb] && (((x[0] + off[0])) & 16) == 0) { mask[n].IsOpposite = true; blocks[cb].GenerateTerrain(x[0] + off[0], x[1] + off[1], x[2] + off[2], vb, CellFace.opposite[d], chunk, ref mask[n]); } } else { if (isTrans[cb]) { mask[n].IsOpposite = false; blocks[ca].GenerateTerrain(x[0], x[1], x[2], va, d, chunk, ref mask[n]); } } n++; } } ++x[d]; n = 0; for (j = 0; j < dim[v]; j++) { for (i = 0; i < dim[u];) { if (mask[n].TextureSlot != -1) { for (w = 1; i + w < dim[u] && mask[w + n] == mask[n]; w++) { } for (h = 1; h + j < dim[v]; h++) { for (k = 0; k < w; k++) { if (mask[n + k + h * dim[u]] != mask[n]) { goto Done; } } } Done: //Debug.LogFormat("quard: {0}, {1}, {2}, {3}; {4}", j, i, h, w, x[d]); x[u] = i; x[v] = j; int[] du = new int[] { 0, 0, 0 }; int[] dv = new int[] { 0, 0, 0 }; du[u] = w; dv[v] = h; int textureSlot = mask[n].TextureSlot; if (!mask[n].IsOpposite) { Terrain.Quad( new Vector3(x[0], x[1], x[2]), new Vector3(x[0] + du[0], x[1] + du[1], x[2] + du[2]), new Vector3(x[0] + du[0] + dv[0], x[1] + du[1] + dv[1], x[2] + du[2] + dv[2]), new Vector3(x[0] + dv[0], x[1] + dv[1], x[2] + dv[2]), textureSlot, mask[n].Color ); } else { Terrain.Quad( new Vector3(x[0], x[1], x[2]), new Vector3(x[0] + dv[0], x[1] + dv[1], x[2] + dv[2]), new Vector3(x[0] + du[0] + dv[0], x[1] + du[1] + dv[1], x[2] + du[2] + dv[2]), new Vector3(x[0] + du[0], x[1] + du[1], x[2] + du[2]), textureSlot, mask[n].Color ); } for (l = 0; l < h; l++) { for (k = 0; k < w; k++) { mask[n + k + l * dim[u]].TextureSlot = -1; } } i += w; n += w; } else { i++; n++; } } } } } }
public void GenerateFluidTerrain(int x, int y, int z, int value, BlockTerrain.Chunk chunk, GreedyTerrainMesh terrainMesh, Color topColor, Color sideColor) { float height1, height2, height3, height4; int data = BlockTerrain.GetData(value); if (GetIsTop(data)) { int cellValueFast = chunk.GetCellValue(x - 1, y, z - 1); int cellValueFast2 = chunk.GetCellValue(x, y, z - 1); int cellValueFast3 = chunk.GetCellValue(x + 1, y, z - 1); int cellValueFast4 = chunk.GetCellValue(x - 1, y, z); int cellValueFast5 = chunk.GetCellValue(x + 1, y, z); int cellValueFast6 = chunk.GetCellValue(x - 1, y, z + 1); int cellValueFast7 = chunk.GetCellValue(x, y, z + 1); int cellValueFast8 = chunk.GetCellValue(x + 1, y, z + 1); float h = CalculateNeighborHeight(cellValueFast); float num = CalculateNeighborHeight(cellValueFast2); float h2 = CalculateNeighborHeight(cellValueFast3); float num2 = CalculateNeighborHeight(cellValueFast4); float num3 = CalculateNeighborHeight(cellValueFast5); float h3 = CalculateNeighborHeight(cellValueFast6); float num4 = CalculateNeighborHeight(cellValueFast7); float h4 = CalculateNeighborHeight(cellValueFast8); float levelHeight = GetLevelHeight(GetLevel(data)); height1 = CalculateFluidVertexHeight(h, num, num2, levelHeight); height2 = CalculateFluidVertexHeight(num, h2, levelHeight, num3); height3 = CalculateFluidVertexHeight(levelHeight, num3, num4, h4); height4 = CalculateFluidVertexHeight(num2, levelHeight, h3, num4); } else { height1 = 1f; height2 = 1f; height3 = 1f; height4 = 1f; } Vector3 v000 = new Vector3(x, y, z); Vector3 v001 = new Vector3(x, y, z + 1f); Vector3 v010 = new Vector3(x, y + height1, z); Vector3 v011 = new Vector3(x, y + height4, z + 1f); Vector3 v100 = new Vector3(x + 1.0f, y, z); Vector3 v101 = new Vector3(x + 1.0f, y, z + 1f); Vector3 v110 = new Vector3(x + 1.0f, y + height2, z); Vector3 v111 = new Vector3(x + 1.0f, y + height3, z + 1f); int v = chunk.GetCellValue(x - 1, y, z); if (v != BlockTerrain.NULL_BLOCK_VALUE && BlockTerrain.GetContent(v) != Index) { terrainMesh.NormalQuad(v001, v011, v010, v000, TextureSlot, sideColor); } v = chunk.GetCellValue(x, y - 1, z); if (v != BlockTerrain.NULL_BLOCK_VALUE && BlockTerrain.GetContent(v) != Index) { terrainMesh.NormalQuad(v000, v100, v101, v001, TextureSlot, sideColor); } v = chunk.GetCellValue(x, y, z - 1); if (v != BlockTerrain.NULL_BLOCK_VALUE && BlockTerrain.GetContent(v) != Index) { terrainMesh.NormalQuad(v000, v010, v110, v100, TextureSlot, sideColor); } v = chunk.GetCellValue(x + 1, y, z); if (v != BlockTerrain.NULL_BLOCK_VALUE && BlockTerrain.GetContent(v) != Index) { terrainMesh.NormalQuad(v100, v110, v111, v101, TextureSlot, sideColor); } v = chunk.GetCellValue(x, y + 1, z); if (v != BlockTerrain.NULL_BLOCK_VALUE && BlockTerrain.GetContent(v) != Index) { terrainMesh.NormalQuad(v111, v110, v010, v011, TextureSlot, topColor); } v = chunk.GetCellValue(x, y, z + 1); if (v != BlockTerrain.NULL_BLOCK_VALUE && BlockTerrain.GetContent(v) != Index) { terrainMesh.NormalQuad(v101, v111, v011, v001, TextureSlot, sideColor); } }