fixed bugs related to the best-fit heuristic
This commit is contained in:
parent
0c10e7c40e
commit
8d3ef72e3c
@ -1,17 +1,24 @@
|
|||||||
// stb_rect_pack.h - v0.01 - public domain - rectangle packing
|
// stb_rect_pack.h - v0.01 - public domain - rectangle packing
|
||||||
|
// Sean Barrett 2014
|
||||||
//
|
//
|
||||||
// Useful for e.g. packing rectangular textures into an atlas.
|
// Useful for e.g. packing rectangular textures into an atlas.
|
||||||
|
// Does not do rotation.
|
||||||
//
|
//
|
||||||
// By Sean Barrett and Ryan Gordon
|
// Not necessarily the awesomest packing method, but better than
|
||||||
|
// the totally naive one in stb_truetype (which is primarily what
|
||||||
|
// this is meant to replace).
|
||||||
|
//
|
||||||
|
// Has only had a few tests run, may have issues.
|
||||||
|
//
|
||||||
|
// More docs to come.
|
||||||
|
//
|
||||||
|
// No memory allocations; uses qsort() and assert() from stblib.
|
||||||
//
|
//
|
||||||
// This library currently uses the Skyline Bottom-Left algorithm.
|
// This library currently uses the Skyline Bottom-Left algorithm.
|
||||||
//
|
//
|
||||||
// Please note: better rectangle packers are welcome! Please
|
// Please note: better rectangle packers are welcome! Please
|
||||||
// implement them to the same API, but with a different init
|
// implement them to the same API, but with a different init
|
||||||
// function. Contact me for details of how to set up the
|
// function.
|
||||||
// heuristic enums and suchlike (as the code currently isn't
|
|
||||||
// designed to do that correctly internally).
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef STB_INCLUDE_STB_RECT_PACK_H
|
#ifndef STB_INCLUDE_STB_RECT_PACK_H
|
||||||
#define STB_INCLUDE_STB_RECT_PACK_H
|
#define STB_INCLUDE_STB_RECT_PACK_H
|
||||||
@ -37,7 +44,7 @@ typedef unsigned short stbrp_coord;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
|
STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
|
||||||
// Assign packing locations to rectangles. The rectangles are of type
|
// Assign packed locations to rectangles. The rectangles are of type
|
||||||
// 'stbrp_rect' defined below, stored in the array 'rects', and there
|
// 'stbrp_rect' defined below, stored in the array 'rects', and there
|
||||||
// are 'num_rects' many of them.
|
// are 'num_rects' many of them.
|
||||||
//
|
//
|
||||||
@ -139,6 +146,7 @@ STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
|
|||||||
switch (context->init_mode) {
|
switch (context->init_mode) {
|
||||||
case STBRP__INIT_skyline:
|
case STBRP__INIT_skyline:
|
||||||
assert(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
|
assert(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
|
||||||
|
context->heuristic = heuristic;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
@ -218,21 +226,26 @@ static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0
|
|||||||
min_y = 0;
|
min_y = 0;
|
||||||
waste_area = 0;
|
waste_area = 0;
|
||||||
visited_width = 0;
|
visited_width = 0;
|
||||||
while (node->x <= x1) {
|
while (node->x < x1) {
|
||||||
if (node->y > min_y) {
|
if (node->y > min_y) {
|
||||||
// raise min_y higher.
|
// raise min_y higher.
|
||||||
// we've accounted for all waste up to min_y,
|
// we've accounted for all waste up to min_y,
|
||||||
// but we'll now add more waste for everything we've visted
|
// but we'll now add more waste for everything we've visted
|
||||||
waste_area += visited_width * (node->y - min_y);
|
waste_area += visited_width * (node->y - min_y);
|
||||||
min_y = node->y;
|
min_y = node->y;
|
||||||
|
// the first time through, visited_width might be reduced
|
||||||
|
if (node->x < x0)
|
||||||
|
visited_width += node->next->x - x0;
|
||||||
|
else
|
||||||
|
visited_width += node->next->x - node->x;
|
||||||
} else {
|
} else {
|
||||||
// add waste area
|
// add waste area
|
||||||
int under_width = node->next->x - node->x;
|
int under_width = node->next->x - node->x;
|
||||||
if (under_width + visited_width > width)
|
if (under_width + visited_width > width)
|
||||||
under_width = width - visited_width;
|
under_width = width - visited_width;
|
||||||
waste_area += under_width * (min_y - node->y);
|
waste_area += under_width * (min_y - node->y);
|
||||||
|
visited_width += under_width;
|
||||||
}
|
}
|
||||||
visited_width += node->next->x - node->x; // adds too much the last time, but that's never used
|
|
||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,7 +272,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
|
|||||||
|
|
||||||
node = c->active_head;
|
node = c->active_head;
|
||||||
prev = &c->active_head;
|
prev = &c->active_head;
|
||||||
while (node->x + width < c->width) {
|
while (node->x + width <= c->width) {
|
||||||
int y,waste;
|
int y,waste;
|
||||||
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
|
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
|
||||||
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
|
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
|
||||||
@ -309,13 +322,13 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
|
|||||||
// find first node that's admissible
|
// find first node that's admissible
|
||||||
while (tail->x < width)
|
while (tail->x < width)
|
||||||
tail = tail->next;
|
tail = tail->next;
|
||||||
while (tail->x <= c->width) {
|
while (tail) {
|
||||||
int xpos = tail->x - width;
|
int xpos = tail->x - width;
|
||||||
int y,waste;
|
int y,waste;
|
||||||
assert(xpos >= 0);
|
assert(xpos >= 0);
|
||||||
// find the left position that matches this
|
// find the left position that matches this
|
||||||
while (node->next->x <= xpos) {
|
while (node->next->x <= xpos) {
|
||||||
prev = &node;
|
prev = &node->next;
|
||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
assert(node->next->x > xpos && node->x <= xpos);
|
assert(node->next->x > xpos && node->x <= xpos);
|
||||||
@ -376,7 +389,7 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
|
|||||||
|
|
||||||
// from here, traverse cur and free the nodes, until we get to one
|
// from here, traverse cur and free the nodes, until we get to one
|
||||||
// that shouldn't be freed
|
// that shouldn't be freed
|
||||||
while (cur->next->x <= res.x + width) {
|
while (cur->next && cur->next->x <= res.x + width) {
|
||||||
stbrp_node *next = cur->next;
|
stbrp_node *next = cur->next;
|
||||||
// move the current node to the free list
|
// move the current node to the free list
|
||||||
cur->next = context->free_head;
|
cur->next = context->free_head;
|
||||||
|
Loading…
Reference in New Issue
Block a user