Index: src/tree_cmd.cpp =================================================================== --- src/tree_cmd.cpp (revision 10160) +++ src/tree_cmd.cpp (working copy) @@ -366,7 +366,8 @@ s = _tree_layout_sprite[index]; } - StartSpriteCombine(); +/* combined trees cause problems with parent sprite ordering */ +// StartSpriteCombine(); if (!HASBIT(_transparent_opt, TO_TREES) || !_patches.invisible_trees) { TreeListEnt te[4]; @@ -411,7 +412,7 @@ } } - EndSpriteCombine(); +// EndSpriteCombine(); } Index: src/landscape.cpp =================================================================== --- src/landscape.cpp (revision 10160) +++ src/landscape.cpp (working copy) @@ -253,7 +253,7 @@ if (f < 15) { /* leveled foundation * Use the original slope sprites if NW and NE borders should be visible */ - if (sprite_base == SPR_SLOPES_BASE - 15) sprite_base = SPR_FOUNDATION_BASE; + if (sprite_base == SPR_SLOPES_BASE - 15) sprite_base = SPR_FOUNDATION_BASE; AddSortableSpriteToDraw(sprite_base + f, PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z); ti->z += TILE_HEIGHT; Index: src/viewport.cpp =================================================================== --- src/viewport.cpp (revision 10160) +++ src/viewport.cpp (working copy) @@ -89,8 +89,8 @@ int32 ymin; int32 xmax; int32 ymax; + int32 sort; /* cached guessed order */ ChildScreenSpriteToDraw *child; - byte unk16; byte zmin; byte zmax; }; @@ -486,6 +486,14 @@ assert((image & SPRITE_MASK) < MAX_SPRITES); + /* dz == 0 is problematic for ViewportSortParentSprites(), + * sprite whould be "above itself" or "above other sprite with dz == 0" + * - those sprites would be above each other, likely causing incorrect rendering + */ + + if ( dz == 0 ) dz = 1; /* TODO: helipads have dz == 0 ... because of shadow? */ + + if (vd->combine_sprites == 2) { AddCombinedSprite(image, pal, x, y, z); return; @@ -532,7 +541,14 @@ ps->zmin = z; ps->zmax = z + dz - 1; - ps->unk16 = 0; + /* Use X+Y as the sorting order, so sprites closer to the bottom of + * the screen are drawn in front. + * Here X,Y are the coordinates of the "center of bottom" of the sprite, + * i.e. X=(left+right)/2, etc. + * However, since we only care about order, don't actually divide / 2 + */ + ps->sort =(ps->xmin + ps->xmax) + (ps->ymin + ps->ymax); /* guessed order */ + ps->child = NULL; vd->last_child = &ps->child; @@ -1104,61 +1120,41 @@ static void ViewportSortParentSprites(ParentSpriteToDraw *psd[]) { - while (*psd != NULL) { - ParentSpriteToDraw* ps = *psd; + uint num=0; /* number of parent sprites */ + for ( ; psd[num] != NULL ; num++ ); - if (!(ps->unk16 & 1)) { - ParentSpriteToDraw** psd2 = psd; + for ( uint i = 0 ; i < num ; i++ ) { + uint jmin = i; /* index of the best match */ + uint ct = 0; /* counter of steps */ + ParentSpriteToDraw* ps = psd[i]; - ps->unk16 |= 1; + rest: + for ( uint k = i ; k < num ; k++ ) { + ParentSpriteToDraw* ps2 = psd[k]; + if ( ps == ps2 ) continue; - while (*++psd2 != NULL) { - ParentSpriteToDraw* ps2 = *psd2; - ParentSpriteToDraw** psd3; - - if (ps2->unk16 & 1) continue; - - /* Decide which comparator to use, based on whether the bounding - * boxes overlap - */ - if (ps->xmax > ps2->xmin && ps->xmin < ps2->xmax && // overlap in X? - ps->ymax > ps2->ymin && ps->ymin < ps2->ymax && // overlap in Y? - ps->zmax > ps2->zmin && ps->zmin < ps2->zmax) { // overlap in Z? - /* Use X+Y+Z as the sorting order, so sprites closer to the bottom of - * the screen and with higher Z elevation, are drawn in front. - * Here X,Y,Z are the coordinates of the "center of mass" of the sprite, - * i.e. X=(left+right)/2, etc. - * However, since we only care about order, don't actually divide / 2 - */ - if (ps->xmin + ps->xmax + ps->ymin + ps->ymax + ps->zmin + ps->zmax <= - ps2->xmin + ps2->xmax + ps2->ymin + ps2->ymax + ps2->zmin + ps2->zmax) { - continue; - } - } else { - if (ps->xmax < ps2->xmin || - ps->ymax < ps2->ymin || - ps->zmax < ps2->zmin || ( - ps->xmin < ps2->xmax && - ps->ymin < ps2->ymax && - ps->zmin < ps2->zmax - )) { - continue; - } + /* do sprites overlay ? */ + if ( ps->left <= ps2->right && ps->right >= ps2->left && ps->bottom >= ps2->top && ps->top <= ps2->bottom ) { + /* should be ps drawn after ps2 ? */ + /* ps whole above ps2 || ( ps2 not whole above ps && guess > guess2 ) */ + if (ps->zmin > ps2->zmax || ( !(ps->zmax < ps2->zmin ) && ( ps->sort > ps2->sort ) ) ) { + if ( ++ct == num-i ) break; /* too many iterations -> inside a loop -> stop now */ + ps = ps2; /* restart searching from actual sprite */ + jmin = k; + goto rest; } - - /* Swap the two sprites ps and ps2 using bubble-sort algorithm. */ - psd3 = psd; - do { - ParentSpriteToDraw* temp = *psd3; - *psd3 = ps2; - ps2 = temp; - - psd3++; - } while (psd3 <= psd2); } - } else { - psd++; } + + if ( jmin != i ) { + /* 'bubble' value to its place - more correct, can even be faster (in effect) that swapping */ + ParentSpriteToDraw* swap = psd[jmin]; + for ( uint j = jmin ; j > i ; j-- ) psd[j] = psd[j-1]; + psd[i] = swap; +/* ParentSpriteToDraw* swap = psd[i]; + psd[i] = psd[jmin]; + psd[jmin] = swap;*/ + } } }