//private static int getX(int index, int dimension) { // return (y * VERTEX_DIMENSION + z) * VERTEX_DIMENSION + x; //} //private static int getY(int index, int dimension) { // return ((VERTEX_DIMENSION + x) * VERTEX_DIMENSION + z) * VERTEX_DIMENSION + y; //} //private static int getZ(int index, int dimension) { // return ((VERTEX_DIMENSION * 2 + x) * VERTEX_DIMENSION + y) * VERTEX_DIMENSION + z; //} //private static int getDimension(int index) { // return index / (VERTEX_DIMENSION * VERTEX_DIMENSION * VERTEX_DIMENSION); //} private Voxel[, ,] createVoxelArray(VoxelUpdateInfo info) { setDimensions(info); Voxel[, ,] voxels = new Voxel[VERTEX_DIMENSION, VERTEX_DIMENSION, VERTEX_DIMENSION]; for (byte y = (byte)(1 - yExtend); y < yDim; ++y) { for (byte z = (byte)(1 - zExtend); z < zDim; ++z) { voxels[1 - xExtend, y, z] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - xExtend, VOXEL_DIMENSION - 1 + y, VOXEL_DIMENSION - 1 + z).toVoxel(); } } for (byte x = (byte)(2 - xExtend); x < xDim; ++x) { for (byte z = (byte)(1 - zExtend); z < zDim; ++z) { voxels[x, 1 - yExtend, z] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + x, VOXEL_DIMENSION - yExtend, VOXEL_DIMENSION - 1 + z).toVoxel(); } } for (byte x = (byte)(2 - xExtend); x < xDim; ++x) { for (byte y = (byte)(2 - yExtend); y < yDim; ++y) { voxels[x, y, 1 - zExtend] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + x, VOXEL_DIMENSION - 1 + y, VOXEL_DIMENSION - zExtend).toVoxel(); } } return(voxels); }
public VoxelUpdateInfo(VoxelUpdateInfo super, byte xi, byte yi, byte zi) : this() { size = super.size / VoxelBlock.CHILD_DIMENSION; detailLevel = (byte)(super.detailLevel + 1); control = super.control; x = super.x * VoxelBlock.CHILD_DIMENSION + xi; y = super.y * VoxelBlock.CHILD_DIMENSION + yi; z = super.z * VoxelBlock.CHILD_DIMENSION + zi; for (byte xii = 0; xii < DIMENSION; ++xii) { for (byte yii = 0; yii < DIMENSION; ++yii) { for (byte zii = 0; zii < DIMENSION; ++zii) { blocks[xii, yii, zii] = super.getSub(VoxelBlock.CHILD_COUNT_POWER, (byte)(xii + xi + VoxelBlock.CHILD_DIMENSION - 1), (byte)(yii + yi + VoxelBlock.CHILD_DIMENSION - 1), (byte)(zii + zi + VoxelBlock.CHILD_DIMENSION - 1)); renderers[xii, yii, zii] = super.renderers[(int)((xii + xi + 1) * 0.5), (int)((yii + yi + 1) * 0.5), (int)((zii + zi + 1) * 0.5)]; if (renderers[xii, yii, zii] == null || renderers[xii, yii, zii].old) { renderers[xii, yii, zii] = super.blocks[(int)((xii + xi + 1) * 0.5), (int)((yii + yi + 1) * 0.5), (int)((zii + zi + 1) * 0.5)].getRenderer(0, 0, 0, 0); if (renderers[xii, yii, zii] == null || renderers[xii, yii, zii].old) renderers[xii, yii, zii] = blocks[xii, yii, zii].getRenderer(0, 0, 0, 0); if (renderers[xii, yii, zii] != null && renderers[xii, yii, zii].old) renderers[xii, yii, zii] = null; } } } } }
public override void execute() { lock (control) { VoxelUpdateInfo info = control.getBaseUpdateInfo().getSubInfo(detailLevel, xOff, yOff, zOff); getRenderer().genMesh(info); } }
public VoxelUpdateInfo(VoxelUpdateInfo super, byte xi, byte yi, byte zi) : this() { size = super.size / VoxelBlock.CHILD_DIMENSION; detailLevel = (byte)(super.detailLevel + 1); control = super.control; x = super.x * VoxelBlock.CHILD_DIMENSION + xi; y = super.y * VoxelBlock.CHILD_DIMENSION + yi; z = super.z * VoxelBlock.CHILD_DIMENSION + zi; for (byte xii = 0; xii < DIMENSION; ++xii) { for (byte yii = 0; yii < DIMENSION; ++yii) { for (byte zii = 0; zii < DIMENSION; ++zii) { blocks[xii, yii, zii] = super.getSub(VoxelBlock.CHILD_COUNT_POWER, (byte)(xii + xi + VoxelBlock.CHILD_DIMENSION - 1), (byte)(yii + yi + VoxelBlock.CHILD_DIMENSION - 1), (byte)(zii + zi + VoxelBlock.CHILD_DIMENSION - 1)); renderers[xii, yii, zii] = super.renderers[(int)((xii + xi + 1) * 0.5), (int)((yii + yi + 1) * 0.5), (int)((zii + zi + 1) * 0.5)]; if (renderers[xii, yii, zii] == null || renderers[xii, yii, zii].old) { renderers[xii, yii, zii] = super.blocks[(int)((xii + xi + 1) * 0.5), (int)((yii + yi + 1) * 0.5), (int)((zii + zi + 1) * 0.5)].getRenderer(0, 0, 0, 0); if (renderers[xii, yii, zii] == null || renderers[xii, yii, zii].old) { renderers[xii, yii, zii] = blocks[xii, yii, zii].getRenderer(0, 0, 0, 0); } if (renderers[xii, yii, zii] != null && renderers[xii, yii, zii].old) { renderers[xii, yii, zii] = null; } } } } } }
private void alignOtherEdge(VoxelUpdateInfo info, byte x, byte y, byte z) { VoxelRenderer other = info.renderers[1, 1, 1]; if (other == null) { if (info.blocks[1, 1, 1].GetType() == typeof(VoxelBlock)) { byte xStart = (byte)((VoxelBlock.CHILD_DIMENSION - 1) * (2 - x) / 2); byte xEnd = (byte)(1 + (VoxelBlock.CHILD_DIMENSION - 1) * (1 - x / 2)); byte yStart = (byte)((VoxelBlock.CHILD_DIMENSION - 1) * (2 - y) / 2); byte yEnd = (byte)(1 + (VoxelBlock.CHILD_DIMENSION - 1) * (1 - y / 2)); byte zStart = (byte)((VoxelBlock.CHILD_DIMENSION - 1) * (2 - z) / 2); byte zEnd = (byte)(1 + (VoxelBlock.CHILD_DIMENSION - 1) * (1 - z / 2)); for (byte xi = xStart; xi < xEnd; ++xi) { for (byte yi = yStart; yi < yEnd; ++yi) { for (byte zi = zStart; zi < zEnd; ++zi) { alignOtherEdge(new VoxelUpdateInfo(info, xi, yi, zi), x, y, z); } } } } return; } other.addEdge(info, (byte)(2 - x), (byte)(2 - y), (byte)(2 - z)); }
protected void traverse(VoxelUpdateInfo info, byte detailLevel) { int factor = 1 << (detailLevel - VoxelBlock.CHILD_COUNT_POWER); byte xiMin = (byte)Mathf.Max(min.x / factor - info.x * VoxelBlock.CHILD_DIMENSION, 0); byte xiMax = (byte)Mathf.Min((max.x + 3) / factor - info.x * VoxelBlock.CHILD_DIMENSION, VoxelBlock.CHILD_DIMENSION - 1); byte yiMin = (byte)Mathf.Max(min.y / factor - info.y * VoxelBlock.CHILD_DIMENSION, 0); byte yiMax = (byte)Mathf.Min((max.y + 3) / factor - info.y * VoxelBlock.CHILD_DIMENSION, VoxelBlock.CHILD_DIMENSION - 1); byte ziMin = (byte)Mathf.Max(min.z / factor - info.z * VoxelBlock.CHILD_DIMENSION, 0); byte ziMax = (byte)Mathf.Min((max.z + 3) / factor - info.z * VoxelBlock.CHILD_DIMENSION, VoxelBlock.CHILD_DIMENSION - 1); VoxelBlock block = (VoxelBlock)info.blocks[1, 1, 1]; int scale = VoxelBlock.CHILD_DIMENSION << (VoxelBlock.CHILD_COUNT_POWER *(detailLevel)); // MonoBehaviour.print (scale); // MonoBehaviour.print (detailLevel); uint minY = uint.MinValue; uint maxY = uint.MaxValue; foreach(VoxelMask mask in control.masks) { if (mask.active) { if (mask.maskAbove) { if (maxY > mask.yPosition) maxY = mask.yPosition; } else if (minY < mask.yPosition) { minY = mask.yPosition; } } } for (byte xi = xiMin; xi <= xiMax; ++xi) { for (byte yi = yiMin; yi <= yiMax; ++yi) { if ((info.y +yi +1) *scale <= minY || (info.y +yi) *scale >= maxY) { continue; } for (byte zi = ziMin; zi <= ziMax; ++zi) { if (detailLevel <= VoxelBlock.CHILD_COUNT_POWER) { block.children[xi, yi, zi] = modifyVoxel(block.children[xi, yi, zi], info.x * VoxelBlock.CHILD_DIMENSION + xi, info.y * VoxelBlock.CHILD_DIMENSION + yi, info.z * VoxelBlock.CHILD_DIMENSION + zi); } else { if (block.children[xi, yi, zi].GetType() == typeof(Voxel)) { block.children[xi, yi, zi] = new VoxelBlock((Voxel)block.children[xi, yi, zi]); } traverse(new VoxelUpdateInfo(info, xi, yi, zi), (byte)(detailLevel - VoxelBlock.CHILD_COUNT_POWER)); } } } } // TODO: this should check if completely contained, not if rendersize (for distant modifications) - FIXED? if (updateMesh && info != null && (VoxelBlock.isRenderSize(info.size, control) || VoxelBlock.isRenderLod(info.x, info.y, info.z, control.sizes[detailLevel], control))) { block.updateAll(info.x, info.y, info.z, info.detailLevel, control, true); } }
protected void traverse(VoxelUpdateInfo info, byte detailLevel) { int factor = 1 << (detailLevel - VoxelBlock.CHILD_COUNT_POWER); byte xiMin = (byte)Mathf.Max(minX / factor - info.x * VoxelBlock.CHILD_DIMENSION, 0f); byte xiMax = (byte)Mathf.Min((maxX + 1) / factor - info.x * VoxelBlock.CHILD_DIMENSION, VoxelBlock.CHILD_DIMENSION - 1f); byte yiMin = (byte)Mathf.Max(minY / factor - info.y * VoxelBlock.CHILD_DIMENSION, 0f); byte yiMax = (byte)Mathf.Min((maxY + 1) / factor - info.y * VoxelBlock.CHILD_DIMENSION, VoxelBlock.CHILD_DIMENSION - 1f); byte ziMin = (byte)Mathf.Max(minZ / factor - info.z * VoxelBlock.CHILD_DIMENSION, 0f); byte ziMax = (byte)Mathf.Min((maxZ + 1) / factor - info.z * VoxelBlock.CHILD_DIMENSION, VoxelBlock.CHILD_DIMENSION - 1f); VoxelBlock block = (VoxelBlock)info.blocks[1, 1, 1]; uint scale = (uint)(1 << (VoxelBlock.CHILD_COUNT_POWER * (detailLevel - 1))); for (byte yi = yiMin; yi <= yiMax; ++yi) { if ((info.y * VoxelBlock.CHILD_DIMENSION + yi) < maskMinY / scale || (info.y * VoxelBlock.CHILD_DIMENSION + yi) > maskMaxY / scale + 1) { continue; } for (byte xi = xiMin; xi <= xiMax; ++xi) { for (byte zi = ziMin; zi <= ziMax; ++zi) { if (detailLevel <= VoxelBlock.CHILD_COUNT_POWER) { block.children[xi, yi, zi] = modifyVoxel(block.children[xi, yi, zi], info.x * VoxelBlock.CHILD_DIMENSION + xi, info.y * VoxelBlock.CHILD_DIMENSION + yi, info.z * VoxelBlock.CHILD_DIMENSION + zi); } else { if (block.children[xi, yi, zi].GetType() == typeof(Voxel)) { block.children[xi, yi, zi] = new VoxelBlock((Voxel)block.children[xi, yi, zi]); } traverse(new VoxelUpdateInfo(info, xi, yi, zi), (byte)(detailLevel - VoxelBlock.CHILD_COUNT_POWER)); } } } } if (updateMesh && info != null && (VoxelBlock.isRenderSize(info.size, control) || VoxelBlock.isRenderLod(info.x, info.y, info.z, info.size, control))) { //block.clearSubRenderers(control); block.updateAll(info.x, info.y, info.z, info.detailLevel, control, true); } }
public void setFromSister(VoxelUpdateInfo sister, byte xi, byte yi, byte zi) { size = sister.size; detailLevel = sister.detailLevel; control = sister.control; x = sister.x + xi - 1; y = sister.y + yi - 1; z = sister.z + zi - 1; for (byte xii = (byte)(1 - (xi + 1) / 2); xii < DIMENSION - (xi / 2); ++xii) { for (byte yii = (byte)(1 - (yi + 1) / 2); yii < DIMENSION - (yi / 2); ++yii) { for (byte zii = (byte)(1 - (zi + 1) / 2); zii < DIMENSION - (zi / 2); ++zii) { blocks[xii, yii, zii] = sister.blocks[xii + xi - 1, yii + yi - 1, zii + zi - 1]; renderers[xii, yii, zii] = sister.renderers[xii + xi - 1, yii + yi - 1, zii + zi - 1]; } } } }
private void setDimensions(VoxelUpdateInfo info) { if (info.renderers[0, 1, 1] == null) { xExtend = 0; } else { xExtend = 1; } if (info.renderers[1, 0, 1] == null) { yExtend = 0; } else { yExtend = 1; } if (info.renderers[1, 1, 0] == null) { zExtend = 0; } else { zExtend = 1; } xDim = (byte)(VOXEL_DIMENSION + 1); yDim = (byte)(VOXEL_DIMENSION + 1); zDim = (byte)(VOXEL_DIMENSION + 1); if (info.renderers[2, 1, 1] != null && info.renderers[2, 1, 1].size > size * 1.1f) { ++xDim; } if (info.renderers[1, 2, 1] != null && info.renderers[1, 2, 1].size > size * 1.1f) { ++yDim; } if (info.renderers[1, 1, 2] != null && info.renderers[1, 1, 2].size > size * 1.1f) { ++zDim; } }
public void setFromSister(VoxelUpdateInfo sister, byte xi, byte yi, byte zi) { size = sister.size; detailLevel = sister.detailLevel; control = sister.control; x = sister.x + xi - 1; y = sister.y + yi - 1; z = sister.z + zi - 1; for (byte xii = (byte)(1 - (xi + 1) / 2); xii < DIMENSION - (xi / 2); ++xii) { for (byte yii = (byte)(1 - (yi + 1) / 2); yii < DIMENSION - (yi / 2); ++yii) { for (byte zii = (byte)(1 - (zi + 1) / 2); zii < DIMENSION - (zi / 2); ++zii) { blocks[xii, yii, zii] = sister.blocks[xii + xi - 1, yii + yi - 1, zii + zi - 1]; renderers[xii, yii, zii] = sister.renderers[xii + xi - 1, yii + yi - 1, zii + zi - 1]; } } } }
protected void traverse(VoxelUpdateInfo info, byte detailLevel) { int factor = 1 << (detailLevel - VoxelBlock.CHILD_COUNT_POWER); byte xiMin = (byte)Mathf.Max(minX / factor - info.x * VoxelBlock.CHILD_DIMENSION, 0f); byte xiMax = (byte)Mathf.Min((maxX + 1) / factor - info.x * VoxelBlock.CHILD_DIMENSION, VoxelBlock.CHILD_DIMENSION - 1f); byte yiMin = (byte)Mathf.Max(minY / factor - info.y * VoxelBlock.CHILD_DIMENSION, 0f); byte yiMax = (byte)Mathf.Min((maxY + 1) / factor - info.y * VoxelBlock.CHILD_DIMENSION, VoxelBlock.CHILD_DIMENSION - 1f); byte ziMin = (byte)Mathf.Max(minZ / factor - info.z * VoxelBlock.CHILD_DIMENSION, 0f); byte ziMax = (byte)Mathf.Min((maxZ + 1) / factor - info.z * VoxelBlock.CHILD_DIMENSION, VoxelBlock.CHILD_DIMENSION - 1f); VoxelBlock block = (VoxelBlock)info.blocks[1, 1, 1]; uint scale = (uint) (1 << (VoxelBlock.CHILD_COUNT_POWER *(detailLevel -1))); for (byte yi = yiMin; yi <= yiMax; ++yi) { if ((info.y *VoxelBlock.CHILD_DIMENSION +yi) < maskMinY /scale || (info.y *VoxelBlock.CHILD_DIMENSION +yi) > maskMaxY /scale +1) { continue; } for (byte xi = xiMin; xi <= xiMax; ++xi) { for (byte zi = ziMin; zi <= ziMax; ++zi) { if (detailLevel <= VoxelBlock.CHILD_COUNT_POWER) { block.children[xi, yi, zi] = modifyVoxel(block.children[xi, yi, zi], info.x * VoxelBlock.CHILD_DIMENSION + xi, info.y * VoxelBlock.CHILD_DIMENSION + yi, info.z * VoxelBlock.CHILD_DIMENSION + zi); } else { if (block.children[xi, yi, zi].GetType() == typeof(Voxel)) { block.children[xi, yi, zi] = new VoxelBlock((Voxel)block.children[xi, yi, zi]); } traverse(new VoxelUpdateInfo(info, xi, yi, zi), (byte)(detailLevel - VoxelBlock.CHILD_COUNT_POWER)); } } } } if (updateMesh && info != null && (VoxelBlock.isRenderSize(info.size, control) || VoxelBlock.isRenderLod(info.x, info.y, info.z, info.size, control))) { //block.clearSubRenderers(control); block.updateAll(info.x, info.y, info.z, info.detailLevel, control, true); } }
public void genMesh(VoxelUpdateInfo info) { if (control == null) { return; } size = info.size; Queue <int[]> triangleSet = new Queue <int[]>(); vertices = new Dictionary <int, object>(); vertexSubstances = new Dictionary <int, byte>(); Voxel[, ,] voxels = createVoxelArray(info); MarchingCubes.setup(info.size / VOXEL_DIMENSION, control.isoLevel, ref vertices, ref vertexSubstances, ref voxels, position - new Vector3(0.5f, 0.5f, 0.5f) * size / VOXEL_DIMENSION, null); int totalTris = 0; for (byte x = (byte)(1 - xExtend), x1 = (byte)(x + 1); x1 < xDim; x = x1++) { for (byte y = (byte)(1 - yExtend), y1 = (byte)(y + 1); y1 < yDim; y = y1++) { for (byte z = (byte)(1 - zExtend), z1 = (byte)(z + 1); z1 < zDim; z = z1++) { lock (control) { VoxelHolder block = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION + x, VOXEL_DIMENSION + y, VOXEL_DIMENSION + z); voxels[x1, y1, z1] = block.toVoxel(); int[] tris = MarchingCubes.lookupTriangles(x, y, z, x1, y1, z1); if (tris == null) { continue; } triangleSet.Enqueue(tris); totalTris += tris.Length; } } } } if (vertices.Count < 1) { applied = true; return; } List <int> triangles = new List <int>(); List <Vector3> finalVertices = new List <Vector3>(vertices.Count); //List<byte> finalMats = new List<byte>(vertices.Count); while (triangleSet.Count > 0) { int[] triangleList = triangleSet.Dequeue(); for (int i = 0; i < triangleList.Length; ++i) { if (vertices[triangleList[i]].GetType() == typeof(Vector3)) { finalVertices.Add((Vector3)vertices[triangleList[i]]); //finalMats.Add(vertexSubstances[triangleList[i]]); vertices[triangleList[i]] = finalVertices.Count - 1; } triangles.Add((int)vertices[triangleList[i]]); } } VERTS = finalVertices.ToArray(); TRIS = triangles.ToArray(); //MATS = finalMats.ToArray(); calcNorms(); alignEdge(info, 0, 1, 1); alignEdge(info, 2, 1, 1); alignEdge(info, 1, 0, 1); alignEdge(info, 1, 2, 1); alignEdge(info, 1, 1, 0); alignEdge(info, 1, 1, 2); lock (control) { control.enqueueJob(new ApplyMeshJob(this, info.detailLevel, info.x, info.y, info.z)); } }
private void alignOtherEdge(VoxelUpdateInfo info, byte x, byte y, byte z) { VoxelRenderer other = info.renderers[1, 1, 1]; if (other == null) { if (info.blocks[1, 1, 1].GetType() == typeof(VoxelBlock)) { byte xStart = (byte)((VoxelBlock.CHILD_DIMENSION - 1) * (2 - x) / 2); byte xEnd = (byte)(1 + (VoxelBlock.CHILD_DIMENSION - 1) * (1 - x / 2)); byte yStart = (byte)((VoxelBlock.CHILD_DIMENSION - 1) * (2 - y) / 2); byte yEnd = (byte)(1 + (VoxelBlock.CHILD_DIMENSION - 1) * (1 - y / 2)); byte zStart = (byte)((VoxelBlock.CHILD_DIMENSION - 1) * (2 - z) / 2); byte zEnd = (byte)(1 + (VoxelBlock.CHILD_DIMENSION - 1) * (1 - z / 2)); for (byte xi = xStart; xi < xEnd; ++xi) { for (byte yi = yStart; yi < yEnd; ++yi) { for (byte zi = zStart; zi < zEnd; ++zi) { alignOtherEdge(new VoxelUpdateInfo(info, xi, yi, zi), x, y, z); } } } } return; } other.addEdge(info, (byte)(2 - x), (byte)(2 - y), (byte)(2 - z)); }
public void addEdge(VoxelUpdateInfo info, byte x, byte y, byte z) { if (vertices == null) { return; } bool recalculate = false; Voxel[, ,] voxels = new Voxel[VERTEX_DIMENSION, VERTEX_DIMENSION, VERTEX_DIMENSION]; if (x == 0 /* && xExtend == 0*/) { recalculate = true; xExtend = 1; for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { voxels[0, yi, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - xExtend, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION - 1 + zi).toVoxel(); voxels[1, yi, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION - 1 + zi).toVoxel(); } } } else if (x == 2 /* && xDim < VERTEX_DIMENSION*/) { recalculate = true; xDim = VERTEX_DIMENSION; for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { voxels[VOXEL_DIMENSION + 1, yi, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION * 2, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION - 1 + zi).toVoxel(); voxels[VOXEL_DIMENSION, yi, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION * 2 - 1, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION - 1 + zi).toVoxel(); } } } else if (y == 0 /* && yExtend == 0*/) { recalculate = true; yExtend = 1; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { voxels[xi, 0, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION - yExtend, VOXEL_DIMENSION - 1 + zi).toVoxel(); voxels[xi, 1, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION, VOXEL_DIMENSION - 1 + zi).toVoxel(); } } } else if (y == 2 /* && yDim < VERTEX_DIMENSION*/) { recalculate = true; yDim = VERTEX_DIMENSION; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { voxels[xi, VOXEL_DIMENSION + 1, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION * 2, VOXEL_DIMENSION - 1 + zi).toVoxel(); voxels[xi, VOXEL_DIMENSION, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION * 2 - 1, VOXEL_DIMENSION - 1 + zi).toVoxel(); } } } else if (z == 0 /* && zExtend == 0*/) { recalculate = true; zExtend = 1; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { voxels[xi, yi, 0] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION - zExtend).toVoxel(); voxels[xi, yi, 1] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION).toVoxel(); } } } else if (z == 2 /* && zDim < VERTEX_DIMENSION*/) { recalculate = true; zDim = VERTEX_DIMENSION; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { voxels[xi, yi, VOXEL_DIMENSION + 1] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION * 2).toVoxel(); voxels[xi, yi, VOXEL_DIMENSION] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION * 2 - 1).toVoxel(); } } } if (recalculate) { Queue <int[]> triangleSet = new Queue <int[]>(); MarchingCubes.setup(info.size / VOXEL_DIMENSION, control.isoLevel, ref vertices, ref vertexSubstances, ref voxels, position - new Vector3(0.5f, 0.5f, 0.5f) * size / VOXEL_DIMENSION, VERTS); byte xStart = (byte)(1 - xExtend + (VOXEL_DIMENSION + xExtend - 1) * (x / 2)); byte xEnd = (byte)(2 + (xDim - 2) * ((x + 1) / 2)); byte yStart = (byte)(1 - yExtend + (VOXEL_DIMENSION + yExtend - 1) * (y / 2)); byte yEnd = (byte)(2 + (yDim - 2) * ((y + 1) / 2)); byte zStart = (byte)(1 - zExtend + (VOXEL_DIMENSION + zExtend - 1) * (z / 2)); byte zEnd = (byte)(2 + (zDim - 2) * ((z + 1) / 2)); for (byte xi = xStart, x1 = (byte)(xi + 1); x1 < xEnd; xi = x1++) { for (byte yi = yStart, y1 = (byte)(yi + 1); y1 < yEnd; yi = y1++) { for (byte zi = zStart, z1 = (byte)(zi + 1); z1 < zEnd; zi = z1++) { int[] tris = MarchingCubes.lookupTriangles(xi, yi, zi, x1, y1, z1); if (tris == null) { continue; } triangleSet.Enqueue(tris); } } } if (vertices.Count < 1) { return; } List <int> newTriangles = new List <int>(TRIS); List <Vector3> newVertices = new List <Vector3>(VERTS); int tri = 0; while (triangleSet.Count > 0) { int[] triangleList = triangleSet.Dequeue(); for (int i = 0; i < triangleList.Length; ++i) { if (vertices[triangleList[i]].GetType() == typeof(Vector3)) { newVertices.Add((Vector3)vertices[triangleList[i]]); vertices[triangleList[i]] = newVertices.Count - 1; } newTriangles.Add((int)vertices[triangleList[i]]); } tri += triangleList.Length; } Vector3[] finalNorms = new Vector3[newVertices.Count]; Array.Copy(NORMS, finalNorms, NORMS.Length); int oldNormCount = NORMS.Length; VERTS = newVertices.ToArray(); TRIS = newTriangles.ToArray(); calcNorms(); Array.Copy(NORMS, oldNormCount, finalNorms, oldNormCount, finalNorms.Length - oldNormCount); NORMS = finalNorms; } alignEdge(info, x, y, z); control.enqueueJob(new ApplyMeshJob(this, info.detailLevel, info.x, info.y, info.z)); }
public void removeEdge(VoxelUpdateInfo info, byte x, byte y, byte z) { if (vertices == null) { return; } bool recalculate = false; if (x == 0 && xExtend == 1) { recalculate = true; xExtend = 0; for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { vertices.Remove(getX(0, yi, zi)); vertices.Remove(getY(0, yi, zi)); vertices.Remove(getZ(0, yi, zi)); } } } else if (x == 2 && xDim >= VERTEX_DIMENSION) { recalculate = true; xDim = VERTEX_DIMENSION - 1; for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { vertices.Remove(getX(xDim - 1, yi, zi)); vertices.Remove(getY(xDim, yi, zi)); vertices.Remove(getZ(xDim, yi, zi)); } } } else if (y == 0 && yExtend == 1) { recalculate = true; yExtend = 0; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { vertices.Remove(getX(xi, 0, zi)); vertices.Remove(getY(xi, 0, zi)); vertices.Remove(getZ(xi, 0, zi)); } } } else if (y == 2 && yDim >= VERTEX_DIMENSION) { recalculate = true; yDim = VERTEX_DIMENSION - 1; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { vertices.Remove(getX(xi, yDim, zi)); vertices.Remove(getY(xi, yDim - 1, zi)); vertices.Remove(getZ(xi, yDim, zi)); } } } else if (z == 0 && zExtend == 1) { recalculate = true; zExtend = 0; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { vertices.Remove(getX(xi, yi, 0)); vertices.Remove(getY(xi, yi, 0)); vertices.Remove(getZ(xi, yi, 0)); } } } else if (z == 2 && zDim >= VERTEX_DIMENSION) { recalculate = true; zDim = VERTEX_DIMENSION - 1; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { vertices.Remove(getX(xi, yi, zDim)); vertices.Remove(getY(xi, yi, zDim)); vertices.Remove(getZ(xi, yi, zDim - 1)); } } } if (recalculate) { List <KeyValuePair <int, object> > vertexList = new List <KeyValuePair <int, object> >(vertices); int[] oldTris = TRIS; Vector3[] oldVerts = VERTS; Vector3[] oldNorms = NORMS; List <int> newTris = new List <int>(TRIS.Length); Vector3[] newVerts = new Vector3[vertexList.Count]; Vector3[] newNorms = new Vector3[newVerts.Length]; object[] oldReverseIndices = new object[oldVerts.Length]; int count = 0; foreach (KeyValuePair <int, object> pair in vertexList) { int oldIndex = (int)pair.Value; vertices[pair.Key] = count; newVerts[count] = oldVerts[oldIndex]; newNorms[count] = oldNorms[oldIndex]; oldReverseIndices[oldIndex] = pair.Key; ++count; } int[] triangle = new int[3]; for (int i = 0; i < oldTris.Length; i += 3) { bool old = false; for (int j = 0; j < 3; ++j) { object newIndex = oldReverseIndices[oldTris[i + j]]; if (newIndex == null) { old = true; break; } triangle[j] = (int)vertices[(int)newIndex]; } if (old) { continue; } newTris.AddRange(triangle); } VERTS = newVerts; NORMS = newNorms; TRIS = newTris.ToArray(); control.enqueueJob(new ApplyMeshJob(this, info.detailLevel, info.x, info.y, info.z)); } }
// ~VoxelRenderer() { // clear(); // } public void genMesh(VoxelUpdateInfo info) { size = info.size; Queue<int[]> triangleSet = new Queue<int[]>(); vertices = new Dictionary<int, object>(); vertexSubstances = new Dictionary<int, byte>(); Voxel[, ,] voxels = createVoxelArray(info); MarchingCubes.setup(info.size / VOXEL_DIMENSION, control.isoLevel, ref vertices, ref vertexSubstances, ref voxels, position - new Vector3(0.5f, 0.5f, 0.5f) * size / VOXEL_DIMENSION, null); int totalTris = 0; for (byte x = (byte)(1 - xExtend), x1 = (byte)(x + 1); x1 < xDim; x = x1++) { for (byte y = (byte)(1 - yExtend), y1 = (byte)(y + 1); y1 < yDim; y = y1++) { for (byte z = (byte)(1 - zExtend), z1 = (byte)(z + 1); z1 < zDim; z = z1++) { lock (control) { VoxelHolder block = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION + x, VOXEL_DIMENSION + y, VOXEL_DIMENSION + z); voxels[x1, y1, z1] = block.toVoxel(); int[] tris = MarchingCubes.lookupTriangles(x, y, z, x1, y1, z1); if (tris == null) continue; triangleSet.Enqueue(tris); totalTris += tris.Length; } } } } if (vertices.Count < 1) { applied = true; return; } List<int> triangles = new List<int>(); List<Vector3> finalVertices = new List<Vector3>(vertices.Count); //List<byte> finalMats = new List<byte>(vertices.Count); while (triangleSet.Count > 0) { int[] triangleList = triangleSet.Dequeue(); for (int i = 0; i < triangleList.Length; ++i) { if (vertices[triangleList[i]].GetType() == typeof(Vector3)) { finalVertices.Add((Vector3)vertices[triangleList[i]]); //finalMats.Add(vertexSubstances[triangleList[i]]); vertices[triangleList[i]] = finalVertices.Count - 1; } triangles.Add((int)vertices[triangleList[i]]); } } VERTS = finalVertices.ToArray(); TRIS = triangles.ToArray(); //MATS = finalMats.ToArray(); calcNorms(); alignEdge(info, 0, 1, 1); alignEdge(info, 2, 1, 1); alignEdge(info, 1, 0, 1); alignEdge(info, 1, 2, 1); alignEdge(info, 1, 1, 0); alignEdge(info, 1, 1, 2); lock (control) { control.enqueueMeshApply(new ApplyMeshJob(this, info.detailLevel, info.x, info.y, info.z)); } }
private void alignEdge(VoxelUpdateInfo info, byte x, byte y, byte z) { if (info.renderers[x, y, z] == null || (x + y + z > 3 && info.renderers[x, y, z].size == size)) { lock (control) { VoxelUpdateInfo newInfo = new VoxelUpdateInfo(info.size, info.blocks[1, 1, 1], info.control); newInfo.setFromSister(info, x, y, z); alignOtherEdge(newInfo, x, y, z); } return; } lock (control) { info.renderers[x, y, z].removeEdge(info, (byte)(2 - x), (byte)(2 - y), (byte)(2 - z)); } Vector3[] newVerts = VERTS; LinkedList <int> myIndices = new LinkedList <int>(); LinkedList <Vector3[]> otherVerts = new LinkedList <Vector3[]>(); Vector3[] newNorms = NORMS; lock (control) { if (x != 1) { if (xDim < VERTEX_DIMENSION && x == 2) { return; } int otherXInd = 1 + (VERTEX_DIMENSION - 3) * (1 - x / 2); int myXInd = (VERTEX_DIMENSION - 1) * (x / 2); for (int yi = 1 - yExtend; yi < yDim; ++yi) { for (int zi = 1 - zExtend; zi < zDim; ++zi) { addDualVertices(otherVerts, info.renderers[x, y, z], otherXInd, yi, zi, 0); myIndices.AddFirst(getY(myXInd, yi, zi)); myIndices.AddFirst(getZ(myXInd, yi, zi)); } } addDualVertices(otherVerts, info.renderers[x, y + 1, z + 1], otherXInd, 0, 0, 0); addDualVertices(otherVerts, info.renderers[x, y + 1, z - 1], otherXInd, 0, VERTEX_DIMENSION - 1, 0); addDualVertices(otherVerts, info.renderers[x, y - 1, z + 1], otherXInd, VERTEX_DIMENSION - 1, 0, 0); addDualVertices(otherVerts, info.renderers[x, y - 1, z - 1], otherXInd, VERTEX_DIMENSION - 1, VERTEX_DIMENSION - 1, 0); for (int i = 0; i < VERTEX_DIMENSION; ++i) { addDualVertices(otherVerts, info.renderers[x, y, z + 1], otherXInd, i, 0, 0); addDualVertices(otherVerts, info.renderers[x, y, z - 1], otherXInd, i, VERTEX_DIMENSION - 1, 0); addDualVertices(otherVerts, info.renderers[x, y + 1, z], otherXInd, 0, i, 0); addDualVertices(otherVerts, info.renderers[x, y - 1, z], otherXInd, VERTEX_DIMENSION - 1, i, 0); } } else if (y != 1) { if (yDim < VERTEX_DIMENSION && y == 2) { return; } int otherYInd = 1 + (VERTEX_DIMENSION - 3) * (1 - y / 2); int myYInd = (VERTEX_DIMENSION - 1) * (y / 2); for (int xi = 1 - xExtend; xi < xDim; ++xi) { for (int zi = 1 - zExtend; zi < zDim; ++zi) { addDualVertices(otherVerts, info.renderers[x, y, z], xi, otherYInd, zi, 1); myIndices.AddFirst(getX(xi, myYInd, zi)); myIndices.AddFirst(getZ(xi, myYInd, zi)); } } addDualVertices(otherVerts, info.renderers[x + 1, y, z + 1], 0, otherYInd, 0, 1); addDualVertices(otherVerts, info.renderers[x + 1, y, z - 1], 0, otherYInd, VERTEX_DIMENSION - 1, 1); addDualVertices(otherVerts, info.renderers[x - 1, y, z + 1], VERTEX_DIMENSION - 1, otherYInd, 0, 1); addDualVertices(otherVerts, info.renderers[x - 1, y, z - 1], VERTEX_DIMENSION - 1, otherYInd, VERTEX_DIMENSION - 1, 1); for (int i = 0; i < VERTEX_DIMENSION; ++i) { addDualVertices(otherVerts, info.renderers[x, y, z + 1], i, otherYInd, 0, 1); addDualVertices(otherVerts, info.renderers[x, y, z - 1], i, otherYInd, VERTEX_DIMENSION - 1, 1); addDualVertices(otherVerts, info.renderers[x + 1, y, z], 0, otherYInd, i, 1); addDualVertices(otherVerts, info.renderers[x - 1, y, z], VERTEX_DIMENSION - 1, otherYInd, i, 1); } } else if (z != 1) { if (zDim < VERTEX_DIMENSION && z == 2) { return; } int otherZInd = 1 + (VERTEX_DIMENSION - 3) * (1 - z / 2); int myZInd = (VERTEX_DIMENSION - 1) * (z / 2); for (int xi = 1 - xExtend; xi < xDim; ++xi) { for (int yi = 1 - yExtend; yi < yDim; ++yi) { addDualVertices(otherVerts, info.renderers[x, y, z], xi, yi, otherZInd, 2); myIndices.AddFirst(getX(xi, yi, myZInd)); myIndices.AddFirst(getY(xi, yi, myZInd)); } } addDualVertices(otherVerts, info.renderers[x + 1, y + 1, z], 0, 0, otherZInd, 2); addDualVertices(otherVerts, info.renderers[x + 1, y - 1, z], 0, VERTEX_DIMENSION - 1, otherZInd, 2); addDualVertices(otherVerts, info.renderers[x - 1, y + 1, z], VERTEX_DIMENSION - 1, 0, otherZInd, 2); addDualVertices(otherVerts, info.renderers[x - 1, y - 1, z], VERTEX_DIMENSION - 1, VERTEX_DIMENSION - 1, otherZInd, 2); for (int i = 0; i < VERTEX_DIMENSION; ++i) { addDualVertices(otherVerts, info.renderers[x, y + 1, z], i, 0, otherZInd, 2); addDualVertices(otherVerts, info.renderers[x, y - 1, z], i, VERTEX_DIMENSION - 1, otherZInd, 2); addDualVertices(otherVerts, info.renderers[x + 1, y, z], 0, i, otherZInd, 2); addDualVertices(otherVerts, info.renderers[x - 1, y, z], VERTEX_DIMENSION - 1, i, otherZInd, 2); } } } lock (control) { foreach (int myIndex in myIndices) { if (vertices.ContainsKey(myIndex)) { Vector3[] vertex = getClosestVertex(newVerts[(int)vertices[myIndex]], otherVerts); if (vertex == null || (newVerts[(int)vertices[myIndex]] - vertex[0]).sqrMagnitude > Mathf.Pow(size / 4, 2)) { continue; } newVerts[(int)vertices[myIndex]] = vertex[0]; newNorms[(int)vertices[myIndex]] = vertex[1]; } } } VERTS = newVerts; NORMS = newNorms; }
public void removeEdge(VoxelUpdateInfo info, byte x, byte y, byte z) { if (vertices == null) return; bool recalculate = false; if (x == 0 && xExtend == 1) { recalculate = true; xExtend = 0; for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { vertices.Remove(getX(0, yi, zi)); vertices.Remove(getY(0, yi, zi)); vertices.Remove(getZ(0, yi, zi)); } } } else if (x == 2 && xDim >= VERTEX_DIMENSION) { recalculate = true; xDim = VERTEX_DIMENSION - 1; for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { vertices.Remove(getX(xDim - 1, yi, zi)); vertices.Remove(getY(xDim, yi, zi)); vertices.Remove(getZ(xDim, yi, zi)); } } } else if (y == 0 && yExtend == 1) { recalculate = true; yExtend = 0; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { vertices.Remove(getX(xi, 0, zi)); vertices.Remove(getY(xi, 0, zi)); vertices.Remove(getZ(xi, 0, zi)); } } } else if (y == 2 && yDim >= VERTEX_DIMENSION) { recalculate = true; yDim = VERTEX_DIMENSION - 1; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { vertices.Remove(getX(xi, yDim, zi)); vertices.Remove(getY(xi, yDim - 1, zi)); vertices.Remove(getZ(xi, yDim, zi)); } } } else if (z == 0 && zExtend == 1) { recalculate = true; zExtend = 0; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { vertices.Remove(getX(xi, yi, 0)); vertices.Remove(getY(xi, yi, 0)); vertices.Remove(getZ(xi, yi, 0)); } } } else if (z == 2 && zDim >= VERTEX_DIMENSION) { recalculate = true; zDim = VERTEX_DIMENSION - 1; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { vertices.Remove(getX(xi, yi, zDim)); vertices.Remove(getY(xi, yi, zDim)); vertices.Remove(getZ(xi, yi, zDim - 1)); } } } if (recalculate) { List<KeyValuePair<int, object>> vertexList = new List<KeyValuePair<int, object>>(vertices); int[] oldTris = TRIS; Vector3[] oldVerts = VERTS; Vector3[] oldNorms = NORMS; List<int> newTris = new List<int>(TRIS.Length); Vector3[] newVerts = new Vector3[vertexList.Count]; Vector3[] newNorms = new Vector3[newVerts.Length]; object[] oldReverseIndices = new object[oldVerts.Length]; int count = 0; foreach (KeyValuePair<int, object> pair in vertexList) { int oldIndex = (int)pair.Value; vertices[pair.Key] = count; newVerts[count] = oldVerts[oldIndex]; newNorms[count] = oldNorms[oldIndex]; oldReverseIndices[oldIndex] = pair.Key; ++count; } int[] triangle = new int[3]; for (int i = 0; i < oldTris.Length; i += 3) { bool old = false; for (int j = 0; j < 3; ++j) { object newIndex = oldReverseIndices[oldTris[i + j]]; if (newIndex == null) { old = true; break; } triangle[j] = (int)vertices[(int)newIndex]; } if (old) continue; newTris.AddRange(triangle); } VERTS = newVerts; NORMS = newNorms; TRIS = newTris.ToArray(); control.enqueueMeshApply(new ApplyMeshJob(this, info.detailLevel, info.x, info.y, info.z)); } }
private void setDimensions(VoxelUpdateInfo info) { if (info.renderers[0, 1, 1] == null) xExtend = 0; else xExtend = 1; if (info.renderers[1, 0, 1] == null) yExtend = 0; else yExtend = 1; if (info.renderers[1, 1, 0] == null) zExtend = 0; else zExtend = 1; xDim = (byte)(VOXEL_DIMENSION + 1); yDim = (byte)(VOXEL_DIMENSION + 1); zDim = (byte)(VOXEL_DIMENSION + 1); if (info.renderers[2, 1, 1] != null && info.renderers[2, 1, 1].size > size * 1.1f) ++xDim; if (info.renderers[1, 2, 1] != null && info.renderers[1, 2, 1].size > size * 1.1f) ++yDim; if (info.renderers[1, 1, 2] != null && info.renderers[1, 1, 2].size > size * 1.1f) ++zDim; }
public void addEdge(VoxelUpdateInfo info, byte x, byte y, byte z) { if (vertices == null) return; bool recalculate = false; Voxel[, ,] voxels = new Voxel[VERTEX_DIMENSION, VERTEX_DIMENSION, VERTEX_DIMENSION]; if (x == 0/* && xExtend == 0*/) { recalculate = true; xExtend = 1; for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { voxels[0, yi, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - xExtend, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION - 1 + zi).toVoxel(); voxels[1, yi, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION - 1 + zi).toVoxel(); } } } else if (x == 2/* && xDim < VERTEX_DIMENSION*/) { recalculate = true; xDim = VERTEX_DIMENSION; for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { voxels[VOXEL_DIMENSION + 1, yi, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION * 2, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION - 1 + zi).toVoxel(); voxels[VOXEL_DIMENSION, yi, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION * 2 - 1, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION - 1 + zi).toVoxel(); } } } else if (y == 0/* && yExtend == 0*/) { recalculate = true; yExtend = 1; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { voxels[xi, 0, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION - yExtend, VOXEL_DIMENSION - 1 + zi).toVoxel(); voxels[xi, 1, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION, VOXEL_DIMENSION - 1 + zi).toVoxel(); } } } else if (y == 2/* && yDim < VERTEX_DIMENSION*/) { recalculate = true; yDim = VERTEX_DIMENSION; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi) { voxels[xi, VOXEL_DIMENSION + 1, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION * 2, VOXEL_DIMENSION - 1 + zi).toVoxel(); voxels[xi, VOXEL_DIMENSION, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION * 2 - 1, VOXEL_DIMENSION - 1 + zi).toVoxel(); } } } else if (z == 0/* && zExtend == 0*/) { recalculate = true; zExtend = 1; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { voxels[xi, yi, 0] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION - zExtend).toVoxel(); voxels[xi, yi, 1] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION).toVoxel(); } } } else if (z == 2/* && zDim < VERTEX_DIMENSION*/) { recalculate = true; zDim = VERTEX_DIMENSION; for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi) { for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi) { voxels[xi, yi, VOXEL_DIMENSION + 1] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION * 2).toVoxel(); voxels[xi, yi, VOXEL_DIMENSION] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION * 2 - 1).toVoxel(); } } } if (recalculate) { Queue<int[]> triangleSet = new Queue<int[]>(); MarchingCubes.setup(info.size / VOXEL_DIMENSION, control.isoLevel, ref vertices, ref vertexSubstances, ref voxels, position - new Vector3(0.5f, 0.5f, 0.5f) * size / VOXEL_DIMENSION, VERTS); byte xStart = (byte)(1 - xExtend + (VOXEL_DIMENSION + xExtend - 1) * (x / 2)); byte xEnd = (byte)(2 + (xDim - 2) * ((x + 1) / 2)); byte yStart = (byte)(1 - yExtend + (VOXEL_DIMENSION + yExtend - 1) * (y / 2)); byte yEnd = (byte)(2 + (yDim - 2) * ((y + 1) / 2)); byte zStart = (byte)(1 - zExtend + (VOXEL_DIMENSION + zExtend - 1) * (z / 2)); byte zEnd = (byte)(2 + (zDim - 2) * ((z + 1) / 2)); for (byte xi = xStart, x1 = (byte)(xi + 1); x1 < xEnd; xi = x1++) { for (byte yi = yStart, y1 = (byte)(yi + 1); y1 < yEnd; yi = y1++) { for (byte zi = zStart, z1 = (byte)(zi + 1); z1 < zEnd; zi = z1++) { int[] tris = MarchingCubes.lookupTriangles(xi, yi, zi, x1, y1, z1); if (tris == null) continue; triangleSet.Enqueue(tris); } } } if (vertices.Count < 1) { return; } List<int> newTriangles = new List<int>(TRIS); List<Vector3> newVertices = new List<Vector3>(VERTS); List<Vector3> newNorms = new List<Vector3>(NORMS); int tri = 0; while (triangleSet.Count > 0) { int[] triangleList = triangleSet.Dequeue(); for (int i = 0; i < triangleList.Length; ++i) { if (vertices[triangleList[i]].GetType() == typeof(Vector3)) { newVertices.Add((Vector3)vertices[triangleList[i]]); newNorms.Add(Vector3.zero); vertices[triangleList[i]] = newVertices.Count - 1; } newTriangles.Add((int)vertices[triangleList[i]]); } tri += triangleList.Length; } Vector3[] finalNorms = new Vector3[newNorms.Count]; Array.Copy(NORMS, finalNorms, NORMS.Length); int oldNormCount = NORMS.Length; VERTS = newVertices.ToArray(); TRIS = newTriangles.ToArray(); calcNorms(); Array.Copy(NORMS, oldNormCount, finalNorms, oldNormCount, finalNorms.Length - oldNormCount); NORMS = finalNorms; } alignEdge(info, x, y, z); control.enqueueMeshApply(new ApplyMeshJob(this, info.detailLevel, info.x, info.y, info.z)); }
//private static int getX(int index, int dimension) { // return (y * VERTEX_DIMENSION + z) * VERTEX_DIMENSION + x; //} //private static int getY(int index, int dimension) { // return ((VERTEX_DIMENSION + x) * VERTEX_DIMENSION + z) * VERTEX_DIMENSION + y; //} //private static int getZ(int index, int dimension) { // return ((VERTEX_DIMENSION * 2 + x) * VERTEX_DIMENSION + y) * VERTEX_DIMENSION + z; //} //private static int getDimension(int index) { // return index / (VERTEX_DIMENSION * VERTEX_DIMENSION * VERTEX_DIMENSION); //} private Voxel[, ,] createVoxelArray(VoxelUpdateInfo info) { setDimensions(info); Voxel[, ,] voxels = new Voxel[VERTEX_DIMENSION, VERTEX_DIMENSION, VERTEX_DIMENSION]; for (byte y = (byte)(1 - yExtend); y < yDim; ++y) { for (byte z = (byte)(1 - zExtend); z < zDim; ++z) { voxels[1 - xExtend, y, z] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - xExtend, VOXEL_DIMENSION - 1 + y, VOXEL_DIMENSION - 1 + z).toVoxel(); } } for (byte x = (byte)(2 - xExtend); x < xDim; ++x) { for (byte z = (byte)(1 - zExtend); z < zDim; ++z) { voxels[x, 1 - yExtend, z] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + x, VOXEL_DIMENSION - yExtend, VOXEL_DIMENSION - 1 + z).toVoxel(); } } for (byte x = (byte)(2 - xExtend); x < xDim; ++x) { for (byte y = (byte)(2 - yExtend); y < yDim; ++y) { voxels[x, y, 1 - zExtend] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + x, VOXEL_DIMENSION - 1 + y, VOXEL_DIMENSION - zExtend).toVoxel(); } } return voxels; }
private void alignEdge(VoxelUpdateInfo info, byte x, byte y, byte z) { if (info.renderers[x, y, z] == null || (x + y + z > 3 && info.renderers[x, y, z].size == size)) { lock (control) { VoxelUpdateInfo newInfo = new VoxelUpdateInfo(info.size, info.blocks[1, 1, 1], info.control); newInfo.setFromSister(info, x, y, z); alignOtherEdge(newInfo, x, y, z); } return; } lock (control) { info.renderers[x, y, z].removeEdge(info, (byte)(2 - x), (byte)(2 - y), (byte)(2 - z)); } Vector3[] newVerts = VERTS; LinkedList<int> myIndices = new LinkedList<int>(); LinkedList<Vector3[]> otherVerts = new LinkedList<Vector3[]>(); Vector3[] newNorms = NORMS; lock (control) { if (x != 1) { if (xDim < VERTEX_DIMENSION && x == 2) return; int otherXInd = 1 + (VERTEX_DIMENSION - 3) * (1 - x / 2); int myXInd = (VERTEX_DIMENSION - 1) * (x / 2); for (int yi = 1 - yExtend; yi < yDim; ++yi) { for (int zi = 1 - zExtend; zi < zDim; ++zi) { addDualVertices(otherVerts, info.renderers[x, y, z], otherXInd, yi, zi, 0); myIndices.AddFirst(getY(myXInd, yi, zi)); myIndices.AddFirst(getZ(myXInd, yi, zi)); } } addDualVertices(otherVerts, info.renderers[x, y + 1, z + 1], otherXInd, 0, 0, 0); addDualVertices(otherVerts, info.renderers[x, y + 1, z - 1], otherXInd, 0, VERTEX_DIMENSION - 1, 0); addDualVertices(otherVerts, info.renderers[x, y - 1, z + 1], otherXInd, VERTEX_DIMENSION - 1, 0, 0); addDualVertices(otherVerts, info.renderers[x, y - 1, z - 1], otherXInd, VERTEX_DIMENSION - 1, VERTEX_DIMENSION - 1, 0); for (int i = 0; i < VERTEX_DIMENSION; ++i) { addDualVertices(otherVerts, info.renderers[x, y, z + 1], otherXInd, i, 0, 0); addDualVertices(otherVerts, info.renderers[x, y, z - 1], otherXInd, i, VERTEX_DIMENSION - 1, 0); addDualVertices(otherVerts, info.renderers[x, y + 1, z], otherXInd, 0, i, 0); addDualVertices(otherVerts, info.renderers[x, y - 1, z], otherXInd, VERTEX_DIMENSION - 1, i, 0); } } else if (y != 1) { if (yDim < VERTEX_DIMENSION && y == 2) return; int otherYInd = 1 + (VERTEX_DIMENSION - 3) * (1 - y / 2); int myYInd = (VERTEX_DIMENSION - 1) * (y / 2); for (int xi = 1 - xExtend; xi < xDim; ++xi) { for (int zi = 1 - zExtend; zi < zDim; ++zi) { addDualVertices(otherVerts, info.renderers[x, y, z], xi, otherYInd, zi, 1); myIndices.AddFirst(getX(xi, myYInd, zi)); myIndices.AddFirst(getZ(xi, myYInd, zi)); } } addDualVertices(otherVerts, info.renderers[x + 1, y, z + 1], 0, otherYInd, 0, 1); addDualVertices(otherVerts, info.renderers[x + 1, y, z - 1], 0, otherYInd, VERTEX_DIMENSION - 1, 1); addDualVertices(otherVerts, info.renderers[x - 1, y, z + 1], VERTEX_DIMENSION - 1, otherYInd, 0, 1); addDualVertices(otherVerts, info.renderers[x - 1, y, z - 1], VERTEX_DIMENSION - 1, otherYInd, VERTEX_DIMENSION - 1, 1); for (int i = 0; i < VERTEX_DIMENSION; ++i) { addDualVertices(otherVerts, info.renderers[x, y, z + 1], i, otherYInd, 0, 1); addDualVertices(otherVerts, info.renderers[x, y, z - 1], i, otherYInd, VERTEX_DIMENSION - 1, 1); addDualVertices(otherVerts, info.renderers[x + 1, y, z], 0, otherYInd, i, 1); addDualVertices(otherVerts, info.renderers[x - 1, y, z], VERTEX_DIMENSION - 1, otherYInd, i, 1); } } else if (z != 1) { if (zDim < VERTEX_DIMENSION && z == 2) return; int otherZInd = 1 + (VERTEX_DIMENSION - 3) * (1 - z / 2); int myZInd = (VERTEX_DIMENSION - 1) * (z / 2); for (int xi = 1 - xExtend; xi < xDim; ++xi) { for (int yi = 1 - yExtend; yi < yDim; ++yi) { addDualVertices(otherVerts, info.renderers[x, y, z], xi, yi, otherZInd, 2); myIndices.AddFirst(getX(xi, yi, myZInd)); myIndices.AddFirst(getY(xi, yi, myZInd)); } } addDualVertices(otherVerts, info.renderers[x + 1, y + 1, z], 0, 0, otherZInd, 2); addDualVertices(otherVerts, info.renderers[x + 1, y - 1, z], 0, VERTEX_DIMENSION - 1, otherZInd, 2); addDualVertices(otherVerts, info.renderers[x - 1, y + 1, z], VERTEX_DIMENSION - 1, 0, otherZInd, 2); addDualVertices(otherVerts, info.renderers[x - 1, y - 1, z], VERTEX_DIMENSION - 1, VERTEX_DIMENSION - 1, otherZInd, 2); for (int i = 0; i < VERTEX_DIMENSION; ++i) { addDualVertices(otherVerts, info.renderers[x, y + 1, z], i, 0, otherZInd, 2); addDualVertices(otherVerts, info.renderers[x, y - 1, z], i, VERTEX_DIMENSION - 1, otherZInd, 2); addDualVertices(otherVerts, info.renderers[x + 1, y, z], 0, i, otherZInd, 2); addDualVertices(otherVerts, info.renderers[x - 1, y, z], VERTEX_DIMENSION - 1, i, otherZInd, 2); } } } lock (control) { foreach (int myIndex in myIndices) { if (vertices.ContainsKey(myIndex)) { Vector3[] vertex = getClosestVertex(newVerts[(int)vertices[myIndex]], otherVerts); if (vertex == null || (newVerts[(int)vertices[myIndex]] -vertex[0]).sqrMagnitude > Mathf.Pow(size /4, 2)) continue; newVerts[(int)vertices[myIndex]] = vertex[0]; newNorms[(int)vertices[myIndex]] = vertex[1]; } } } VERTS = newVerts; NORMS = newNorms; }