protected bool TrySnowGrowZ(CuboidWithMaterial cub, bool[,,] voxels, bool[,] voxelVisited) { if (cub.Z2 > 15) { return(false); } for (int x = cub.X1; x < cub.X2; x++) { // Stop if // "Floor" is gone, already visited, or there's a voxel above if (!voxels[x, cub.Y1, cub.Z2] || voxelVisited[x, cub.Z2] || (cub.Y2 < 15 && voxels[x, cub.Y2, cub.Z2])) { return(false); } } for (int x = cub.X1; x < cub.X2; x++) { voxelVisited[x, cub.Z2] = true; } cub.Z2++; return(true); }
public static MeshData CreateDecalMesh(ICoreClientAPI coreClientAPI, List <uint> voxelCuboids, ITexPositionSource decalTexSource) { MeshData mesh = new MeshData(24, 36, false).WithColorMaps().WithRenderpasses().WithXyzFaces(); CuboidWithMaterial cwm = tmpCuboid; for (int i = 0; i < voxelCuboids.Count; i++) { FromUint(voxelCuboids[i], cwm); MeshData cuboidmesh = genCube( cwm.X1, cwm.Y1, cwm.Z1, cwm.X2 - cwm.X1, cwm.Y2 - cwm.Y1, cwm.Z2 - cwm.Z1, coreClientAPI, decalTexSource, 0, 0, coreClientAPI.World.GetBlock(0) ); mesh.AddMeshData(cuboidmesh); } return(mesh); }
private bool TryGrowX(CuboidWithMaterial cub, bool[,,] voxels, bool[,,] voxelVisited, byte[,,] voxelMaterial) { if (cub.X2 > 15) { return(false); } for (int y = cub.Y1; y < cub.Y2; y++) { for (int z = cub.Z1; z < cub.Z2; z++) { if (!voxels[cub.X2, y, z] || voxelVisited[cub.X2, y, z] || voxelMaterial[cub.X2, y, z] != cub.Material) { return(false); } } } for (int y = cub.Y1; y < cub.Y2; y++) { for (int z = cub.Z1; z < cub.Z2; z++) { voxelVisited[cub.X2, y, z] = true; } } cub.X2++; return(true); }
public override void RegenSelectionBoxes(IPlayer byPlayer) { // Create a temporary array first, because the offthread particle system might otherwise access a null collisionbox Cuboidf[] selectionBoxesTmp = new Cuboidf[VoxelCuboids.Count]; CuboidWithMaterial cwm = tmpCuboids[0]; totalVoxels = 0; for (int i = 0; i < VoxelCuboids.Count; i++) { FromUint(VoxelCuboids[i], cwm); selectionBoxesTmp[i] = cwm.ToCuboidf(); totalVoxels += cwm.Volume; } selectionBoxes = selectionBoxesTmp; if (byPlayer != null) { RegenSelectionVoxelBoxes(false, byPlayer); } else { selectionBoxesVoxels = null; } }
private bool TryGrowY(CuboidWithMaterial cub, bool[,,] voxels, bool[,,] voxelVisited, byte[,,] voxelMaterial) { if (cub.Y2 > 15) { return(false); } for (int x = cub.X1; x < cub.X2; x++) { for (int z = cub.Z1; z < cub.Z2; z++) { if (!voxels[x, cub.Y2, z] || voxelVisited[x, cub.Y2, z] || voxelMaterial[x, cub.Y2, z] != cub.Material) { return(false); } } } for (int x = cub.X1; x < cub.X2; x++) { for (int z = cub.Z1; z < cub.Z2; z++) { voxelVisited[x, cub.Y2, z] = true; } } cub.Y2++; return(true); }
protected void RotateModel(IPlayer byPlayer, bool clockwise) { List <uint> rotatedCuboids = new List <uint>(); CuboidWithMaterial cwm = tmpCuboid; foreach (var val in VoxelCuboids) { FromUint(val, cwm); Cuboidi rotated = cwm.RotatedCopy(0, clockwise ? 90 : -90, 0, new Vec3d(8, 8, 8)); cwm.Set(rotated.X1, rotated.Y1, rotated.Z1, rotated.X2, rotated.Y2, rotated.Z2); rotatedCuboids.Add(ToCuboid(cwm)); } VoxelCuboids = rotatedCuboids; rotatedCuboids = new List <uint>(); foreach (var val in SnowCuboids) { FromUint(val, cwm); Cuboidi rotated = cwm.RotatedCopy(0, clockwise ? 90 : -90, 0, new Vec3d(8, 8, 8)); cwm.Set(rotated.X1, rotated.Y1, rotated.Z1, rotated.X2, rotated.Y2, rotated.Z2); rotatedCuboids.Add(ToCuboid(cwm)); } SnowCuboids = rotatedCuboids; }
protected void convertToVoxels(out bool[,,] voxels, out byte[,,] materials) { voxels = new bool[16, 16, 16]; materials = new byte[16, 16, 16]; CuboidWithMaterial cwm = tmpCuboid; for (int i = 0; i < VoxelCuboids.Count; i++) { FromUint(VoxelCuboids[i], cwm); for (int dx = cwm.X1; dx < cwm.X2; dx++) { for (int dy = cwm.Y1; dy < cwm.Y2; dy++) { for (int dz = cwm.Z1; dz < cwm.Z2; dz++) { voxels[dx, dy, dz] = true; materials[dx, dy, dz] = cwm.Material; } } } } }
private bool TryGrowZ(CuboidWithMaterial cub, bool[,,] voxels, bool[,,] voxelVisited, byte[,,] voxelMaterial) { if (cub.Z2 > 15) { return(false); } for (int x = cub.X1; x < cub.X2; x++) { for (int y = cub.Y1; y < cub.Y2; y++) { if (!voxels[x, y, cub.Z2] || voxelVisited[x, y, cub.Z2] || voxelMaterial[x, y, cub.Z2] != cub.Material) { return(false); } } } for (int x = cub.X1; x < cub.X2; x++) { for (int y = cub.Y1; y < cub.Y2; y++) { voxelVisited[x, y, cub.Z2] = true; } } cub.Z2++; return(true); }
public static void FromUint(uint val, ref CuboidWithMaterial tocuboid) { tocuboid.X1 = (int)((val) & 15); tocuboid.Y1 = (int)((val >> 4) & 15); tocuboid.Z1 = (int)((val >> 8) & 15); tocuboid.X2 = (int)(((val) >> 12) & 15) + 1; tocuboid.Y2 = (int)(((val) >> 16) & 15) + 1; tocuboid.Z2 = (int)(((val) >> 20) & 15) + 1; tocuboid.Material = (byte)((val >> 24) & 15); }
public static MeshData CreateMesh(ICoreClientAPI coreClientAPI, List <uint> voxelCuboids, int[] materials, BlockPos posForRnd = null) { MeshData mesh = new MeshData(24, 36, false).WithColorMaps().WithRenderpasses().WithXyzFaces(); if (voxelCuboids == null || materials == null) { return(mesh); } CuboidWithMaterial cwm = tmpCuboid; for (int i = 0; i < voxelCuboids.Count; i++) { FromUint(voxelCuboids[i], cwm); Block block = coreClientAPI.World.GetBlock(materials[cwm.Material]); float subPixelPaddingx = coreClientAPI.BlockTextureAtlas.SubPixelPaddingX; float subPixelPaddingy = coreClientAPI.BlockTextureAtlas.SubPixelPaddingY; int altNum = 0; if (block.HasAlternates && posForRnd != null) { int altcount = 0; foreach (var val in block.Textures) { BakedCompositeTexture bct = val.Value.Baked; if (bct.BakedVariants == null) { continue; } altcount = Math.Max(altcount, bct.BakedVariants.Length); } altNum = block.RandomizeAxes == EnumRandomizeAxes.XYZ ? GameMath.MurmurHash3Mod(posForRnd.X, posForRnd.Y, posForRnd.Z, altcount) : GameMath.MurmurHash3Mod(posForRnd.X, 0, posForRnd.Z, altcount); } MeshData cuboidmesh = genCube( cwm.X1, cwm.Y1, cwm.Z1, cwm.X2 - cwm.X1, cwm.Y2 - cwm.Y1, cwm.Z2 - cwm.Z1, coreClientAPI, coreClientAPI.Tesselator.GetTexSource(block, altNum, true), subPixelPaddingx, subPixelPaddingy, block ); mesh.AddMeshData(cuboidmesh); } return(mesh); }
public virtual void RegenSelectionBoxes(IPlayer byPlayer) { // Create a temporary array first, because the offthread particle system might otherwise access a null collisionbox Cuboidf[] selectionBoxesTmp = new Cuboidf[VoxelCuboids.Count]; CuboidWithMaterial cwm = tmpCuboid; for (int i = 0; i < VoxelCuboids.Count; i++) { FromUint(VoxelCuboids[i], cwm); selectionBoxesTmp[i] = cwm.ToCuboidf(); } this.selectionBoxes = selectionBoxesTmp; }
public void RegenSelectionVoxelBoxes(bool mustLoad, IPlayer byPlayer) { if (selectionBoxesVoxels == null && !mustLoad) { return; } HashSet <Cuboidf> boxes = new HashSet <Cuboidf>(); int size = GetChiselSize(byPlayer); if (size <= 0) { size = 16; } float sx = size / 16f; float sy = size / 16f; float sz = size / 16f; CuboidWithMaterial cwm = tmpCuboids[0]; for (int i = 0; i < VoxelCuboids.Count; i++) { FromUint(VoxelCuboids[i], cwm); for (int x1 = cwm.X1; x1 < cwm.X2; x1 += size) { for (int y1 = cwm.Y1; y1 < cwm.Y2; y1 += size) { for (int z1 = cwm.Z1; z1 < cwm.Z2; z1 += size) { float px = (float)Math.Floor((float)x1 / size) * sx; float py = (float)Math.Floor((float)y1 / size) * sy; float pz = (float)Math.Floor((float)z1 / size) * sz; if (px + sx > 1 || py + sy > 1 || pz + sz > 1) { continue; } boxes.Add(new Cuboidf(px, py, pz, px + sx, py + sy, pz + sz)); } } } } selectionBoxesVoxels = boxes.ToArray(); }
private void RebuildCuboidList(bool[,,] Voxels, byte[,,] VoxelMaterial) { bool[,,] VoxelVisited = new bool[16, 16, 16]; // And now let's rebuild the cuboids with some greedy search algo thing VoxelCuboids.Clear(); for (int dx = 0; dx < 16; dx++) { for (int dy = 0; dy < 16; dy++) { for (int dz = 0; dz < 16; dz++) { if (VoxelVisited[dx, dy, dz] || !Voxels[dx, dy, dz]) { continue; } CuboidWithMaterial cub = new CuboidWithMaterial() { Material = VoxelMaterial[dx, dy, dz], X1 = dx, Y1 = dy, Z1 = dz, X2 = dx + 1, Y2 = dy + 1, Z2 = dz + 1 }; // Try grow this cuboid for as long as we can bool didGrowAny = true; while (didGrowAny) { didGrowAny = TryGrowX(cub, Voxels, VoxelVisited, VoxelMaterial) || TryGrowY(cub, Voxels, VoxelVisited, VoxelMaterial) || TryGrowZ(cub, Voxels, VoxelVisited, VoxelMaterial) ; } VoxelCuboids.Add(ToCuboid(cub)); } } } }
protected bool TrySnowGrowX(CuboidWithMaterial cub, bool[,,] voxels, bool[,] voxelVisited) { if (cub.X2 > 15) { return(false); } for (int z = cub.Z1; z < cub.Z2; z++) { if (!voxels[cub.X2, cub.Y1, z] || voxelVisited[cub.X2, z] || (cub.Y2 < 15 && voxels[cub.X2, cub.Y2, z])) { return(false); } } for (int z = cub.Z1; z < cub.Z2; z++) { voxelVisited[cub.X2, z] = true; } cub.X2++; return(true); }
public void OnTransformed(ITreeAttribute tree, int byDegrees, EnumAxis?aroundAxis) { List <uint> rotatedCuboids = new List <uint>(); VoxelCuboids = new List <uint>((tree["cuboids"] as IntArrayAttribute).AsUint); CuboidWithMaterial cwm = tmpCuboid; foreach (var val in VoxelCuboids) { FromUint(val, cwm); Cuboidi rotated = cwm.Clone(); if (aroundAxis == EnumAxis.X) { rotated.X1 = 16 - rotated.X1; rotated.X2 = 16 - rotated.X2; } if (aroundAxis == EnumAxis.Y) { rotated.Y1 = 16 - rotated.Y1; rotated.Y2 = 16 - rotated.Y2; } if (aroundAxis == EnumAxis.Z) { rotated.Z1 = 16 - rotated.Z1; rotated.Z2 = 16 - rotated.Z2; } rotated = rotated.RotatedCopy(0, byDegrees, 0, new Vec3d(8, 8, 8)); cwm.Set(rotated.X1, rotated.Y1, rotated.Z1, rotated.X2, rotated.Y2, rotated.Z2); rotatedCuboids.Add(ToCuboid(cwm)); } tree["cuboids"] = new IntArrayAttribute(rotatedCuboids.ToArray()); }
public bool CanAttachBlockAt(BlockFacing blockFace, Cuboidi attachmentArea = null) { if (attachmentArea == null) { return(sideSolid[blockFace.Index]); } else { HashSet <XYZ> req = new HashSet <XYZ>(); for (int x = attachmentArea.X1; x <= attachmentArea.X2; x++) { for (int y = attachmentArea.Y1; y <= attachmentArea.Y2; y++) { for (int z = attachmentArea.Z1; z <= attachmentArea.Z2; z++) { XYZ vec; switch (blockFace.Index) { case 0: vec = new XYZ(x, y, 0); break; // N case 1: vec = new XYZ(15, y, z); break; // E case 2: vec = new XYZ(x, y, 15); break; // S case 3: vec = new XYZ(0, y, z); break; // W case 4: vec = new XYZ(x, 15, z); break; // U case 5: vec = new XYZ(x, 0, z); break; // D default: vec = new XYZ(0, 0, 0); break; } req.Add(vec); } } } CuboidWithMaterial cwm = tmpCuboid; for (int i = 0; i < VoxelCuboids.Count; i++) { FromUint(VoxelCuboids[i], cwm); for (int x = cwm.X1; x < cwm.X2; x++) { for (int y = cwm.Y1; y < cwm.Y2; y++) { for (int z = cwm.Z1; z < cwm.Z2; z++) { // Early exit if (x != 0 && x != 15 && y != 0 && y != 15 && z != 0 && z != 15) { continue; } req.Remove(new XYZ(x, y, z)); } } } } return(req.Count == 0); } }
protected void RebuildCuboidList(bool[,,] Voxels, byte[,,] VoxelMaterial) { bool[,,] VoxelVisited = new bool[16, 16, 16]; emitSideAo = new bool[] { true, true, true, true, true, true }; sideSolid = new bool[] { true, true, true, true, true, true }; float voxelCount = 0; // And now let's rebuild the cuboids with some greedy search algo thing VoxelCuboids.Clear(); int[] edgeVoxelsMissing = new int[6]; int[] edgeCenterVoxelsMissing = new int[6]; for (int dx = 0; dx < 16; dx++) { for (int dy = 0; dy < 16; dy++) { for (int dz = 0; dz < 16; dz++) { bool isVoxel = Voxels[dx, dy, dz]; // North: Negative Z // East: Positive X // South: Positive Z // West: Negative X // Up: Positive Y // Down: Negative Y if (!isVoxel) { if (dz == 0) { edgeVoxelsMissing[BlockFacing.NORTH.Index]++; if (Math.Abs(dy - 8) < 5 && Math.Abs(dx - 8) < 5) { edgeCenterVoxelsMissing[BlockFacing.NORTH.Index]++; } } if (dx == 15) { edgeVoxelsMissing[BlockFacing.EAST.Index]++; if (Math.Abs(dy - 8) < 5 && Math.Abs(dz - 8) < 5) { edgeCenterVoxelsMissing[BlockFacing.EAST.Index]++; } } if (dz == 15) { edgeVoxelsMissing[BlockFacing.SOUTH.Index]++; if (Math.Abs(dy - 8) < 5 && Math.Abs(dx - 8) < 5) { edgeCenterVoxelsMissing[BlockFacing.SOUTH.Index]++; } } if (dx == 0) { edgeVoxelsMissing[BlockFacing.WEST.Index]++; if (Math.Abs(dy - 8) < 5 && Math.Abs(dz - 8) < 5) { edgeCenterVoxelsMissing[BlockFacing.WEST.Index]++; } } if (dy == 15) { edgeVoxelsMissing[BlockFacing.UP.Index]++; if (Math.Abs(dz - 8) < 5 && Math.Abs(dx - 8) < 5) { edgeCenterVoxelsMissing[BlockFacing.UP.Index]++; } } if (dy == 0) { edgeVoxelsMissing[BlockFacing.DOWN.Index]++; if (Math.Abs(dz - 8) < 5 && Math.Abs(dx - 8) < 5) { edgeCenterVoxelsMissing[BlockFacing.DOWN.Index]++; } } continue; } else { voxelCount++; } if (VoxelVisited[dx, dy, dz]) { continue; } CuboidWithMaterial cub = new CuboidWithMaterial() { Material = VoxelMaterial[dx, dy, dz], X1 = dx, Y1 = dy, Z1 = dz, X2 = dx + 1, Y2 = dy + 1, Z2 = dz + 1 }; // Try grow this cuboid for as long as we can bool didGrowAny = true; while (didGrowAny) { didGrowAny = false; didGrowAny |= TryGrowX(cub, Voxels, VoxelVisited, VoxelMaterial); didGrowAny |= TryGrowY(cub, Voxels, VoxelVisited, VoxelMaterial); didGrowAny |= TryGrowZ(cub, Voxels, VoxelVisited, VoxelMaterial); } VoxelCuboids.Add(ToCuboid(cub)); } } } bool doEmitSideAo = edgeVoxelsMissing[0] < 64 || edgeVoxelsMissing[1] < 64 || edgeVoxelsMissing[2] < 64 || edgeVoxelsMissing[3] < 64; if (absorbAnyLight != doEmitSideAo) { int preva = GetLightAbsorption(); absorbAnyLight = doEmitSideAo; int nowa = GetLightAbsorption(); if (preva != nowa) { Api.World.BlockAccessor.MarkAbsorptionChanged(preva, nowa, Pos); } } for (int i = 0; i < 6; i++) { emitSideAo[i] = doEmitSideAo; sideSolid[i] = edgeCenterVoxelsMissing[i] < 5; } this.emitSideAoByFlags = Block.ResolveAoFlags(this.Block, emitSideAo); this.sizeRel = voxelCount / (16f * 16f * 16f); buildSnowCuboids(Voxels); }
void buildSnowCuboids(bool[,,] Voxels) { SnowCuboids.Clear(); GroundSnowCuboids.Clear(); //if (SnowLevel > 0) - always generate this { bool[,] snowVoxelVisited = new bool[16, 16]; for (int dx = 0; dx < 16; dx++) { for (int dz = 0; dz < 16; dz++) { if (snowVoxelVisited[dx, dz]) { continue; } for (int dy = 15; dy >= 0; dy--) { bool ground = dy == 0; bool solid = ground || Voxels[dx, dy, dz]; if (solid) { CuboidWithMaterial cub = new CuboidWithMaterial() { Material = 0, X1 = dx, Y1 = dy, Z1 = dz, X2 = dx + 1, Y2 = dy + 1, Z2 = dz + 1 }; // Try grow this cuboid for as long as we can bool didGrowAny = true; while (didGrowAny) { didGrowAny = false; didGrowAny |= TrySnowGrowX(cub, Voxels, snowVoxelVisited); didGrowAny |= TrySnowGrowZ(cub, Voxels, snowVoxelVisited); } if (ground) { GroundSnowCuboids.Add(ToCuboid(cub)); } else { SnowCuboids.Add(ToCuboid(cub)); } break; } } } } } }
private uint ToCuboid(CuboidWithMaterial cub) { return((uint)(cub.X1 | (cub.Y1 << 4) | (cub.Z1 << 8) | ((cub.X2 - 1) << 12) | ((cub.Y2 - 1) << 16) | ((cub.Z2 - 1) << 20) | (cub.Material << 24))); }