public void Pack() { atlasPath = null; jsonPath = null; //@todo if (_PURE_WHITE == null) { _PURE_WHITE = AssetDatabase.LoadAssetAtPath <Texture2D>("Assets/SeinJSUnityToolkit/Shaders/white.png"); } atlasTexture = new Texture2D(maxWidth, maxHeight); Graphics.CopyTexture(_PURE_WHITE, 0, 0, 0, 0, maxWidth, maxHeight, atlasTexture, 0, 0, 0, 0); Utils.DoActionForTextures(ref images, (texs) => { rects = BinPacker.Pack(texs, atlasTexture, padding); atlasTexture.Apply(); }); if (rects == null) { EditorUtility.DisplayDialog("Error!", "Pack failed, atlas' size may be too small !", "OK"); return; } if (saveAfterPack) { Save(); } }
public void Pack_AdjustedGlyphs_All() { // Arrange var glyphs = new List <Bitmap>(); glyphs.Add(new Bitmap(5, 5)); glyphs[0].SetPixel(2, 1, Color.White); glyphs[0].SetPixel(2, 2, Color.White); glyphs[0].SetPixel(2, 3, Color.White); glyphs[0].SetPixel(1, 2, Color.White); glyphs[0].SetPixel(3, 2, Color.White); glyphs.Add(new Bitmap(5, 5)); glyphs[1].SetPixel(2, 2, Color.White); glyphs[1].SetPixel(2, 1, Color.White); glyphs[1].SetPixel(3, 2, Color.White); glyphs.Add(new Bitmap(2, 2)); glyphs[2].SetPixel(0, 0, Color.White); glyphs[2].SetPixel(1, 0, Color.White); var adjustedGlyphs = FontMeasurement.MeasureWhiteSpace(glyphs); var binPacker = new BinPacker(new Size(5, 3)); // Act var boxes = binPacker.Pack(adjustedGlyphs).ToArray(); // Assert boxes.Length.Should().Be(3); boxes[0].position.Should().Be(Point.Empty); boxes[1].position.Should().Be(new Point(3, 0)); boxes[2].position.Should().Be(new Point(3, 2)); }
static void TestBinPack() { List <Bin> bins = new List <Bin>(); for (int i = 0; i < 10; ++i) { Bin b = new Bin(); b.Size = new Vec2i(100, 100); bins.Add(b); } Bin b2 = new Bin(); b2.Size = new Vec2i(12, 200); bins.Add(b2); Bin b3 = new Bin(); b3.Size = new Vec2i(1, 90); bins.Add(b3); BinPacker bp = new BinPacker(512); bp.Pack(bins); Console.WriteLine("Total size: {0} x {1}", bp.Width, bp.Height); }
static void Main(string[] args) { var binPacker = BinPacker.GetDefault(BinPackerVerifyOption.All); var bestAlgorithmRecords = new Dictionary <string, int>(); var round = 0; while (true) { var result = TestBinPacker(binPacker); if (bestAlgorithmRecords.ContainsKey(result.BestAlgorithmName)) { bestAlgorithmRecords[result.BestAlgorithmName]++; } else { bestAlgorithmRecords[result.BestAlgorithmName] = 1; } round++; var binCount = result.BestResult.Count; var cuboidCount = result.BestResult.Sum(x => x.Count); Console.WriteLine($"Round {round} finished, {binCount} bins contains {cuboidCount} cuboids"); Console.WriteLine($"Best algorithm records:"); foreach (var pair in bestAlgorithmRecords.OrderByDescending(x => x.Value)) { Console.WriteLine($"{pair.Key}: {pair.Value}"); } Console.WriteLine(); Thread.Sleep(1); } }
static Tuple <BinPackResult, decimal> TestBinPacker(IBinPacker binPacker) { var binWidth = RandomInstance.Next(100, 5001); var binHeight = RandomInstance.Next(100, 5001); var binDepth = RandomInstance.Next(100, 5001); var binWeight = RandomInstance.Next(100, 5001); var cuboidsCount = RandomInstance.Next(50, 501); var allowRotateVertically = RandomInstance.Next(0, 2) == 0; var cuboids = new List <Cuboid>(); for (var x = 0; x < cuboidsCount; ++x) { var width = RandomInstance.Next(1, binWidth + 1); var height = RandomInstance.Next(1, binHeight + 1); var depth = RandomInstance.Next(1, binDepth + 1); var weight = RandomInstance.Next(1, binWeight / 20 + 1); cuboids.Add(new Cuboid(width, height, depth, weight, null)); } var parameter = new BinPackParameter( binWidth, binHeight, binDepth, binWeight, allowRotateVertically, cuboids); var result = binPacker.Pack(parameter); var volumeRate = BinPacker.GetVolumeRate(parameter, result.BestResult); return(Tuple.Create(result, volumeRate)); }
static void Main(string[] args) { // Define the size of bin var binWidth = 1000; var binHeight = 1000; var binDepth = 1000; // Define the cuboids to pack var parameter = new BinPackParameter(binWidth, binHeight, binDepth, new[] { new Cuboid(150, 100, 150), new Cuboid(500, 500, 500), new Cuboid(500, 550, 700), new Cuboid(350, 350, 350), new Cuboid(650, 750, 850), }); // Create a bin packer instance // The default bin packer will test all algorithms and try to find the best result // BinPackerVerifyOption is used to avoid bugs, it will check whether the result is correct var binPacker = BinPacker.GetDefault(BinPackerVerifyOption.BestOnly); // The result contains bins which contains packed cuboids whith their coordinates var result = binPacker.Pack(parameter); foreach (var bins in result.BestResult) { Console.WriteLine("Bin:"); foreach (var cuboid in bins) { Console.WriteLine(cuboid); } } }
public void EmptyImageTest() { BinPacker pkr1 = new BinPacker(); BinPacker pkr2 = new BinPacker(); byte [] img = pkr1.GetBinaryImage(); pkr2.SetBinaryImage(img); Assert.AreEqual(0,pkr2.Files.Count); }
public void BadImageTest() { byte [] image1 = {1,2,3,4}; BinPacker pkr1 = new BinPacker(); try { pkr1.SetBinaryImage(image1); Assert.IsTrue(false); } catch(SerializationException ex) { Console.WriteLine(ex.Message); } }
public void Pack_AdjustedGlyphs_Space() { // Arrange var glyphs = new List <Bitmap>(); glyphs.Add(new Bitmap(5, 5)); var adjustedGlyphs = FontMeasurement.MeasureWhiteSpace(glyphs); var binPacker = new BinPacker(new Size(6, 6)); // Act var boxes = binPacker.Pack(adjustedGlyphs).ToArray(); // Assert boxes.Length.Should().Be(1); boxes[0].position.Should().Be(new Point(1, 1)); }
static void Main(string[] args) { var binPacker = BinPacker.GetDefault(BinPackerVerifyOption.All); var averageVolumeRate = 0m; var round = 0; while (true) { var tuple = TestBinPacker(binPacker); var result = tuple.Item1; var volumeRate = tuple.Item2; averageVolumeRate = (averageVolumeRate * round + volumeRate) / (round + 1); round++; var binCount = result.BestResult.Count; var cuboidCount = result.BestResult.Sum(x => x.Count); Console.WriteLine( $"Round {round} finished, {binCount} bins contains {cuboidCount} cuboids, " + $"average volume rate {averageVolumeRate.ToString("0.0000")}"); Thread.Sleep(1); } }
static void Main(string[] args) { DisplayIntro(); SetUpLogging(); if (args.Length == 0) { DisplayHelpText(); } else { string folderPath = args[0]; string prefix = "P"; if (args.Length == 2) { prefix = args[1]; } BinPacker binPacker = new BinPacker(folderPath, prefix); binPacker.ProcessFolder(); string binListing = binPacker.GetBinListing(); Console.WriteLine(binListing); binPacker.MoveFilesIntoBins(); } }
/* * This function try to rearranges all objects on the build platform so they * do not touch each other */ public void RearrangeObjects() { BinPacker bp = new BinPacker(); List<BinPacker.BinRect> rects = new List<BinPacker.BinRect>(); foreach (Object3d obj in m_objects) { if (obj.tag != Object3d.OBJ_NORMAL) continue; float w = obj.m_max.x - obj.m_min.x; float h = obj.m_max.y - obj.m_min.y; BinPacker.BinRect rc = new BinPacker.BinRect(w, h, obj); rects.Add(rc); } float pw = (float)UVDLPApp.Instance().m_printerinfo.m_PlatXSize; float ph = (float)UVDLPApp.Instance().m_printerinfo.m_PlatYSize; bp.Pack(rects, (int)pw, (int)ph, true); // find pack size int maxw = 0; int maxh = 0; foreach (BinPacker.BinRect rc in rects) { if (rc.packed && ((rc.x + rc.w) > maxw)) maxw = rc.x + rc.w; if (rc.packed && ((rc.y + rc.h) > maxh)) maxh = rc.y + rc.h; } // find offsets to center all objects float offsx = -(float)maxw / 2f + 0.5f; float offsy = -(float)maxh / 2f + 0.5f; // move all objects to new positions foreach (BinPacker.BinRect rc in rects) { Object3d obj = (Object3d)rc.obj; if (rc.packed) { if (rc.rotated) obj.Rotate(0, 0, 1.570796326f); float dx = rc.x - obj.m_min.x + offsx; float dy = rc.y - obj.m_min.y + offsy; obj.Translate(dx, dy, 0, true); } else { // object could not fit, place outside platform obj.Translate(pw / 2f - obj.m_min.x, 0, 0, true); } } UVDLPApp.Instance().RaiseAppEvent(eAppEvent.eReDraw,"Redraw new arrangement"); }
public void GenereteUserTexture() { if (mUserTexture >= 0) { DeleteTexture(mUserTexture); } // step 1, arrange all textures in a one big bitmap; Bitmap bmp = new Bitmap(2048, 2048, System.Drawing.Imaging.PixelFormat.Format32bppArgb); float tw = bmp.Width; float th = bmp.Height; BinPacker bp = new BinPacker(); List <BinPacker.BinRect> rects = new List <BinPacker.BinRect>(); foreach (C2DImage img in mNewImages) { BinPacker.BinRect rc = new BinPacker.BinRect(img.w, img.h, img); rects.Add(rc); } bp.Pack(rects, bmp.Width, bmp.Height, false); List <C2DImage> packedImages = new List <C2DImage>(); foreach (BinPacker.BinRect rc in rects) { C2DImage img = (C2DImage)rc.obj; if (rc.packed) { img.x = rc.x; img.y = rc.y; img.x1 = (img.x + 0.5f) / tw; img.y1 = (img.y + 0.5f) / th; img.x2 = img.x1 + (float)(img.w - 1) / tw; img.y2 = img.y1 + (float)(img.h - 1) / th; img.scalex = tw; img.scaley = th; for (int i = 0; i < img.bmp.Height; i++) { System.Drawing.Imaging.BitmapData ddata = bmp.LockBits(new Rectangle((int)img.x, (int)img.y + i, img.bmp.Width, 1), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb); System.Drawing.Imaging.BitmapData sdata = img.bmp.LockBits(new Rectangle(0, i, img.bmp.Width, 1), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int numBytes = 4 * img.bmp.Width; byte[] rgbValues = new byte[numBytes]; Marshal.Copy(sdata.Scan0, rgbValues, 0, numBytes); Marshal.Copy(rgbValues, 0, ddata.Scan0, numBytes); bmp.UnlockBits(ddata); img.bmp.UnlockBits(sdata); } packedImages.Add(img); mNewImages.Remove(img); } } if (mNewImages.Count != 0) { DebugLogger.Instance().LogError("Not all user images could be loaded"); } //bmp.Save("packedbmp.png", System.Drawing.Imaging.ImageFormat.Png); mUserTexture = LoadTextureImage(bmp); foreach (C2DImage img in packedImages) { img.tex = mUserTexture; ImgDbase[img.name] = img; } needPacking = false; }
/* * This function try to rearranges all objects on the build platform so they * do not touch each other */ public void RearrangeObjects() { BinPacker bp = new BinPacker(); List <BinPacker.BinRect> rects = new List <BinPacker.BinRect>(); foreach (Object3d obj in m_objects) { if (obj.tag != Object3d.OBJ_NORMAL) { continue; } float w = obj.m_max.x - obj.m_min.x; float h = obj.m_max.y - obj.m_min.y; BinPacker.BinRect rc = new BinPacker.BinRect(w, h, obj); rects.Add(rc); } float pw = (float)UVDLPApp.Instance().m_printerinfo.m_PlatXSize; float ph = (float)UVDLPApp.Instance().m_printerinfo.m_PlatYSize; bp.Pack(rects, (int)pw, (int)ph, true); // find pack size int maxw = 0; int maxh = 0; foreach (BinPacker.BinRect rc in rects) { if (rc.packed && ((rc.x + rc.w) > maxw)) { maxw = rc.x + rc.w; } if (rc.packed && ((rc.y + rc.h) > maxh)) { maxh = rc.y + rc.h; } } // find offsets to center all objects float offsx = -(float)maxw / 2f + 0.5f; float offsy = -(float)maxh / 2f + 0.5f; // move all objects to new positions foreach (BinPacker.BinRect rc in rects) { Object3d obj = (Object3d)rc.obj; if (rc.packed) { if (rc.rotated) { obj.Rotate(0, 0, 1.570796326f); } float dx = rc.x - obj.m_min.x + offsx; float dy = rc.y - obj.m_min.y + offsy; obj.Translate(dx, dy, 0, true); } else { // object could not fit, place outside platform obj.Translate(pw / 2f - obj.m_min.x, 0, 0, true); } } UVDLPApp.Instance().RaiseAppEvent(eAppEvent.eReDraw, "Redraw new arrangement"); }
public void BinPackerBasicTest() { const string image_name1 = "first"; const string image_name2 = "second"; const string image_name3 = "third"; BinPacker pkr1 = new BinPacker(); BinPacker pkr2 = new BinPacker(); pkr1.Files.Add(new FileToTransmit(image_name1,image1)); pkr1.Files.Add(new FileToTransmit(image_name2,image2)); pkr1.Files.Add(new FileToTransmit(image_name3,image3)); byte [] binImage = pkr1.GetBinaryImage(); pkr2.SetBinaryImage(binImage); Assert.AreEqual(3,pkr2.Files.Count); bool first_seen = false; bool second_seen = false; bool third_seen = false; byte [] compare_img = null; foreach(FileToTransmit ftt in pkr2.Files) { switch(ftt.Filename) { case image_name1: first_seen = true; compare_img = image1; break; case image_name2: second_seen = true; compare_img = image2; break; case image_name3: third_seen = true; compare_img = image3; break; } int curr_byte = 0; foreach(byte b in ftt.File_image) { Assert.AreEqual(b,compare_img[curr_byte]); curr_byte++; } } Assert.IsTrue(first_seen); Assert.IsTrue(second_seen); Assert.IsTrue(third_seen); }
public List <HSolution> BuildSolutions(HAnalysis analysis) { List <ContentItem> contentItems = new List <ContentItem>(analysis.Content); // *** Sharp3DBinPacking : begin // create cuboid list List <Cuboid> listCuboids = new List <Cuboid>(); bool bAllowAllOrientations = true; foreach (ContentItem ci in contentItems) { for (int i = 0; i < ci.Number; ++i) { if (ci.Pack is BoxProperties b) { listCuboids.Add( new Cuboid((decimal)b.Length, (decimal)b.Width, (decimal)b.Height) { Tag = b, AllowOrientX = ci.AllowOrientX, AllowOrientY = ci.AllowOrientY, AllowOrientZ = ci.AllowOrientZ } ); } if (!ci.AllowOrientX || !ci.AllowOrientY || !ci.AllowOrientZ) { bAllowAllOrientations = false; } } } // dim container + offset Vector3D dimContainer = analysis.DimContainer(0), offset = analysis.Offset(0); // Create a bin packer instance // The default bin packer will test all algorithms and try to find the best result // BinPackerVerifyOption is used to avoid bugs, it will check whether the result is correct var binPacker = BinPacker.GetDefault(BinPackerVerifyOption.BestOnly, bAllowAllOrientations); // The result contains bins which contains packed cuboids whith their coordinates var parameter = new BinPackParameter( (decimal)dimContainer.X, (decimal)dimContainer.Y, (decimal)dimContainer.Z, listCuboids.ToArray()) { }; var binPackResult = binPacker.Pack(parameter); List <HSolution> solutions = new List <HSolution>(); //foreach (var result in binPackResult.BestResult) //{ HSolution sol = new HSolution("") { Analysis = analysis }; foreach (var bins in binPackResult.BestResult) { HSolItem hSolItem = sol.CreateSolItem(); foreach (var cuboid in bins) { CuboidToSolItem(contentItems, offset, cuboid, out int index, out BoxPosition pos); hSolItem.InsertContainedElt(index, pos); } } solutions.Add(sol); //} // *** Sharp3DBinPacking : end return(solutions); }
public List <HSolution> BuildSolutions(AnalysisHetero analysis) { // dim container + offset Vector3D dimContainer = analysis.DimContainer(0), offset = analysis.Offset(0); // content items List <ContentItem> contentItems = new List <ContentItem>(analysis.Content); // solutions List <HSolution> solutions = new List <HSolution>(); // *** Sharp3DBinPacking : begin // create cuboid list List <Cuboid> listCuboids = new List <Cuboid>(); bool bAllowAllOrientations = true; foreach (ContentItem ci in contentItems) { for (int i = 0; i < ci.Number; ++i) { if (!ci.AllowOrientX && !ci.AllowOrientY && !ci.AllowOrientZ) { continue; } if (ci.Pack is BoxProperties b) { listCuboids.Add( new Cuboid((decimal)b.Length, (decimal)b.Width, (decimal)b.Height) { Tag = b , AllowOrientX = ci.AllowOrientX , AllowOrientY = ci.AllowOrientY , AllowOrientZ = ci.AllowOrientZ } ); } } if (!ci.AllowOrientX || !ci.AllowOrientY || !ci.AllowOrientZ) { bAllowAllOrientations = false; } } // Create a bin packer instance // The default bin packer will test all algorithms and try to find the best result // BinPackerVerifyOption is used to avoid bugs, it will check whether the result is correct var binPacker = BinPacker.GetDefault(BinPackerVerifyOption.BestOnly, bAllowAllOrientations); // The result contains bins which contains packed cuboids whith their coordinates var parameter = new BinPackParameter( (decimal)dimContainer.X, (decimal)dimContainer.Y, (decimal)dimContainer.Z, listCuboids.ToArray()) { }; var binPackResult = binPacker.Pack(parameter); { HSolution sol = new HSolution("Sharp3DBinPacking") { Analysis = analysis }; foreach (var bins in binPackResult.BestResult) { HSolItem hSolItem = sol.CreateSolItem(); foreach (var cuboid in bins) { CuboidToSolItem(contentItems, offset, cuboid, out int index, out BoxPosition pos); hSolItem.InsertContainedElt(index, pos); } } solutions.Add(sol); } // *** Sharp3DBinPacking : end // *** BoxoLogic : begin List <BoxItem> listItems = new List <BoxItem>(); foreach (ContentItem ci in contentItems) { for (int i = 0; i < ci.Number; ++i) { if (ci.Pack is BoxProperties b) { listItems.Add( new BoxItem() { ID = BoxToID(b), Boxx = (decimal)b.Length, Boxy = (decimal)b.Width, Boxz = (decimal)b.Height, AllowX = ci.AllowOrientX, AllowY = ci.AllowOrientY, AllowZ = ci.AllowOrientZ, N = 1 } ); } } } var bl = new Boxlogic() { OutputFilePath = string.Empty }; var solArray = new SolutionArray(); bl.Run(listItems.ToArray(), (decimal)dimContainer.X, (decimal)dimContainer.Y, (decimal)dimContainer.Z, ref solArray); foreach (var solution in solArray.Solutions) { HSolution sol = new HSolution($"Boxologic - Variant {solution.Variant}") { Analysis = analysis }; HSolItem hSolItem = sol.CreateSolItem(); Transform3D transform; switch (solution.Variant) { case 1: transform = Transform3D.Translation(new Vector3D(0.0, dimContainer.Y, 0.0)) * Transform3D.RotationX(90.0); break; case 2: transform = Transform3D.Translation(new Vector3D(dimContainer.X, 0.0, 0.0)) * Transform3D.RotationZ(90.0); break; case 3: transform = Transform3D.Translation(new Vector3D(dimContainer.X, 0.0, 0.0)) * Transform3D.RotationZ(90.0); break; case 4: transform = Transform3D.Translation(new Vector3D(dimContainer.X, 0.0, 0.0)) * Transform3D.RotationY(-90.0); break; case 5: transform = Transform3D.Translation(new Vector3D(0.0, dimContainer.Y, 0.0)) * Transform3D.RotationX(90.0); break; default: transform = Transform3D.Identity; break; } foreach (var item in solution.ItemsPacked) { BoxInfoToSolItem(contentItems, offset, item, transform, out int index, out BoxPosition pos); hSolItem.InsertContainedElt(index, pos.Adjusted(new Vector3D((double)item.DimX, (double)item.DimY, (double)item.DimZ))); } solutions.Add(sol); } // *** BoxoLogic : end return(solutions); }
public List <HSolution> BuildSolutions(AnalysisHetero analysis) { // dim container + offset Vector3D dimContainer = analysis.DimContainer(0), offset = analysis.Offset(0); // content items List <ContentItem> contentItems = new List <ContentItem>(analysis.Content); // solutions List <HSolution> solutions = new List <HSolution>(); // *** Sharp3DBinPacking : begin // create cuboid list List <Cuboid> listCuboids = new List <Cuboid>(); bool bAllowAllOrientations = true; foreach (ContentItem ci in contentItems) { for (int i = 0; i < ci.Number; ++i) { if (!ci.AllowOrientX && !ci.AllowOrientY && !ci.AllowOrientZ) { continue; } if (ci.Pack is BoxProperties b) { listCuboids.Add( new Cuboid((decimal)b.Length, (decimal)b.Width, (decimal)b.Height) { Tag = BoxToID(ci.Pack as BoxProperties) , AllowOrientX = ci.AllowOrientX , AllowOrientY = ci.AllowOrientY , AllowOrientZ = ci.AllowOrientZ , PriorityLevel = ci.PriorityLevel } ); } } if (!ci.AllowOrientX || !ci.AllowOrientY || !ci.AllowOrientZ) { bAllowAllOrientations = false; } } // Create a bin packer instance // The default bin packer will test all algorithms and try to find the best result // BinPackerVerifyOption is used to avoid bugs, it will check whether the result is correct var binPacker = BinPacker.GetDefault(BinPackerVerifyOption.BestOnly, bAllowAllOrientations); // The result contains bins which contains packed cuboids whith their coordinates var parameter = new BinPackParameter( (decimal)dimContainer.X, (decimal)dimContainer.Y, (decimal)dimContainer.Z, listCuboids.ToArray()) { ShuffleCount = 0 }; var binPackResult = binPacker.Pack(parameter); { HSolution sol = new HSolution("Sharp3DBinPacking") { Analysis = analysis }; foreach (var bins in binPackResult.BestResult) { HSolItem hSolItem = sol.CreateSolItem(); foreach (var cuboid in bins) { CuboidToSolItem(contentItems, offset, cuboid, out int index, out BoxPosition pos); hSolItem.InsertContainedElt(index, pos); } } solutions.Add(sol); } // *** Sharp3DBinPacking : end // *** BoxoLogic : begin bool singleSol = true; for (int variant = singleSol? 5 : 1; variant < 6; ++variant) { HSolution sol = new HSolution($"Boxologic - Variant {variant}") { Analysis = analysis }; RunBoxologic(variant, sol, dimContainer, offset, contentItems); solutions.Add(sol); } // for // *** BoxoLogic : end return(solutions); }
public void SetUp() { _binPacker = new BinPacker(); }
public void GenereteUserTexture() { if (mUserTexture >= 0) DeleteTexture(mUserTexture); // step 1, arrange all textures in a one big bitmap; Bitmap bmp = new Bitmap(2048, 2048, System.Drawing.Imaging.PixelFormat.Format32bppArgb); Graphics gr = Graphics.FromImage(bmp); gr.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy; //gr.ResetTransform(); //gr.PageUnit = GraphicsUnit.Pixel; using (Brush br = new SolidBrush(Color.FromArgb(0, 0, 0, 0))) { gr.FillRectangle(br, new Rectangle(0,0,bmp.Width,bmp.Height)); } float tw = bmp.Width; float th = bmp.Height; BinPacker bp = new BinPacker(); List<BinPacker.BinRect> rects = new List<BinPacker.BinRect>(); foreach (C2DImage img in mNewImages) { BinPacker.BinRect rc = new BinPacker.BinRect(img.w, img.h, img); rects.Add(rc); } bp.Pack(rects, bmp.Width, bmp.Height, false); List<C2DImage> packedImages = new List<C2DImage>(); foreach (BinPacker.BinRect rc in rects) { C2DImage img = (C2DImage)rc.obj; if (rc.packed) { img.x = rc.x; img.y = rc.y; img.x1 = (img.x + 0.5f) / tw; img.y1 = (img.y + 0.5f) / th; img.x2 = img.x1 + (float)(img.w - 1) / tw; img.y2 = img.y1 + (float)(img.h - 1) / th; img.scalex = tw; img.scaley = th; gr.DrawImage(img.bmp, img.x, img.y, img.bmp.Width, img.bmp.Height); //img.bmp.Save("origbmp.png", System.Drawing.Imaging.ImageFormat.Png); packedImages.Add(img); mNewImages.Remove(img); } } if (mNewImages.Count != 0) { DebugLogger.Instance().LogError("Not all user images could be loaded"); } //bmp.Save("packedbmp.png", System.Drawing.Imaging.ImageFormat.Png); mUserTexture = LoadTextureImage(bmp); foreach (C2DImage img in packedImages) { img.tex = mUserTexture; ImgDbase[img.name] = img; } needPacking = false; }