From 4f0046105dd615eb88b1eab9f97b03acb5104b1f Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 10 Jan 2016 21:09:16 -0600 Subject: [PATCH 1/4] Change texture atlas display to show allocated rectangles --- src/win32/fb_d3d9.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 1641df365..474183086 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -1833,8 +1833,8 @@ void D3DFB::DrawPackedTextures(int packnum) { D3DCOLOR empty_colors[8] = { - 0xFFFF9999, 0xFF99FF99, 0xFF9999FF, 0xFFFFFF99, - 0xFFFF99FF, 0xFF99FFFF, 0xFFFFCC99, 0xFF99CCFF + 0x80FF0000, 0x8000FF00, 0x800000FF, 0x80FFFF00, + 0x80FF00FF, 0x8000FFFF, 0x80FF8000, 0x800080FF }; Atlas *pack; int x = 8, y = 8; @@ -1869,7 +1869,14 @@ void D3DFB::DrawPackedTextures(int packnum) } AddColorOnlyRect(x-1, y-1-LBOffsetI, 258, 258, D3DCOLOR_XRGB(255,255,0)); - AddColorOnlyQuad(x, y-LBOffsetI, 256, 256, D3DCOLOR_ARGB(180,0,0,0)); + int back = 0; + for (PackedTexture *box = pack->UsedList; box != NULL; box = box->Next) + { + AddColorOnlyQuad(x + box->Area.left, y + box->Area.top, + box->Area.right - box->Area.left, box->Area.bottom - box->Area.top, empty_colors[back]); + back = (back + 1) & 7; + } +// AddColorOnlyQuad(x, y-LBOffsetI, 256, 256, D3DCOLOR_ARGB(180,0,0,0)); CheckQuadBatch(); From 670058fa3c1afb9afababec32afad204dbb7216f Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 10 Jan 2016 21:54:28 -0600 Subject: [PATCH 2/4] Switch to the bottom-left picker for the Skyline Bin Packer --- src/SkylineBinPack.cpp | 69 +++++++++++++++++++++++++++++++++++++++++- src/SkylineBinPack.h | 3 ++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/SkylineBinPack.cpp b/src/SkylineBinPack.cpp index 33f862043..4e9de153e 100644 --- a/src/SkylineBinPack.cpp +++ b/src/SkylineBinPack.cpp @@ -119,7 +119,7 @@ Rect SkylineBinPack::Insert(int width, int height) return newNode; } - return InsertMinWaste(width, height); + return InsertBottomLeft(width, height); } bool SkylineBinPack::RectangleFits(int skylineNodeIndex, int width, int height, int &y) const @@ -254,6 +254,73 @@ void SkylineBinPack::MergeSkylines() } } +Rect SkylineBinPack::InsertBottomLeft(int width, int height) +{ + int bestHeight; + int bestWidth; + int bestIndex; + Rect newNode = FindPositionForNewNodeBottomLeft(width, height, bestHeight, bestWidth, bestIndex); + + if (bestIndex != -1) + { + assert(disjointRects.Disjoint(newNode)); + // Perform the actual packing. + AddSkylineLevel(bestIndex, newNode); + + usedSurfaceArea += width * height; +#ifdef _DEBUG + disjointRects.Add(newNode); +#endif + } + else + memset(&newNode, 0, sizeof(Rect)); + + return newNode; +} + +Rect SkylineBinPack::FindPositionForNewNodeBottomLeft(int width, int height, int &bestHeight, int &bestWidth, int &bestIndex) const +{ + bestHeight = INT_MAX; + bestIndex = -1; + // Used to break ties if there are nodes at the same level. Then pick the narrowest one. + bestWidth = INT_MAX; + Rect newNode = { 0, 0, 0, 0 }; + for(unsigned i = 0; i < skyLine.Size(); ++i) + { + int y; + if (RectangleFits(i, width, height, y)) + { + if (y + height < bestHeight || (y + height == bestHeight && skyLine[i].width < bestWidth)) + { + bestHeight = y + height; + bestIndex = i; + bestWidth = skyLine[i].width; + newNode.x = skyLine[i].x; + newNode.y = y; + newNode.width = width; + newNode.height = height; + assert(disjointRects.Disjoint(newNode)); + } + } +/* if (RectangleFits(i, height, width, y)) + { + if (y + width < bestHeight || (y + width == bestHeight && skyLine[i].width < bestWidth)) + { + bestHeight = y + width; + bestIndex = i; + bestWidth = skyLine[i].width; + newNode.x = skyLine[i].x; + newNode.y = y; + newNode.width = height; + newNode.height = width; + assert(disjointRects.Disjoint(newNode)); + } + } +*/ } + + return newNode; +} + Rect SkylineBinPack::InsertMinWaste(int width, int height) { int bestHeight; diff --git a/src/SkylineBinPack.h b/src/SkylineBinPack.h index f93ddd29d..937c88de6 100644 --- a/src/SkylineBinPack.h +++ b/src/SkylineBinPack.h @@ -72,7 +72,10 @@ private: bool useWasteMap; GuillotineBinPack wasteMap; + Rect InsertBottomLeft(int width, int height); Rect InsertMinWaste(int width, int height); + + Rect FindPositionForNewNodeBottomLeft(int width, int height, int &bestHeight, int &bestWidth, int &bestIndex) const; Rect FindPositionForNewNodeMinWaste(int width, int height, int &bestHeight, int &bestWastedArea, int &bestIndex) const; bool RectangleFits(int skylineNodeIndex, int width, int height, int &y) const; From aaac5ac7a122d7d0cae223964b0624ae3af3c02e Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 10 Jan 2016 22:01:29 -0600 Subject: [PATCH 3/4] Use not so brilliant backgrounds for allocated atlas backgrounds --- src/win32/fb_d3d9.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 474183086..bfb618b51 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -1833,8 +1833,8 @@ void D3DFB::DrawPackedTextures(int packnum) { D3DCOLOR empty_colors[8] = { - 0x80FF0000, 0x8000FF00, 0x800000FF, 0x80FFFF00, - 0x80FF00FF, 0x8000FFFF, 0x80FF8000, 0x800080FF + 0x50FF0000, 0x5000FF00, 0x500000FF, 0x50FFFF00, + 0x50FF00FF, 0x5000FFFF, 0x50FF8000, 0x500080FF }; Atlas *pack; int x = 8, y = 8; From 42e9a6a711816bb2fce51166220cb7d8bc19f063 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 10 Jan 2016 22:14:35 -0600 Subject: [PATCH 4/4] Make atlas size a macro definition and default it to 512x512 (was 256x256) --- src/win32/fb_d3d9.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index bfb618b51..4e3a14c18 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -85,6 +85,10 @@ // The number of quads we can batch together. #define MAX_QUAD_BATCH (NUM_INDEXES / 6) +// The default size for a texture atlas. +#define DEF_ATLAS_WIDTH 512 +#define DEF_ATLAS_HEIGHT 512 + // TYPES ------------------------------------------------------------------- IMPLEMENT_CLASS(D3DFB) @@ -1872,8 +1876,11 @@ void D3DFB::DrawPackedTextures(int packnum) int back = 0; for (PackedTexture *box = pack->UsedList; box != NULL; box = box->Next) { - AddColorOnlyQuad(x + box->Area.left, y + box->Area.top, - box->Area.right - box->Area.left, box->Area.bottom - box->Area.top, empty_colors[back]); + AddColorOnlyQuad( + x + box->Area.left * 256 / pack->Width, + y + box->Area.top * 256 / pack->Height, + (box->Area.right - box->Area.left) * 256 / pack->Width, + (box->Area.bottom - box->Area.top) * 256 / pack->Height, empty_colors[back]); back = (back + 1) & 7; } // AddColorOnlyQuad(x, y-LBOffsetI, 256, 256, D3DCOLOR_ARGB(180,0,0,0)); @@ -1980,8 +1987,8 @@ D3DFB::PackedTexture *D3DFB::AllocPackedTexture(int w, int h, bool wrapping, D3D Rect box; bool padded; - // check for 254 to account for padding - if (w > 254 || h > 254 || wrapping) + // The - 2 to account for padding + if (w > 256 - 2 || h > 256 - 2 || wrapping) { // Create a new texture atlas. pack = new Atlas(this, w, h, format); pack->OneUse = true; @@ -2006,7 +2013,7 @@ D3DFB::PackedTexture *D3DFB::AllocPackedTexture(int w, int h, bool wrapping, D3D } if (pack == NULL) { // Create a new texture atlas. - pack = new Atlas(this, 256, 256, format); + pack = new Atlas(this, DEF_ATLAS_WIDTH, DEF_ATLAS_HEIGHT, format); box = pack->Packer.Insert(w, h); } padded = true;