public uint this[IntVector3 pos] { get { return data[GetIndexForVoxel(pos)]; } set { data[GetIndexForVoxel(pos)] = value; } }
public void GenerateTextureAndUV(VoxelModel model, MeshSlices slices, out Bitmap bitmap, IProgressListener progress) { // Collect colors var colors = new List<int>(); // Marshal.Copy doesn't support uint[] lol int totalSlices = 0; foreach (var slicelist in slices) { totalSlices += slicelist.Length; } int sliceIndex = 0; progress?.Report("Collecting colors"); foreach (var slicelist in slices) { foreach (var slice in slicelist) { ++sliceIndex; progress?.Report((double)sliceIndex / totalSlices); var verts = slice.Positions; Axis3 paxis1, paxis2; GetPerpendicularAxises(slice.Axis, out paxis1, out paxis2); var pt = new IntVector3(); pt[slice.Axis] = slice.Layer; foreach (var face in slice.MeshSliceFaces) { var scoord = FindSliceCoordForFace(slice, face, slice.Axis, paxis1, paxis2); pt[paxis1] = scoord.X; pt[paxis2] = scoord.Y; colors.Add((int) (model[pt] | 0xff000000)); } } } // Determine the dimensions of the texture int texwidth = (int)Math.Ceiling(Math.Sqrt(colors.Count)); int texheight = (colors.Count + texwidth - 1) / texwidth; // And then create the texture bitmap = new Bitmap(texwidth * 2, texheight * 2, System.Drawing.Imaging.PixelFormat.Format32bppRgb); var bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb); System.Runtime.InteropServices.Marshal.Copy(Scale2x(colors.ToArray(), texwidth, texheight), 0, bmpdata.Scan0, colors.Count * 4); bitmap.UnlockBits(bmpdata); // Assign UVs int faceu = 0, facev = 0; sliceIndex = 0; progress?.Report("Assigning UV coordinates"); foreach (var slicelist in slices) { foreach (var slice in slicelist) { ++sliceIndex; progress?.Report((double)sliceIndex / totalSlices); var verts = slice.Positions; var uvs = slice.UVs = new Vector2[slice.Positions.Length]; Axis3 paxis1, paxis2; GetPerpendicularAxises(slice.Axis, out paxis1, out paxis2); foreach (var face in slice.MeshSliceFaces) { var scoord = FindSliceCoordForFace(slice, face, slice.Axis, paxis1, paxis2); var uv = new Vector2((float) (faceu << 1) + 0.5f, (float) (facev << 1) + 0.5f); for (int i = face.StartIndex; i < face.EndIndex; ++i) { var vt = verts[i]; float u = uv.X + (float)(vt[paxis1] - scoord.X); float v = uv.Y + (float)(vt[paxis2] - scoord.Y); uvs[i] = new Vector2(u, v); } faceu += 1; if (faceu == texwidth) { faceu = 0; facev += 1; } } } } }
public MeshSlices GenerateSlices(VoxelModel model, IProgressListener progress) { var slices = new MeshSlices(); var dims = model.Dimensions; int totalsteps = 2 * (model.Width + model.Height + model.Depth); int step = 0; progress?.Report("Generating slices"); for (int iaxis = 0; iaxis < 3; ++iaxis) { for (int iface = 0; iface < 2; ++iface) { var axis = (Axis3) iaxis; var paxis1 = (Axis3) ((iaxis + 1) % 3); var paxis2 = (Axis3) ((iaxis + 2) % 3); bool face = iface != 0; int dim0 = dims[axis]; int dim1 = dims[paxis1]; int dim2 = dims[paxis2]; var slicelist = new MeshSlice[dim0]; slices[axis, face] = slicelist; for (int layer = 0; layer < dim0; ++layer) { ++step; progress?.Report((double)step / totalsteps); var faces = new List<int>(); var ret = new List<IntVector3>(); var pt1 = new IntVector3(); pt1[axis] = layer; for (int x = 0; x < dim1; ++x) { pt1[paxis1] = x; for (int y = 0; y < dim2; ++y) { pt1[paxis2] = y; bool solid1 = model.IsVoxelSolid(pt1); var pt2 = pt1; bool solid2 = false; if (face) { pt2[axis] += 1; if (pt2[axis] < dim0) { solid2 = model.IsVoxelSolid(pt2); } } else { pt2[axis] -= 1; if (pt2[axis] >= 0) { solid2 = model.IsVoxelSolid(pt2); } } if (!solid1 || solid2) { continue; } // Create quad var qpt1 = pt1; if (face) { qpt1[axis] += 1; qpt1[paxis2] += 1; } var qpt2 = qpt1; qpt2[paxis1] += 1; var qpt3 = qpt1; var qpt4 = qpt2; if (face) { qpt3[paxis2] -= 1; qpt4[paxis2] -= 1; } else { qpt3[paxis2] += 1; qpt4[paxis2] += 1; } // Emit polygons faces.Add(ret.Count); ret.Add(qpt3); ret.Add(qpt4); ret.Add(qpt2); ret.Add(qpt1); } // for y } // for x slicelist[layer] = new MeshSlice() { Positions = ret.ToArray(), Faces = faces.ToArray(), Face = face, Axis = axis, Layer = layer }; } // for slice } // iface } // iaxis return slices; }
int GetIndexForVoxel(IntVector3 p) { return (p.X * height + p.Y) * depth + p.Z; }
public bool IsVoxelSolid(IntVector3 p) { return this[p] != EmptyVoxel; }