public VoxelRenderData GenerateRenderData(VxlLimb l) { Vertex[] v; try { v = GenerateSlicePlanes(l).SelectMany(x => x).ToArray(); } catch (SheetOverflowException) { // Sheet overflow - allocate a new sheet and try once more Log.Write("debug", "Voxel sheet overflow! Generating new sheet"); sheetBuilder = CreateSheetBuilder(); v = GenerateSlicePlanes(l).SelectMany(x => x).ToArray(); } vertices.Add(v); var start = totalVertexCount; var count = v.Length; totalVertexCount += count; return(new VoxelRenderData(start, count, sheetBuilder.Current)); }
IEnumerable <Vertex[]> GenerateSlicePlanes(VxlLimb l) { Func <int, int, int, VxlElement> get = (x, y, z) => { if (x < 0 || y < 0 || z < 0) { return(null); } if (x >= l.Size[0] || y >= l.Size[1] || z >= l.Size[2]) { return(null); } var v = l.VoxelMap[(byte)x, (byte)y]; if (v == null || !v.ContainsKey((byte)z)) { return(null); } return(l.VoxelMap[(byte)x, (byte)y][(byte)z]); }; // Cull slices without any visible faces var xPlanes = new bool[l.Size[0] + 1]; var yPlanes = new bool[l.Size[1] + 1]; var zPlanes = new bool[l.Size[2] + 1]; for (var x = 0; x < l.Size[0]; x++) { for (var y = 0; y < l.Size[1]; y++) { for (var z = 0; z < l.Size[2]; z++) { if (get(x, y, z) == null) { continue; } // Only generate a plane if it is actually visible if (!xPlanes[x] && get(x - 1, y, z) == null) { xPlanes[x] = true; } if (!xPlanes[x + 1] && get(x + 1, y, z) == null) { xPlanes[x + 1] = true; } if (!yPlanes[y] && get(x, y - 1, z) == null) { yPlanes[y] = true; } if (!yPlanes[y + 1] && get(x, y + 1, z) == null) { yPlanes[y + 1] = true; } if (!zPlanes[z] && get(x, y, z - 1) == null) { zPlanes[z] = true; } if (!zPlanes[z + 1] && get(x, y, z + 1) == null) { zPlanes[z + 1] = true; } } } } for (var x = 0; x <= l.Size[0]; x++) { if (xPlanes[x]) { yield return(GenerateSlicePlane(l.Size[1], l.Size[2], (u, v) => get(x, u, v), (u, v) => get(x - 1, u, v), (u, v) => new float[] { x, u, v })); } } for (var y = 0; y <= l.Size[1]; y++) { if (yPlanes[y]) { yield return(GenerateSlicePlane(l.Size[0], l.Size[2], (u, v) => get(u, y, v), (u, v) => get(u, y - 1, v), (u, v) => new float[] { u, y, v })); } } for (var z = 0; z <= l.Size[2]; z++) { if (zPlanes[z]) { yield return(GenerateSlicePlane(l.Size[0], l.Size[1], (u, v) => get(u, v, z), (u, v) => get(u, v, z - 1), (u, v) => new float[] { u, v, z })); } } }