From ee9ebe6c54d2f0790d8285907bbab0e2aa294785 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 1 Nov 2022 17:56:52 -0400 Subject: [PATCH] Improve LINKDRAW with multiple objects Multiple objects with MF2_LINKDRAW will get sorted between each other, instead of purely done with dispoffset. --- src/r_things.c | 60 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 9fbdf24aa..0defa44e2 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1817,6 +1817,11 @@ static void R_ProjectSprite(mobj_t *thing) ang = (viewangle >> ANGLETOFINESHIFT); sort_x = FixedMul(FixedMul(FixedMul(spritexscale, this_scale), sort_z), FINECOSINE(ang)); sort_y = FixedMul(FixedMul(FixedMul(spriteyscale, this_scale), sort_z), FINESINE(ang)); + + tr_x = (interp.x + sort_x) - viewx; + tr_y = (interp.y + sort_y) - viewy; + sort_z = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); + sortscale = FixedDiv(projectiony, sort_z); } if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) // toast 16/09/16 (SYMMETRY) @@ -1849,16 +1854,11 @@ static void R_ProjectSprite(mobj_t *thing) if (sortscale < linkscale) dispoffset *= -1; // if it's physically behind, make sure it's ordered behind (if dispoffset > 0) - sortscale = linkscale; // now make sure it's linked + //sortscale = linkscale; // now make sure it's linked + // No need to do that, linkdraw already excludes it from regular sorting. + cut |= SC_LINKDRAW; } - else if (splat) - { - tr_x = (interp.x + sort_x) - viewx; - tr_y = (interp.y + sort_y) - viewy; - sort_z = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); - sortscale = FixedDiv(projectiony, sort_z); - } // Calculate the splat's sortscale if (splat) @@ -2414,6 +2414,21 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) } } +static boolean R_SortVisSpriteFunc(vissprite_t *ds, fixed_t bestscale, INT32 bestdispoffset) +{ + if (ds->sortscale < bestscale) + { + return true; + } + // order visprites of same scale by dispoffset, smallest first + else if (ds->sortscale == bestscale && ds->dispoffset < bestdispoffset) + { + return true; + } + + return false; +} + // // R_SortVisSprites // @@ -2504,7 +2519,7 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e // reusing dsnext... dsnext = dsfirst->linkdraw; - if (!dsnext || ds->dispoffset < dsnext->dispoffset) + if (dsnext == NULL || R_SortVisSpriteFunc(ds, dsnext->sortscale, dsnext->dispoffset) == true) { ds->next = dsnext; dsfirst->linkdraw = ds; @@ -2512,8 +2527,13 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e else { for (; dsnext->next != NULL; dsnext = dsnext->next) - if (ds->dispoffset < dsnext->next->dispoffset) + { + if (R_SortVisSpriteFunc(ds, dsnext->next->sortscale, dsnext->next->dispoffset) == true) + { break; + } + } + ds->next = dsnext->next; dsnext->next = ds; } @@ -2532,18 +2552,12 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e I_Error("R_SortVisSprites: no link or discardal made for linkdraw!"); #endif - if (ds->sortscale < bestscale) + if (R_SortVisSpriteFunc(ds, bestscale, bestdispoffset) == true) { bestscale = ds->sortscale; bestdispoffset = ds->dispoffset; best = ds; } - // order visprites of same scale by dispoffset, smallest first - else if (ds->sortscale == bestscale && ds->dispoffset < bestdispoffset) - { - bestdispoffset = ds->dispoffset; - best = ds; - } } best->next->prev = best->prev; best->prev->next = best->next; @@ -3289,14 +3303,20 @@ static void R_DrawMaskedList (drawnode_t* head) vissprite_t *ds = r2->sprite->linkdraw; for (; - (ds != NULL && r2->sprite->dispoffset > ds->dispoffset); - ds = ds->next) + (ds != NULL && r2->sprite->dispoffset > ds->dispoffset); + ds = ds->next) + { R_DrawSprite(ds); + } R_DrawSprite(r2->sprite); - for (; ds != NULL; ds = ds->next) + for (; + ds != NULL; + ds = ds->next) + { R_DrawSprite(ds); + } } R_DoneWithNode(r2);