void AddVoxel(int x, int y, int z, Voxel_t voxel) { var blendVoxel = _voxels[_numVoxels++]; ZeroInts(blendVoxel->vertexFlags, 8); ZeroInts(blendVoxel->neighbors, 6); blendVoxel->touched = true; }
private List <VoxInfo> BuildVoxInfo(Voxel_t[] voxels, float unit) { List <VoxInfo> vi = new List <VoxInfo>(); if (!selectedMesh || !selectedMaterial) { return(vi); } Vector3 min = selectedMesh.bounds.min; Texture2D tex = GetReadableTexture(selectedMaterial.mainTexture); float n = 1 / unit; for (int i = 0; i < voxels.Length; i++) { Voxel_t v = voxels[i]; if (v.fill == 0) { continue; } Vector3 p = v.position - min; p *= n; int x = Mathf.RoundToInt(p.x); int y = Mathf.RoundToInt(p.y); int z = Mathf.RoundToInt(p.z); Vector3Int vp = new Vector3Int(x, y, z); Color col = Color.white; if (v.uv.x != -1)//Fill color? { if (tex != null) { col = tex.GetPixel((int)(v.uv.x * tex.width), (int)(v.uv.y * tex.height)); } else { col = selectedMaterial.color; } } VoxInfo nvi = new VoxInfo { pos = vp, col = col, idx = 1 }; vi.Add(nvi); } return(vi); }
private void SymmetrizeVoxels(List <Voxel_t> voxels) { // Calculate the center of the voxels Vector3 center = Vector3.zero; foreach (Voxel_t voxel in voxels) { center += voxel.position; } center /= voxels.Count; // Create a list of previous voxels whose x-values are left or equal to center List <Voxel_t> sideVoxels = new List <Voxel_t>(voxels.Count); foreach (Voxel_t voxel in voxels) { if (voxel.position.x <= center.x + EPSILON) { sideVoxels.Add(voxel); } } // Clear the voxels and only add the ones whose x-value is left or equal to center voxels.Clear(); foreach (Voxel_t sideVoxel in sideVoxels) { // Add the voxel for this side into the result voxels.Add(sideVoxel); // Add the opposite side voxel into the result // (Only do this if the voxel isn't along the center line) if (!Eq(sideVoxel.position.x, center.x)) { Vector3 reversePosition = sideVoxel.position; reversePosition.x = -reversePosition.x; Voxel_t reverseVoxel = sideVoxel; reverseVoxel.position = reversePosition; voxels.Add(reverseVoxel); } } }
void EmitVoxelFaces(int index, int x, int y, int z, Voxel_t voxel, bool isBorderVoxel) { var contents = _tables.blockContents[(int)voxel.type]; Color32 color; if ((voxel.flags & EVoxelBlockFlags.FullVoxel) != 0) { color = Color.red; } else { GetBlockColor(voxel.type, x, y, z, out color); } for (int i = 0; i < 6; ++i) { if (_vnc[i] < contents) { var v0 = _tables.voxelFaces[i][0]; for (int k = 1; k <= 2; ++k) { var v1 = _tables.voxelFaces[i][k]; var v2 = _tables.voxelFaces[i][k + 1]; if ((v0 != v1) && (v0 != v2) && (v1 != v2)) { _smoothVerts.EmitTri( x + _tables.voxelVerts[v0][0] - BORDER_SIZE, y + _tables.voxelVerts[v0][1] - BORDER_SIZE, z + _tables.voxelVerts[v0][2] - BORDER_SIZE, x + _tables.voxelVerts[v1][0] - BORDER_SIZE, y + _tables.voxelVerts[v1][1] - BORDER_SIZE, z + _tables.voxelVerts[v1][2] - BORDER_SIZE, x + _tables.voxelVerts[v2][0] - BORDER_SIZE, y + _tables.voxelVerts[v2][1] - BORDER_SIZE, z + _tables.voxelVerts[v2][2] - BORDER_SIZE, color, isBorderVoxel ); } } } } }
public static void Voxelize(Vector3[] vertices, int[] indices, Bounds bounds, int resolution, out float unit) { float maxLength = Mathf.Max(bounds.size.x, Mathf.Max(bounds.size.y, bounds.size.z)); unit = maxLength / resolution; float hunit = unit * 0.5f; start = bounds.min - new Vector3(hunit, hunit, hunit); Vector3 end = bounds.max + new Vector3(hunit, hunit, hunit); Vector3 size = end - start; width = Mathf.CeilToInt(size.x / unit); height = Mathf.CeilToInt(size.y / unit); depth = Mathf.CeilToInt(size.z / unit); volume = new Voxel_t[width, height, depth]; Bounds[, ,] boxes = new Bounds[width, height, depth]; Vector3 voxelSize = Vector3.one * unit; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { for (int z = 0; z < depth; z++) { Vector3 p = new Vector3(x, y, z) * unit + start; Bounds aabb = new Bounds(p, voxelSize); boxes[x, y, z] = aabb; volume[x, y, z] = new Voxel_t(); } } } Vector3 direction = Vector3.forward; for (int i = 0, n = indices.Length; i < n; i += 3) { MegaTriangle tri = new MegaTriangle(vertices[indices[i]], vertices[indices[i + 1]], vertices[indices[i + 2]], direction, i); Vector3 min = tri.bounds.min - start; Vector3 max = tri.bounds.max - start; int iminX = (int)(min.x / unit), iminY = (int)(min.y / unit), iminZ = (int)(min.z / unit); int imaxX = (int)(max.x / unit), imaxY = (int)(max.y / unit), imaxZ = (int)(max.z / unit); iminX = Mathf.Clamp(iminX, 0, width - 1); iminY = Mathf.Clamp(iminY, 0, height - 1); iminZ = Mathf.Clamp(iminZ, 0, depth - 1); imaxX = Mathf.Clamp(imaxX, 0, width - 1); imaxY = Mathf.Clamp(imaxY, 0, height - 1); imaxZ = Mathf.Clamp(imaxZ, 0, depth - 1); for (int x = iminX; x <= imaxX; x++) { for (int y = iminY; y <= imaxY; y++) { for (int z = iminZ; z <= imaxZ; z++) { if (Intersects(tri, boxes[x, y, z])) { Voxel_t voxel = volume[x, y, z]; voxel.position = boxes[x, y, z].center; voxel.tris.Add(tri); volume[x, y, z] = voxel; } } } } } }
public static unsafe PinnedChunkData_t DecompressChunkData(byte *ptr, int len, PinnedChunkData_t chunk, FinalMeshVerts_t verts) { var src = ptr; { var decorationCount = *((int *)src); src += 4; for (int i = 0; i < decorationCount; ++i) { var d = default(Decoration_t); d.pos.x = *((float *)src); src += 4; d.pos.y = *((float *)src); src += 4; d.pos.z = *((float *)src); src += 4; d.type = (EDecorationType)(*((int *)src)); src += 4; chunk.AddDecoration(d); } } if ((chunk.flags & EChunkFlags.SOLID) == 0) { // empty chunk chunk.voxeldata.Broadcast(EVoxelBlockType.Air); for (int i = 0; i < verts.counts.Length; ++i) { verts.counts[i] = 0; } for (int i = 0; i < verts.submeshes.Length; ++i) { verts.submeshes[i] = 0; } return(chunk); } { var voxeldata = chunk.voxeldata; var count = chunk.voxeldata.length; for (int i = 0; i < count; ++i) { voxeldata[i] = new Voxel_t(src[i]); } } src += chunk.voxeldata.length; for (int i = 0; i < verts.counts.Length; ++i) { verts.counts[i] = *((int *)src); src += 4; } for (int i = 0; i < verts.submeshes.Length; ++i) { verts.submeshes[i] = *((int *)src); src += 4; } int totalVerts = *((int *)src); src += 4; int totalIndices = *((int *)src); src += 4; for (int i = 0; i < totalVerts; ++i) { Vector3 v3; v3.x = *((float *)src); src += 4; v3.y = *((float *)src); src += 4; v3.z = *((float *)src); src += 4; verts.positions[i] = v3; } for (int i = 0; i < totalVerts; ++i) { Vector3 v3; v3.x = *((float *)src); src += 4; v3.y = *((float *)src); src += 4; v3.z = *((float *)src); src += 4; verts.normals[i] = v3; } for (int i = 0; i < totalVerts; ++i) { uint c = *((uint *)src); src += 4; verts.colors[i] = Utils.GetColor32FromUIntRGBA(c); } for (int i = 0; i < totalIndices; ++i) { verts.indices[i] = *((int *)src); src += 4; } return(chunk); }
void Run(PinnedChunkData_t chunk) { _smoothVerts.Init(); if ((chunk.flags & EChunkFlags.SOLID) == 0) { // no solid blocks in this chunk it can't have any visible faces. _smoothVerts.Finish(); return; } byte * grid = stackalloc byte[8]; int * x = stackalloc int[3]; int * edges = stackalloc int[12]; byte * edgeBlocks = stackalloc byte[24]; float *nv = stackalloc float[3]; for (x[2] = -2; x[2] < VOXEL_CHUNK_SIZE_Y + 1; ++x[2]) { for (x[1] = -2; x[1] < VOXEL_CHUNK_SIZE_XZ + 1; ++x[1]) { for (x[0] = -2; x[0] < VOXEL_CHUNK_SIZE_XZ + 1; ++x[0]) { // read voxels around this vertex // note the mask, and grid verts for the cubes are X/Y/Z, but unity // is Y up so we have to swap Z/Y bool isBorder = (x[0] < 0) || (x[0] >= VOXEL_CHUNK_SIZE_XZ) || (x[1] < 0) || (x[1] >= VOXEL_CHUNK_SIZE_XZ) || (x[2] < 0) || (x[2] >= VOXEL_CHUNK_SIZE_Y); int cubeIndex = 0; for (int i = 0; i < 8; ++i) { var v = _tables.mc_cubeVerts[i]; var iz = x[2] + v[2]; var zwrap = Wrap(iz, VOXEL_CHUNK_SIZE_Y); var zofs = VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ * zwrap; // zofs is really yofs in voxel data var cz = (iz < 0) ? 0 : (iz < VOXEL_CHUNK_SIZE_Y) ? 1 : 2; var iy = x[1] + v[1]; var ywrap = Wrap(iy, VOXEL_CHUNK_SIZE_XZ); var yofs = VOXEL_CHUNK_SIZE_XZ * ywrap; // yofs is really zofs in voxel data var cy = (iy < 0) ? 0 : (iy < VOXEL_CHUNK_SIZE_XZ) ? 1 : 2; var ix = x[0] + v[0]; var xwrap = Wrap(ix, VOXEL_CHUNK_SIZE_XZ); var xofs = xwrap; var cx = (ix < 0) ? 0 : (ix < VOXEL_CHUNK_SIZE_XZ) ? 1 : 2; var chunkIndex = cx + (cz * Y_PITCH) + (cy * Z_PITCH); var POS_X = chunkIndex + 1; var NEG_X = chunkIndex - 1; var POS_Y = chunkIndex + Y_PITCH; var NEG_Y = chunkIndex - Y_PITCH; var POS_Z = chunkIndex + Z_PITCH; var NEG_Z = chunkIndex - Z_PITCH; var neighbor = _area[chunkIndex]; var voxel = neighbor.valid != 0 ? neighbor.voxeldata[xofs + yofs + zofs] : EVoxelBlockType.Air; grid[i] = voxel.raw; if (_tables.blockContents[(int)voxel.type] == EVoxelBlockContents.None) { cubeIndex |= 1 << i; } } var edgeMask = _tables.mc_edgeTable[cubeIndex]; if (edgeMask == 0) { // no contents change continue; } for (int i = 0; i < 12; ++i) { edges[i] = -1; if ((edgeMask & (1 << i)) == 0) { continue; } nv[0] = 0; nv[1] = 0; nv[2] = 0; var e = _tables.mc_edgeIndex[i]; var v0 = _tables.mc_cubeVerts[e[0]]; var v1 = _tables.mc_cubeVerts[e[1]]; edgeBlocks[i * 2 + 0] = grid[e[0]]; edgeBlocks[i * 2 + 1] = grid[e[1]]; var t = 0.5f; for (int j = 0; j < 3; ++j) { nv[j] = (x[j] + v0[j] + 0.5f) + t * (v1[j] - v0[j]); } edges[i] = _smoothVerts.EmitVert(new Vector3(nv[0], nv[2], nv[1])); } var faces = _tables.mc_triTable[cubeIndex]; for (int i = 0; (i < faces.length) && (faces[i] != -1); i += 3) { BoundsCheckAndThrow(faces[i + 0], 0, 12); BoundsCheckAndThrow(faces[i + 1], 0, 12); BoundsCheckAndThrow(faces[i + 2], 0, 12); Voxel_t voxel = default(Voxel_t); EVoxelBlockContents vc = default(EVoxelBlockContents); for (int j = 0; j < 3; ++j) { var v0v = new Voxel_t(edgeBlocks[faces[i + j] * 2 + 0]); var v1v = new Voxel_t(edgeBlocks[faces[i + j] * 2 + 1]); var v0c = _tables.blockContents[(int)v0v.type]; var v1c = _tables.blockContents[(int)v1v.type]; if (j > 0) { if (v0c > v1c) { if (v0c > vc) { vc = v0c; voxel = v0v; } } else if (v1c > vc) { vc = v1c; voxel = v1v; } } else { vc = (v0c > v1c) ? v0c : v1c; voxel = (v0c > v1c) ? v0v : v1v; } } int mat, layer; uint smg; Color32 color; float smoothing; GetBlockColorAndSmoothing(voxel.type, out color, out smg, out smoothing, out layer); mat = _blockMaterials[(int)voxel.type - 1]; _smoothVerts.EmitTri(edges[faces[i]], edges[faces[i + 2]], edges[faces[i + 1]], smg, smoothing, color, layer, mat, isBorder); } } } } _smoothVerts.Finish(); }