private AreaRow newAreaRow(int yPos, int width, int height) { AreaRow r = new AreaRow(); r.EmptySpaces = new List <AtlasRect>(); r.EmptySpaces.Add(newRect(0, yPos, width, height)); r.FilledSpaces = new List <FilledTex>(); r.yPos = yPos; r.width = width; r.height = height; return(r); }
private void buildAtlas(ref List <Bitmap> textures, int width, int height) { List <AreaRow> texRows = new List <AreaRow>(); int curYPos = 0; uint texCount = 0; foreach (Bitmap bmp in textures) { if (texCount == 0) { texRows.Add(newAreaRow(curYPos, width, bmp.Height)); } bool hasBeenSlotted = false; while (!hasBeenSlotted) { foreach (AreaRow texRow in texRows) { if (hasBeenSlotted) { break; } int esi = texCanFit(texRow, bmp); if (esi > -1) { AreaRow ar = texRow; Bitmap mr = bmp; insertIntoEmptySpace(ref ar, ref mr, esi, texCount); hasBeenSlotted = true; } } if (!hasBeenSlotted) { curYPos += texRows[texRows.Count - 1].height; texRows.Add(newAreaRow(curYPos, width, bmp.Height)); } } texCount++; } curYPos += texRows[texRows.Count - 1].height; //System.Console.WriteLine("current Y pos: " + curYPos); atlas = new Bitmap(width, Math.Min(nextPowerOfTwo(curYPos), height)); foreach (AreaRow r in texRows) { //Console.WriteLine("Row number " + (++rNum) + ", RowHeight = "+ r.height); foreach (FilledTex ft in r.FilledSpaces) { entries.Add(newEntry(ft.actualID, ft.rect.X, ft.rect.Y, ft.rect.W, ft.rect.H)); drawOnAtlas(textures[(int)ft.localID], 16, ft.rect.X, ft.rect.Y); } } }
private int texCanFit(AreaRow row, Bitmap bmp) { int entry = 0; foreach (AtlasRect empty in row.EmptySpaces) { if (bmp.Width <= empty.W && bmp.Height <= empty.H) { return(entry); } else { entry++; } } return(-1); }
private bool spaceIsFree(AreaRow row, AtlasRect rect) { foreach (FilledTex tex in row.FilledSpaces) { if (testAABB(rect, tex.rect)) { return(false); } } foreach (AtlasRect empty in row.EmptySpaces) { if (testAABB(rect, empty)) { return(false); } } return(true); }
private void insertIntoEmptySpace(ref AreaRow row, ref Bitmap bmp, int emptySpaceIndex, uint newLocalID) { AtlasRect EmptySpaceRect = row.EmptySpaces[emptySpaceIndex]; FilledTex newTex = new FilledTex(); newTex.rect = newRect( EmptySpaceRect.X, EmptySpaceRect.Y, bmp.Width, bmp.Height ); newTex.localID = newLocalID; newTex.actualID = (uint)bmp.Tag; /* * Console.WriteLine("Adding new tex! (X/Y/W/H/LID: " + * EmptySpaceRect.X + "/" + * EmptySpaceRect.Y + "/" + * bmp.Width + "/" + * bmp.Height + "/" + * newTex.localID.ToString("X2") + ")" * ); */ row.FilledSpaces.Add(newTex); row.EmptySpaces.RemoveAt(emptySpaceIndex); // Remove Old empty space; /* * if (EmptySpaceRect.Width == newTex.rect.Width && * EmptySpaceRect.Height == newTex.rect.Height) * return; */ int yd = row.height - (newTex.rect.Y + newTex.rect.H); int xd = row.width - (newTex.rect.X + newTex.rect.W); if (yd > 0) { /* * Console.WriteLine("Adding new empty space below! (X/Y/W/H: "+ * EmptySpaceRect.X + "/" + * (newTex.rect.Y + newTex.rect.H) + "/" + * newTex.rect.W + "/" + * yd + ")" * ); */ AtlasRect newSpace = newRect( EmptySpaceRect.X, newTex.rect.Y + newTex.rect.H, newTex.rect.W + (row.width - (EmptySpaceRect.X + newTex.rect.W)), yd ); if (spaceIsFree(row, newSpace)) { row.EmptySpaces.Add(newSpace); } } if (xd > 0) { /* * Console.WriteLine("Adding new empty space to the right! (X/Y/W/H: " + * (newTex.rect.X + newTex.rect.W) + "/" + * EmptySpaceRect.Y + "/" + * xd + "/" + * newTex.rect.H + ")" * ); */ AtlasRect newSpace = newRect( newTex.rect.X + newTex.rect.W, EmptySpaceRect.Y, xd, newTex.rect.H ); if (spaceIsFree(row, newSpace)) { row.EmptySpaces.Add(newSpace); } } row.EmptySpaces.Sort((x, y) => { var ret = x.H.CompareTo(y.H); if (ret == 0) { ret = x.W.CompareTo(y.W); } return(ret); }); }