public override void BuildBlock(Chunk chunk, Vector3Int localPos, Vector3Int globalPos) { WorldBlocks blocks = chunk.world.blocks; for (int d = 0; d < 6; d++) { Direction dir = DirectionUtils.Get(d); Block adjacentBlock = blocks.GetBlock(globalPos.Add(dir)); if (CanBuildFaceWith(adjacentBlock, dir)) { BuildFace(chunk, localPos, globalPos, dir); } } }
public override void BuildBlock(Chunk chunk, Vector3Int localPos, Vector3Int globalPos) { Rect texture; RenderGeometryBatcher batcher = chunk.GeometryHandler.Batcher; WorldBlocks blocks = chunk.world.blocks; for (int d = 0; d < 6; d++) { Direction dir = DirectionUtils.Get(d); if (!connectedMeshConfig.directionalTris.ContainsKey(dir)) { continue; } if (connectedMeshConfig.connectsToSolid && blocks.GetBlock(globalPos + dir).IsSolid(DirectionUtils.Opposite(dir))) { texture = connectedMeshConfig.texture.GetTexture(chunk, localPos, globalPos, dir); batcher.AddMeshData(connectedMeshConfig.directionalTris[dir], connectedMeshConfig.directionalVerts[dir], texture, localPos); } else if (connectedMeshConfig.connectsToTypes.Length != 0) { int neighborType = blocks.Get(globalPos.Add(dir)).Type; for (int i = 0; i < connectedMeshConfig.connectsToTypes.Length; i++) { if (neighborType == connectedMeshConfig.connectsToTypes[i]) { texture = connectedMeshConfig.texture.GetTexture(chunk, localPos, globalPos, dir); batcher.AddMeshData(connectedMeshConfig.directionalTris[dir], connectedMeshConfig.directionalVerts[dir], texture, localPos); break; } } } } texture = customMeshConfig.texture.GetTexture(chunk, localPos, globalPos, Direction.down); batcher.AddMeshData(customMeshConfig.tris, customMeshConfig.verts, texture, localPos); }
public void Build(Chunk chunk, int minX, int maxX, int minY, int maxY, int minZ, int maxZ) { WorldBlocks blocks = chunk.world.blocks; const int stepSize = 1; const int width = Env.ChunkSize; int[] mins = { minX, minY, minZ }; int[] maxes = { maxX, maxY, maxZ }; int[] x = { 0, 0, 0 }; // Relative position of a block int[] q = { 0, 0, 0 }; // Direction in which we compare neighbors when building mask (q[d] is our current direction) int[] du = { 0, 0, 0 }; // Width in a given dimension (du[u] is our current dimension) int[] dv = { 0, 0, 0 }; // Height in a given dimension (dv[v] is our current dimension) bool[] mask = chunk.pools.PopBoolArray(width * width); Vector3[] vecs = chunk.pools.PopVector3Array(4); // Iterate over 3 dimensions. Once for front faces, once for back faces for (int dd = 0; dd < 2 * 3; dd++) { int d = dd % 3; int u = (d + 1) % 3; int v = (d + 2) % 3; x[0] = 0; x[1] = 0; x[2] = 0; q[0] = 0; q[1] = 0; q[2] = 0; q[d] = stepSize; // Determine which side we're meshing Direction dir = Direction.west; switch (dd) { // Back faces //case 0: dir = Direction.west; break; case 1: dir = Direction.down; break; case 2: dir = Direction.south; break; // Front faces case 3: dir = Direction.east; break; case 4: dir = Direction.up; break; case 5: dir = Direction.north; break; } bool backFace = DirectionUtils.Backface(dir); // Move through the dimension from front to back for (x[d] = mins[d] - 1; x[d] <= maxes[d];) { // Compute the mask int n = 0; for (x[v] = 0; x[v] < mins[v]; x[v]++) { for (x[u] = 0; x[u] < width; x[u]++) { mask[n++] = false; } } for (x[v] = mins[v]; x[v] <= maxes[v]; x[v]++) { for (x[u] = 0; x[u] < mins[u]; x[u]++) { mask[n++] = false; } for (x[u] = mins[u]; x[u] <= maxes[u]; x[u]++) { int realX = chunk.pos.x + x[0]; int realY = chunk.pos.y + x[1]; int realZ = chunk.pos.z + x[2]; bool voxelFace0 = blocks.GetBlock(new Vector3Int(realX, realY, realZ)).canBeWalkedOn; bool voxelFace1 = blocks.GetBlock(new Vector3Int(realX + q[0], realY + q[1], realZ + q[2])).canBeWalkedOn; mask[n++] = (!voxelFace0 || !voxelFace1) && (backFace ? voxelFace1 : voxelFace0); } for (x[u] = maxes[u] + 1; x[u] < width; x[u]++) { mask[n++] = false; } } for (x[v] = maxes[v] + 1; x[v] < width; x[v]++) { for (x[u] = 0; x[u] < width; x[u]++) { mask[n++] = false; } } x[d]++; n = 0; // Build faces from the mask if it's possible int j; for (j = 0; j < width; j++) { int i; for (i = 0; i < width;) { if (mask[n] == false) { i++; n++; continue; } bool type = mask[n]; // Compute width int w; for (w = 1; i + w < width && mask[n + w] == type; w++) { } // Compute height bool done = false; int k; int h; for (h = 1; j + h < width; h++) { for (k = 0; k < w; k++) { if (mask[n + k + h * width] == false || mask[n + k + h * width] != type) { done = true; break; } } if (done) { break; } } // Determine whether we really want to build this face // TODO: Skip bottom faces at the bottom of the world const bool buildFace = true; if (buildFace) { // Prepare face coordinates and dimensions x[u] = i; x[v] = j; du[0] = du[1] = du[2] = 0; dv[0] = dv[1] = dv[2] = 0; du[u] = w; dv[v] = h; // Face vertices transformed to world coordinates // 0--1 // | | // | | // 3--2 vecs[0] = new Vector3(x[0], x[1], x[2]) - BlockUtils.HalfBlockVector; vecs[1] = new Vector3(x[0] + du[0], x[1] + du[1], x[2] + du[2]) - BlockUtils.HalfBlockVector; vecs[2] = new Vector3(x[0] + du[0] + dv[0], x[1] + du[1] + dv[1], x[2] + du[2] + dv[2]) - BlockUtils.HalfBlockVector; vecs[3] = new Vector3(x[0] + dv[0], x[1] + dv[1], x[2] + dv[2]) - BlockUtils.HalfBlockVector; { LocalPools pool = chunk.pools; VertexData[] vertexData = pool.PopVertexDataArray(4); VertexDataFixed[] vertexDataFixed = pool.PopVertexDataFixedArray(4); { for (int ii = 0; ii < 4; ii++) { vertexData[ii] = pool.PopVertexData(); vertexData[ii].Vertex = vecs[ii]; vertexDataFixed[ii] = VertexDataUtils.ClassToStruct(vertexData[ii]); } chunk.ChunkColliderGeometryHandler.Batcher.AddFace(vertexDataFixed, backFace); for (int ii = 0; ii < 4; ii++) { pool.PushVertexData(vertexData[ii]); } } pool.PushVertexDataFixedArray(vertexDataFixed); pool.PushVertexDataArray(vertexData); } } // Zero out the mask int l; for (l = 0; l < h; ++l) { for (k = 0; k < w; ++k) { mask[n + k + l * width] = false; } } i += w; n += w; } } } } chunk.pools.PushBoolArray(mask); chunk.pools.PushVector3Array(vecs); }
private static void PrepareColors_Slow(Chunk chunk, ref Vector3Int globalPos, VertexData[] vertexData, Direction direction) { bool nSolid = false; bool eSolid = false; bool sSolid = false; bool wSolid = false; bool wnSolid = false; bool neSolid = false; bool esSolid = false; bool swSolid = false; //float light = 0; WorldBlocks blocks = chunk.world.blocks; Block block; switch (direction) { case Direction.up: nSolid = blocks.GetBlock(globalPos.Add(0, 1, 1)).IsSolid(Direction.south); eSolid = blocks.GetBlock(globalPos.Add(1, 1, 0)).IsSolid(Direction.west); sSolid = blocks.GetBlock(globalPos.Add(0, 1, -1)).IsSolid(Direction.north); wSolid = blocks.GetBlock(globalPos.Add(-1, 1, 0)).IsSolid(Direction.east); block = blocks.GetBlock(globalPos.Add(-1, 1, 1)); wnSolid = block.IsSolid(Direction.east) && block.IsSolid(Direction.south); block = blocks.GetBlock(globalPos.Add(1, 1, 1)); neSolid = block.IsSolid(Direction.south) && block.IsSolid(Direction.west); block = blocks.GetBlock(globalPos.Add(1, 1, -1)); esSolid = block.IsSolid(Direction.west) && block.IsSolid(Direction.north); block = blocks.GetBlock(globalPos.Add(-1, 1, -1)); swSolid = block.IsSolid(Direction.north) && block.IsSolid(Direction.east); //light = BlockDataMap.NonSolid.Light(blocks.GetBlock(globalPos.Add(0, 1, 0)))/ 15f; break; case Direction.down: nSolid = blocks.GetBlock(globalPos.Add(0, -1, -1)).IsSolid(Direction.south); eSolid = blocks.GetBlock(globalPos.Add(1, -1, 0)).IsSolid(Direction.west); sSolid = blocks.GetBlock(globalPos.Add(0, -1, 1)).IsSolid(Direction.north); wSolid = blocks.GetBlock(globalPos.Add(-1, -1, 0)).IsSolid(Direction.east); block = blocks.GetBlock(globalPos.Add(-1, -1, -1)); wnSolid = block.IsSolid(Direction.east) && block.IsSolid(Direction.south); block = blocks.GetBlock(globalPos.Add(1, -1, -1)); neSolid = block.IsSolid(Direction.south) && block.IsSolid(Direction.west); block = blocks.GetBlock(globalPos.Add(1, -1, 1)); esSolid = block.IsSolid(Direction.west) && block.IsSolid(Direction.north); block = blocks.GetBlock(globalPos.Add(-1, -1, 1)); swSolid = block.IsSolid(Direction.north) && block.IsSolid(Direction.east); //light = BlockDataMap.NonSolid.Light(blocks.GetBlock(globalPos.Add(0, -1, 0))) / 15f; break; case Direction.north: nSolid = blocks.GetBlock(globalPos.Add(1, 0, 1)).IsSolid(Direction.west); eSolid = blocks.GetBlock(globalPos.Add(0, 1, 1)).IsSolid(Direction.down); sSolid = blocks.GetBlock(globalPos.Add(-1, 0, 1)).IsSolid(Direction.east); wSolid = blocks.GetBlock(globalPos.Add(0, -1, 1)).IsSolid(Direction.up); block = blocks.GetBlock(globalPos.Add(-1, 1, 1)); esSolid = block.IsSolid(Direction.east) && block.IsSolid(Direction.south); block = blocks.GetBlock(globalPos.Add(1, 1, 1)); neSolid = block.IsSolid(Direction.south) && block.IsSolid(Direction.west); block = blocks.GetBlock(globalPos.Add(1, -1, 1)); wnSolid = block.IsSolid(Direction.west) && block.IsSolid(Direction.north); block = blocks.GetBlock(globalPos.Add(-1, -1, 1)); swSolid = block.IsSolid(Direction.north) && block.IsSolid(Direction.east); //light = BlockDataMap.NonSolid.Light(blocks.GetBlock(globalPos.Add(0, 0, 1))) / 15f; break; case Direction.east: nSolid = blocks.GetBlock(globalPos.Add(1, 0, -1)).IsSolid(Direction.up); eSolid = blocks.GetBlock(globalPos.Add(1, 1, 0)).IsSolid(Direction.west); sSolid = blocks.GetBlock(globalPos.Add(1, 0, 1)).IsSolid(Direction.down); wSolid = blocks.GetBlock(globalPos.Add(1, -1, 0)).IsSolid(Direction.east); block = blocks.GetBlock(globalPos.Add(1, 1, 1)); esSolid = block.IsSolid(Direction.west) && block.IsSolid(Direction.north); block = blocks.GetBlock(globalPos.Add(1, 1, -1)); neSolid = block.IsSolid(Direction.south) && block.IsSolid(Direction.west); block = blocks.GetBlock(globalPos.Add(1, -1, -1)); wnSolid = block.IsSolid(Direction.east) && block.IsSolid(Direction.north); block = blocks.GetBlock(globalPos.Add(1, -1, 1)); swSolid = block.IsSolid(Direction.north) && block.IsSolid(Direction.east); //light = BlockDataMap.NonSolid.Light(blocks.GetBlock(globalPos.Add(1, 0, 0))) / 15f; break; case Direction.south: nSolid = blocks.GetBlock(globalPos.Add(-1, 0, -1)).IsSolid(Direction.down); eSolid = blocks.GetBlock(globalPos.Add(0, 1, -1)).IsSolid(Direction.west); sSolid = blocks.GetBlock(globalPos.Add(1, 0, -1)).IsSolid(Direction.up); wSolid = blocks.GetBlock(globalPos.Add(0, -1, -1)).IsSolid(Direction.south); block = blocks.GetBlock(globalPos.Add(1, 1, -1)); esSolid = block.IsSolid(Direction.west) && block.IsSolid(Direction.north); block = blocks.GetBlock(globalPos.Add(-1, 1, -1)); neSolid = block.IsSolid(Direction.south) && block.IsSolid(Direction.west); block = blocks.GetBlock(globalPos.Add(-1, -1, -1)); wnSolid = block.IsSolid(Direction.east) && block.IsSolid(Direction.north); block = blocks.GetBlock(globalPos.Add(1, -1, -1)); swSolid = block.IsSolid(Direction.north) && block.IsSolid(Direction.east); //light = BlockDataMap.NonSolid.Light(blocks.GetBlock(globalPos.Add(0, 0, -1))) / 15f; break; case Direction.west: nSolid = blocks.GetBlock(globalPos.Add(-1, 0, 1)).IsSolid(Direction.up); eSolid = blocks.GetBlock(globalPos.Add(-1, 1, 0)).IsSolid(Direction.west); sSolid = blocks.GetBlock(globalPos.Add(-1, 0, -1)).IsSolid(Direction.down); wSolid = blocks.GetBlock(globalPos.Add(-1, -1, 0)).IsSolid(Direction.east); block = blocks.GetBlock(globalPos.Add(-1, 1, -1)); esSolid = block.IsSolid(Direction.west) && block.IsSolid(Direction.north); block = blocks.GetBlock(globalPos.Add(-1, 1, 1)); neSolid = block.IsSolid(Direction.south) && block.IsSolid(Direction.west); block = blocks.GetBlock(globalPos.Add(-1, -1, 1)); wnSolid = block.IsSolid(Direction.east) && block.IsSolid(Direction.north); block = blocks.GetBlock(globalPos.Add(-1, -1, -1)); swSolid = block.IsSolid(Direction.north) && block.IsSolid(Direction.east); //light = BlockDataMap.NonSolid.Light(blocks.GetBlock(globalPos.Add(-1, 0, 0))) / 15f; break; } if (chunk.world.config.addAOToMesh) { SetColorsAO(vertexData, wnSolid, nSolid, neSolid, eSolid, esSolid, sSolid, swSolid, wSolid, chunk.world.config.ambientOcclusionStrength); } else { SetColors(vertexData, 1, 1, 1, 1, 1); } }