(svn r11105) -Codechange [FS#1223]: add some support for tuning of the bounding boxes for some special cases (like tunnels and bridges). Patch by frosch.

This commit is contained in:
rubidium 2007-09-14 21:54:57 +00:00
parent 6762862edc
commit b25c661ce6
2 changed files with 46 additions and 29 deletions

View File

@ -84,25 +84,30 @@ struct ParentSpriteToDraw {
SpriteID image; ///< sprite to draw SpriteID image; ///< sprite to draw
SpriteID pal; ///< palette to use SpriteID pal; ///< palette to use
int32 x; ///< screen X coordinate of sprite
int32 y; ///< screen Y coordinate of sprite
int32 left; ///< minimal screen X coordinate of sprite (= x + sprite->x_offs), reference point for child sprites int32 left; ///< minimal screen X coordinate of sprite (= x + sprite->x_offs), reference point for child sprites
int32 top; ///< minimal screen Y coordinate of sprite (= y + sprite->y_offs), reference point for child sprites int32 top; ///< minimal screen Y coordinate of sprite (= y + sprite->y_offs), reference point for child sprites
int32 right;
int32 bottom;
int32 xmin; ///< minimal world X coordinate of bounding box int32 xmin; ///< minimal world X coordinate of bounding box
int32 xmax; ///< maximal world X coordinate of bounding box int32 xmax; ///< maximal world X coordinate of bounding box
int32 ymin; ///< minimal world Y coordinate of bounding box int32 ymin; ///< minimal world Y coordinate of bounding box
int32 ymax; ///< maximal world Y coordinate of bounding box int32 ymax; ///< maximal world Y coordinate of bounding box
byte zmin; ///< minimal world Z coordinate of bounding box int zmin; ///< minimal world Z coordinate of bounding box
byte zmax; ///< maximal world Z coordinate of bounding box int zmax; ///< maximal world Z coordinate of bounding box
ChildScreenSpriteToDraw *child; ///< head of child list; ChildScreenSpriteToDraw *child; ///< head of child list;
bool comparaison_done; ///< Used during sprite sorting: true if sprite has been compared with all other sprites bool comparison_done; ///< Used during sprite sorting: true if sprite has been compared with all other sprites
}; };
/* Quick hack to know how much memory to reserve when allocating from the spritelist /* Quick hack to know how much memory to reserve when allocating from the spritelist
* to prevent a buffer overflow. */ * to prevent a buffer overflow. */
#define LARGEST_SPRITELIST_STRUCT ParentSpriteToDraw #define LARGEST_SPRITELIST_STRUCT ParentSpriteToDraw
assert_compile(sizeof(LARGEST_SPRITELIST_STRUCT) >= sizeof(StringSpriteToDraw));
assert_compile(sizeof(LARGEST_SPRITELIST_STRUCT) >= sizeof(TileSpriteToDraw));
assert_compile(sizeof(LARGEST_SPRITELIST_STRUCT) >= sizeof(ChildScreenSpriteToDraw));
assert_compile(sizeof(LARGEST_SPRITELIST_STRUCT) >= sizeof(ParentSpriteToDraw));
struct ViewportDrawer { struct ViewportDrawer {
DrawPixelInfo dpi; DrawPixelInfo dpi;
@ -482,18 +487,29 @@ static void AddCombinedSprite(SpriteID image, SpriteID pal, int x, int y, byte z
AddChildSpriteScreen(image, pal, pt.x - vd->parent_list[-1]->left, pt.y - vd->parent_list[-1]->top); AddChildSpriteScreen(image, pal, pt.x - vd->parent_list[-1]->left, pt.y - vd->parent_list[-1]->top);
} }
/** Draw a (transparent) sprite at given coordinates /** Draw a (transparent) sprite at given coordinates with a given bounding box.
* The bounding box extends from (x + bb_offset_x, y + bb_offset_y, z + bb_offset_z) to (x + w - 1, y + h - 1, z + dz - 1), both corners included.
*
* @note Bounding boxes are normally specified with bb_offset_x = bb_offset_y = bb_offset_z = 0. The extent of the bounding box in negative direction is
* defined by the sprite offset in the grf file.
* However if modifying the sprite offsets is not suitable (e.g. when using existing graphics), the bounding box can be tuned by bb_offset.
*
* @pre w > bb_offset_x, h > bb_offset_y, dz > bb_offset_z. Else w, h or dz are ignored.
*
* @param image the image to combine and draw, * @param image the image to combine and draw,
* @param pal the provided palette, * @param pal the provided palette,
* @param x position x of the sprite, * @param x position X (world) of the sprite,
* @param y position y of the sprite, * @param y position Y (world) of the sprite,
* @param w width of the sprite, * @param w bounding box extent towards positive X (world),
* @param h height of the sprite, * @param h bounding box extent towards positive Y (world),
* @param dz delta z, difference of elevation between sprite and parent sprite, * @param dz bounding box extent towards positive Z (world),
* @param z elevation of the sprite, * @param z position Z (world) of the sprite,
* @param transparent if true, switch the palette between the provided palette and the transparent palette * @param transparent if true, switch the palette between the provided palette and the transparent palette,
* @param bb_offset_x bounding box extent towards negative X (world),
* @param bb_offset_y bounding box extent towards negative Y (world),
* @param bb_offset_z bounding box extent towards negative Z (world)
*/ */
void AddSortableSpriteToDraw(SpriteID image, SpriteID pal, int x, int y, int w, int h, byte dz, byte z, bool transparent) void AddSortableSpriteToDraw(SpriteID image, SpriteID pal, int x, int y, int w, int h, int dz, int z, bool transparent, int bb_offset_x, int bb_offset_y, int bb_offset_z)
{ {
ViewportDrawer *vd = _cur_vd; ViewportDrawer *vd = _cur_vd;
ParentSpriteToDraw *ps; ParentSpriteToDraw *ps;
@ -533,11 +549,13 @@ void AddSortableSpriteToDraw(SpriteID image, SpriteID pal, int x, int y, int w,
} }
pt = RemapCoords(x, y, z); pt = RemapCoords(x, y, z);
ps->x = pt.x;
ps->y = pt.y;
spr = GetSprite(image & SPRITE_MASK); spr = GetSprite(image & SPRITE_MASK);
if ((ps->left = (pt.x += spr->x_offs)) >= vd->dpi.left + vd->dpi.width || if ((ps->left = (pt.x += spr->x_offs)) >= vd->dpi.left + vd->dpi.width ||
(ps->right = (pt.x + spr->width )) <= vd->dpi.left || ( (pt.x + spr->width )) <= vd->dpi.left ||
(ps->top = (pt.y += spr->y_offs)) >= vd->dpi.top + vd->dpi.height || (ps->top = (pt.y += spr->y_offs)) >= vd->dpi.top + vd->dpi.height ||
(ps->bottom = (pt.y + spr->height)) <= vd->dpi.top) { ( (pt.y + spr->height)) <= vd->dpi.top) {
return; return;
} }
@ -545,16 +563,16 @@ void AddSortableSpriteToDraw(SpriteID image, SpriteID pal, int x, int y, int w,
ps->image = image; ps->image = image;
ps->pal = pal; ps->pal = pal;
ps->xmin = x; ps->xmin = x + bb_offset_x;
ps->xmax = x + w - 1; ps->xmax = x + max(bb_offset_x, w - 1);
ps->ymin = y; ps->ymin = y + bb_offset_y;
ps->ymax = y + h - 1; ps->ymax = y + max(bb_offset_y, h - 1);
ps->zmin = z; ps->zmin = z + bb_offset_z;
ps->zmax = z + dz - 1; ps->zmax = z + max(bb_offset_z, dz - 1);
ps->comparaison_done = false; ps->comparison_done = false;
ps->child = NULL; ps->child = NULL;
vd->last_child = &ps->child; vd->last_child = &ps->child;
@ -1133,16 +1151,16 @@ static void ViewportSortParentSprites(ParentSpriteToDraw *psd[])
while (*psd != NULL) { while (*psd != NULL) {
ParentSpriteToDraw* ps = *psd; ParentSpriteToDraw* ps = *psd;
if (!ps->comparaison_done) { if (!ps->comparison_done) {
ParentSpriteToDraw** psd2 = psd; ParentSpriteToDraw** psd2 = psd;
ps->comparaison_done = true; ps->comparison_done = true;
while (*++psd2 != NULL) { while (*++psd2 != NULL) {
ParentSpriteToDraw* ps2 = *psd2; ParentSpriteToDraw* ps2 = *psd2;
ParentSpriteToDraw** psd3; ParentSpriteToDraw** psd3;
if (ps2->comparaison_done) continue; if (ps2->comparison_done) continue;
/* Decide which comparator to use, based on whether the bounding /* Decide which comparator to use, based on whether the bounding
* boxes overlap * boxes overlap
@ -1192,10 +1210,9 @@ static void ViewportDrawParentSprites(ParentSpriteToDraw *psd[])
{ {
for (; *psd != NULL; psd++) { for (; *psd != NULL; psd++) {
const ParentSpriteToDraw* ps = *psd; const ParentSpriteToDraw* ps = *psd;
Point pt = RemapCoords(ps->xmin, ps->ymin, ps->zmin);
const ChildScreenSpriteToDraw* cs; const ChildScreenSpriteToDraw* cs;
DrawSprite(ps->image, ps->pal, pt.x, pt.y); DrawSprite(ps->image, ps->pal, ps->x, ps->y);
for (cs = ps->child; cs != NULL; cs = cs->next) { for (cs = ps->child; cs != NULL; cs = cs->next) {
DrawSprite(cs->image, cs->pal, ps->left + cs->x, ps->top + cs->y); DrawSprite(cs->image, cs->pal, ps->left + cs->x, ps->top + cs->y);

View File

@ -48,7 +48,7 @@ void OffsetGroundSprite(int x, int y);
void DrawGroundSprite(SpriteID image, SpriteID pal); void DrawGroundSprite(SpriteID image, SpriteID pal);
void DrawGroundSpriteAt(SpriteID image, SpriteID pal, int32 x, int32 y, byte z); void DrawGroundSpriteAt(SpriteID image, SpriteID pal, int32 x, int32 y, byte z);
void AddSortableSpriteToDraw(SpriteID image, SpriteID pal, int x, int y, int w, int h, byte dz, byte z, bool transparent = false); void AddSortableSpriteToDraw(SpriteID image, SpriteID pal, int x, int y, int w, int h, int dz, int z, bool transparent = false, int bb_offset_x = 0, int bb_offset_y = 0, int bb_offset_z = 0);
void *AddStringToDraw(int x, int y, StringID string, uint64 params_1, uint64 params_2); void *AddStringToDraw(int x, int y, StringID string, uint64 params_1, uint64 params_2);
void AddChildSpriteScreen(SpriteID image, SpriteID pal, int x, int y); void AddChildSpriteScreen(SpriteID image, SpriteID pal, int x, int y);