Exemplo n.º 1
0
 public void GenerateTextureAndUV(VoxelModel model, MeshSlices slices, out Bitmap bitmap)
 {
     throw new NotImplementedException();
 }
Exemplo n.º 2
0
        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;
                        }
                    }
                }
            }
        }
Exemplo n.º 3
0
        public void Save(MeshSlices slices, Bitmap texture, string path, IProgressListener progress)
        {
            var name = System.IO.Path.GetFileNameWithoutExtension(path);
            var mtlname = name + ".mtl";
            var imgname = name + ".png";
            var dirname = System.IO.Path.GetDirectoryName(System.IO.Path.GetFullPath(path));

            progress?.Report("Opening the output file");
            progress?.Report(0);

            using (var writer = System.IO.File.CreateText(path))
            {
                progress?.Report("Writing headers");

                writer.WriteLine($"mtllib {mtlname}");
                writer.WriteLine("o Object");

                progress?.Report("Writing position");
                int numTotalSlices = slices.Select((slicelist) => slicelist.Length).Sum();
                int sliceIndex = 0;
                foreach (var slicelist in slices)
                {
                    foreach (var slice in slicelist)
                    {
                        foreach (var vt in slice.Positions)
                        {
                            // Usually Y is the upward direction for OBJs
                            writer.WriteLine($"v {vt.X} {-vt.Z} {vt.Y}");
                        }
                        ++sliceIndex;
                        progress?.Report((double)sliceIndex / numTotalSlices * (1.0 / 3.0));
                    }
                }

                progress?.Report("Writing UV coordinates");
                sliceIndex = 0;
                foreach (var slicelist in slices)
                {
                    foreach (var slice in slicelist)
                    {
                        foreach (var uv in slice.UVs)
                        {
                            writer.WriteLine($"vt {uv.X / texture.Width} {1f - uv.Y / texture.Height}");
                        }
                        ++sliceIndex;
                        progress?.Report((double)sliceIndex / numTotalSlices * (1.0 / 3.0) + (1.0 / 3.0));
                    }
                }

                writer.WriteLine("usemtl Material");
                writer.WriteLine("s off");

                progress?.Report("Writing faces");

                int vtxidx = 1;
                sliceIndex = 0;
                foreach (var slicelist in slices)
                {
                    foreach (var slice in slicelist)
                    {
                        foreach (var f in slice.MeshSliceFaces)
                        {
                            writer.Write("f");
                            for (int i = f.StartIndex; i < f.EndIndex; ++i)
                            {
                                writer.Write($" {vtxidx + i}/{vtxidx + i}");
                            }
                            writer.WriteLine();
                        }
                        vtxidx += slice.Positions.Length;

                        ++sliceIndex;
                        progress?.Report((double)sliceIndex / numTotalSlices * (1.0 / 3.0) + (2.0 / 3.0));
                    }
                }
            } // using writer

            progress?.Report("Saving material");

            using (var writer = System.IO.File.CreateText(System.IO.Path.Combine(dirname, mtlname)))
            {
                writer.WriteLine("newmtl Material");
                writer.WriteLine("Ka 0 0 0");
                writer.WriteLine("Kd 1 1 1");
                writer.WriteLine("Ks 0.2 0.2 0.2");
                writer.WriteLine("Ni 1");
                writer.WriteLine("d 1");
                writer.WriteLine("illum 2");
                writer.WriteLine($"map_Kd {imgname}");
            }

            progress?.Report("Saving texture");

            texture.Save(System.IO.Path.Combine(dirname, imgname),
                         System.Drawing.Imaging.ImageFormat.Png);
        }
Exemplo n.º 4
0
        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;
        }