From dca1a05a7f70b536fb4b7f9e759b82f419f54fe7 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 26 May 2019 03:41:18 -0400 Subject: [PATCH 1/8] Gradient skincolors for MD2 blend textures --- src/hardware/hw_md2.c | 167 +++++++++++++++++++++++------------------- src/k_kart.c | 2 +- 2 files changed, 93 insertions(+), 76 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index d217f4094..cc69fad02 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -653,13 +653,12 @@ spritemd2found: // 0.2126 to red // 0.7152 to green // 0.0722 to blue -// (See this same define in k_kart.c!) +// (See this same define in hw_md2.c!) #define SETBRIGHTNESS(brightness,r,g,b) \ - brightness = (UINT8)(((1063*((UINT16)r)/5000) + (3576*((UINT16)g)/5000) + (361*((UINT16)b)/5000)) / 3) + brightness = (UINT8)(((1063*(UINT16)(r))/5000) + ((3576*(UINT16)(g))/5000) + ((361*(UINT16)(b))/5000)) static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolors_t color) { - UINT8 i; UINT16 w = gpatch->width, h = gpatch->height; UINT32 size = w*h; RGBA_t *image, *blendimage, *cur, blendcolor; @@ -684,102 +683,120 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, image = gpatch->mipmap.grInfo.data; blendimage = blendgpatch->mipmap.grInfo.data; + blendcolor = V_GetColor(0); // initialize - // Average all of the translation's colors + while (size--) { - const UINT8 div = 6; - const UINT8 start = 4; - UINT32 r, g, b; + UINT16 brightness; - blendcolor = V_GetColor(colortranslations[color][start]); - r = (UINT32)(blendcolor.s.red*blendcolor.s.red); - g = (UINT32)(blendcolor.s.green*blendcolor.s.green); - b = (UINT32)(blendcolor.s.blue*blendcolor.s.blue); - - for (i = 1; i < div; i++) - { - RGBA_t nextcolor = V_GetColor(colortranslations[color][start+i]); - r += (UINT32)(nextcolor.s.red*nextcolor.s.red); - g += (UINT32)(nextcolor.s.green*nextcolor.s.green); - b += (UINT32)(nextcolor.s.blue*nextcolor.s.blue); - } - - blendcolor.s.red = (UINT8)(FixedSqrt((r/div)<>FRACBITS); - blendcolor.s.green = (UINT8)(FixedSqrt((g/div)<>FRACBITS); - blendcolor.s.blue = (UINT8)(FixedSqrt((b/div)<>FRACBITS); - } - - // rainbow support, could theoretically support boss ones too - if (skinnum == TC_RAINBOW) - { - while (size--) + // Don't bother with blending the pixel if the alpha of the blend pixel is 0 + if (skinnum == TC_RAINBOW) { if (image->s.alpha == 0 && blendimage->s.alpha == 0) { - // Don't bother with blending the pixel if the alpha of the blend pixel is 0 cur->rgba = image->rgba; + cur++; image++; blendimage++; + continue; } else { - UINT32 tempcolor; - UINT16 imagebright, blendbright, finalbright, colorbright; + UINT16 imagebright, blendbright; SETBRIGHTNESS(imagebright,image->s.red,image->s.green,image->s.blue); SETBRIGHTNESS(blendbright,blendimage->s.red,blendimage->s.green,blendimage->s.blue); // slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway - finalbright = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255; - SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue); - - tempcolor = (finalbright*blendcolor.s.red)/colorbright; - tempcolor = min(255, tempcolor); - cur->s.red = (UINT8)tempcolor; - tempcolor = (finalbright*blendcolor.s.green)/colorbright; - tempcolor = min(255, tempcolor); - cur->s.green = (UINT8)tempcolor; - tempcolor = (finalbright*blendcolor.s.blue)/colorbright; - tempcolor = min(255, tempcolor); - cur->s.blue = (UINT8)tempcolor; - cur->s.alpha = image->s.alpha; + brightness = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255; } - - cur++; image++; blendimage++; } - } - else - { - while (size--) + else { if (blendimage->s.alpha == 0) { - // Don't bother with blending the pixel if the alpha of the blend pixel is 0 cur->rgba = image->rgba; + cur++; image++; blendimage++; + continue; } else { - INT32 tempcolor; - INT16 tempmult, tempalpha; - tempalpha = -(abs(blendimage->s.red-127)-127)*2; - if (tempalpha > 255) - tempalpha = 255; - else if (tempalpha < 0) - tempalpha = 0; - - tempmult = (blendimage->s.red-127)*2; - if (tempmult > 255) - tempmult = 255; - else if (tempmult < 0) - tempmult = 0; - - tempcolor = (image->s.red*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.red)/255)) * blendimage->s.alpha)/255; - cur->s.red = (UINT8)tempcolor; - tempcolor = (image->s.green*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.green)/255)) * blendimage->s.alpha)/255; - cur->s.green = (UINT8)tempcolor; - tempcolor = (image->s.blue*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.blue)/255)) * blendimage->s.alpha)/255; - cur->s.blue = (UINT8)tempcolor; - cur->s.alpha = image->s.alpha; + SETBRIGHTNESS(brightness,blendimage->s.red,blendimage->s.green,blendimage->s.blue); } - - cur++; image++; blendimage++; } + + // Calculate a sort of "gradient" for the skincolor + // (Me splitting this into a function didn't work, so I had to ruin this entire function's groove...) + { + RGBA_t nextcolor; + UINT8 firsti, secondi, mul; + UINT32 r, g, b; + + firsti = ((UINT8)(255-brightness) / 16); + mul = ((UINT8)(255-brightness) % 16); + + blendcolor = V_GetColor(colortranslations[color][firsti]); + + if (mul > 0) // If it's 0, then we only need the first color. + { + secondi = firsti+1; + + if (secondi == 16) // blend to black + nextcolor = V_GetColor(31); + else + nextcolor = V_GetColor(colortranslations[color][secondi]); + + // Find difference between points + r = (UINT32)(nextcolor.s.red - blendcolor.s.red); + g = (UINT32)(nextcolor.s.green - blendcolor.s.green); + b = (UINT32)(nextcolor.s.blue - blendcolor.s.blue); + + // Find the gradient of the two points + r = ((mul * r) / 16); + g = ((mul * g) / 16); + b = ((mul * b) / 16); + + // Add gradient value to color + blendcolor.s.red += r; + blendcolor.s.green += g; + blendcolor.s.blue += b; + } + } + + if (skinnum == TC_RAINBOW) + { + // Directly set blendcolor + cur->s.red = blendcolor.s.red; + cur->s.green = blendcolor.s.green; + cur->s.blue = blendcolor.s.blue; + cur->s.alpha = image->s.alpha; + } + else + { + // Color strength depends on image alpha + INT32 tempcolor; + INT16 tempmult, tempalpha; + + tempalpha = -(abs(blendimage->s.red-127)-127)*2; + if (tempalpha > 255) + tempalpha = 255; + else if (tempalpha < 0) + tempalpha = 0; + + tempmult = (blendimage->s.red-127)*2; + if (tempmult > 255) + tempmult = 255; + else if (tempmult < 0) + tempmult = 0; + + tempcolor = (image->s.red*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.red)/255)) * blendimage->s.alpha)/255; + cur->s.red = (UINT8)tempcolor; + + tempcolor = (image->s.green*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.green)/255)) * blendimage->s.alpha)/255; + cur->s.green = (UINT8)tempcolor; + + tempcolor = (image->s.blue*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.blue)/255)) * blendimage->s.alpha)/255; + cur->s.blue = (UINT8)tempcolor; + cur->s.alpha = image->s.alpha; + } + + cur++; image++; blendimage++; } return; diff --git a/src/k_kart.c b/src/k_kart.c index 659c499db..5ec49b444 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -410,7 +410,7 @@ UINT8 colortranslations[MAXTRANSLATIONS][16] = { // 0.0722 to blue // (See this same define in hw_md2.c!) #define SETBRIGHTNESS(brightness,r,g,b) \ - brightness = (UINT8)(((1063*((UINT16)r)/5000) + (3576*((UINT16)g)/5000) + (361*((UINT16)b)/5000)) / 3) + brightness = (UINT8)(((1063*(UINT16)(r))/5000) + ((3576*(UINT16)(g))/5000) + ((361*(UINT16)(b))/5000)) /** \brief Generates the rainbow colourmaps that are used when a player has the invincibility power From 179bb2bd8b1fe801c1817734f3451657162f96d8 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 26 May 2019 06:22:14 -0400 Subject: [PATCH 2/8] Update colorize blending Didn't notice for a moment that it was back to 2.0-style rainbow blending -- this is horrible but it keeps the brightness of the textures in-tact --- src/hardware/hw_md2.c | 89 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 8 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index cc69fad02..36d2a606f 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -728,15 +728,78 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, UINT8 firsti, secondi, mul; UINT32 r, g, b; - firsti = ((UINT8)(255-brightness) / 16); - mul = ((UINT8)(255-brightness) % 16); + // Rainbow needs to find the closest match to the textures themselves, instead of matching brightnesses to other colors. + // Ensue horrible mess. + if (skinnum == TC_RAINBOW) + { + UINT16 brightdif = 256; + UINT8 colorbrightnesses[16]; + INT32 compare, m, d; + UINT8 i; + + // Ignore pure white & pitch black + if (brightness > 246 || brightness < 7) + { + cur->rgba = image->rgba; + cur++; image++; blendimage++; + continue; + } + + firsti = 0; + mul = 0; + + for (i = 0; i < 16; i++) + { + RGBA_t tempc = V_GetColor(colortranslations[color][i]); + SETBRIGHTNESS(colorbrightnesses[i], tempc.s.red, tempc.s.green, tempc.s.blue); // store brightnesses for comparison + } + + for (i = 0; i < 16; i++) + { + if (brightness > colorbrightnesses[i]) // don't allow greater matches (because calculating a makeshift gradient for this is already a huge mess as is) + continue; + compare = abs((INT16)(colorbrightnesses[i]) - (INT16)(brightness)); + if (compare < brightdif) + { + brightdif = (UINT16)compare; + firsti = i; // best matching color that's equal brightness or darker + } + } + + secondi = firsti+1; // next color in line + if (secondi == 16) + { + m = (INT16)brightness; // - 0; + d = (INT16)colorbrightnesses[firsti]; // - 0; + } + else + { + m = (INT16)brightness - (INT16)colorbrightnesses[secondi]; + d = (INT16)colorbrightnesses[firsti] - (INT16)colorbrightnesses[secondi]; + } + + if (m >= d) + m = d-1; + + // calculate the "gradient" multiplier based on how close this color is to the one next in line + if (m <= 0 || d <= 0) + mul = 0; + else + mul = 15 - ((m * 16) / d); + } + else + { + // Thankfully, it's normally way more simple. + // Just convert brightness to a skincolor value, use remainder to find the gradient multipler + firsti = ((UINT8)(255-brightness) / 16); + secondi = firsti+1; + mul = ((UINT8)(255-brightness) % 16); + } blendcolor = V_GetColor(colortranslations[color][firsti]); if (mul > 0) // If it's 0, then we only need the first color. { - secondi = firsti+1; - if (secondi == 16) // blend to black nextcolor = V_GetColor(31); else @@ -761,10 +824,20 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, if (skinnum == TC_RAINBOW) { - // Directly set blendcolor - cur->s.red = blendcolor.s.red; - cur->s.green = blendcolor.s.green; - cur->s.blue = blendcolor.s.blue; + UINT32 tempcolor; + UINT16 colorbright = 127; // an arbitrary value now, since blendcolor is always changing + + tempcolor = (brightness * blendcolor.s.red) / colorbright; + tempcolor = min(255, tempcolor); + cur->s.red = (UINT8)tempcolor; + + tempcolor = (brightness * blendcolor.s.green) / colorbright; + tempcolor = min(255, tempcolor); + cur->s.green = (UINT8)tempcolor; + + tempcolor = (brightness * blendcolor.s.blue) / colorbright; + tempcolor = min(255, tempcolor); + cur->s.blue = (UINT8)tempcolor; cur->s.alpha = image->s.alpha; } else From ee60e6d76c326a22e57418708dacf0e49203a963 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 26 May 2019 07:44:40 -0400 Subject: [PATCH 3/8] Minor touchup to colorization code --- src/hardware/hw_md2.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 36d2a606f..02594eb70 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -738,7 +738,7 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, UINT8 i; // Ignore pure white & pitch black - if (brightness > 246 || brightness < 7) + if (brightness > 253 || brightness < 2) { cur->rgba = image->rgba; cur++; image++; blendimage++; @@ -825,7 +825,11 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, if (skinnum == TC_RAINBOW) { UINT32 tempcolor; - UINT16 colorbright = 127; // an arbitrary value now, since blendcolor is always changing + UINT16 colorbright; + + SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue); + if (colorbright == 0) + colorbright = 1; // no dividing by 0 please tempcolor = (brightness * blendcolor.s.red) / colorbright; tempcolor = min(255, tempcolor); From e1d73d0e3502bf7bb44f428b82b1c8bb689375ae Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 26 May 2019 15:20:16 -0400 Subject: [PATCH 4/8] Tiny optimization --- src/hardware/hw_md2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 02594eb70..561daf058 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -798,7 +798,8 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, blendcolor = V_GetColor(colortranslations[color][firsti]); - if (mul > 0) // If it's 0, then we only need the first color. + if (mul > 0 // If it's 0, then we only need the first color. + && colortranslations[color][firsti] != colortranslations[color][secondi]) // Some colors have duplicate colors in a row, so let's just save the process { if (secondi == 16) // blend to black nextcolor = V_GetColor(31); From c6a0a41d1a614a9ece8ae38d7699abe186a4cfa8 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 28 May 2019 17:21:22 -0400 Subject: [PATCH 5/8] Model tilts - Add modeltilt variable, for more manual control of the model tilting. By default this just copies standingslope, but doesn't get cleared in the air. - Shadows & trailing bananas now tilt to match the ground they are on. - Rocket Sneakers & afterimages now tilt to match the player's current orientation. --- src/hardware/hw_md2.c | 8 +-- src/k_kart.c | 83 +++++++++++++++++++++++++++ src/p_map.c | 12 +++- src/p_mobj.c | 129 +++++++++++++++++++++++++++++++++++++----- src/p_mobj.h | 3 + src/p_saveg.c | 5 ++ src/p_slopes.c | 6 ++ src/p_user.c | 6 +- 8 files changed, 233 insertions(+), 19 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 561daf058..b610d410c 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1186,11 +1186,11 @@ void HWR_DrawMD2(gr_vissprite_t *spr) #ifdef USE_FTRANSFORM_ANGLEZ // Slope rotation from Kart p.anglez = 0.0f; - if (spr->mobj->standingslope) + if (spr->mobj->modeltilt) { - fixed_t tempz = spr->mobj->standingslope->normal.z; - fixed_t tempy = spr->mobj->standingslope->normal.y; - fixed_t tempx = spr->mobj->standingslope->normal.x; + fixed_t tempz = spr->mobj->modeltilt->normal.z; + fixed_t tempy = spr->mobj->modeltilt->normal.y; + fixed_t tempx = spr->mobj->modeltilt->normal.x; fixed_t tempangle = AngleFixed(R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx)); p.anglez = FIXED_TO_FLOAT(tempangle); tempangle = -AngleFixed(R_PointToAngle2(0, 0, tempz, tempy)); diff --git a/src/k_kart.c b/src/k_kart.c index 5ec49b444..12c4f14e0 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4093,6 +4093,86 @@ static void K_MoveHeldObjects(player_t *player) if (R_PointToDist2(cur->x, cur->y, targx, targy) > 768*FRACUNIT) P_TeleportMove(cur, targx, targy, cur->z); +#ifdef ESLOPE + // We gotta do ALL of this... just so that bananas can tilt in OGL :V + if (P_IsObjectOnGround(cur)) + { + pslope_t *slope = NULL; + sector_t *sec = R_PointInSubsector(cur->x, cur->y)->sector; + boolean flip = (cur->eflags & MFE_VERTICALFLIP); + + if (flip) + { + if (sec->c_slope) + { + slope = sec->c_slope; + targz = P_GetZAt(sec->c_slope, cur->x, cur->y); + } + else + targz = sec->ceilingheight; + } + else + { + if (sec->f_slope) + { + slope = sec->f_slope; + targz = P_GetZAt(sec->f_slope, cur->x, cur->y); + } + else + targz = sec->floorheight; + } + + // Check FOFs for a better suited slope + if (sec->ffloors) + { + ffloor_t *rover; + + for (rover = sec->ffloors; rover; rover = rover->next) + { + fixed_t surface; + + if (!(rover->flags & FF_EXISTS)) + continue; + + if (!((rover->flags & FF_BLOCKOTHERS) || (rover->flags & FF_QUICKSAND)) || (rover->flags & FF_SWIMMABLE)) + continue; + + if (flip) + { + surface = *rover->bottomheight; + if (*rover->b_slope) + surface = P_GetZAt(*rover->b_slope, cur->x, cur->y); + + if (surface < targz && surface > (cur->z + cur->height)) + { + targz = surface; + if (*rover->b_slope) + slope = *rover->b_slope; + } + } + else + { + surface = *rover->topheight; + if (*rover->t_slope) + surface = P_GetZAt(*rover->t_slope, cur->x, cur->y); + + if (surface > targz && surface < cur->z) + { + targz = surface; + if (*rover->t_slope) + slope = *rover->t_slope; + } + } + } + } + + cur->standingslope = slope; +#ifdef HWRENDER + cur->modeltilt = cur->standingslope; +#endif + } +#endif + cur = cur->hnext; } } @@ -4182,6 +4262,9 @@ static void K_MoveHeldObjects(player_t *player) P_TeleportMove(cur, targx, targy, targz); K_FlipFromObject(cur, player->mo); // Update graviflip in real time thanks. +#ifdef HWRENDER + cur->modeltilt = player->mo->modeltilt; +#endif num = (num+1) % 2; cur = cur->hnext; } diff --git a/src/p_map.c b/src/p_map.c index 2c766349d..e7041afea 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2881,14 +2881,24 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) P_HandleSlopeLanding(thing, tmfloorslope); if (thing->momz <= 0) + { thing->standingslope = tmfloorslope; +#ifdef HWRENDER + thing->modeltilt = thing->standingslope; +#endif + } } else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) { if (!startingonground && tmceilingslope) P_HandleSlopeLanding(thing, tmceilingslope); if (thing->momz >= 0) + { thing->standingslope = tmceilingslope; +#ifdef HWRENDER + thing->modeltilt = thing->standingslope; +#endif + } } } else // don't set standingslope if you're not going to clip against it @@ -4691,7 +4701,7 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) if (!(rover->flags & FF_EXISTS)) continue; - if ((!(rover->flags & FF_SOLID || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE))) + if (!((rover->flags & FF_SOLID) || (rover->flags & FF_QUICKSAND)) || (rover->flags & FF_SWIMMABLE)) continue; topheight = *rover->topheight; diff --git a/src/p_mobj.c b/src/p_mobj.c index 1d0224590..dda3d045b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1816,6 +1816,9 @@ void P_XYMovement(mobj_t *mo) // Now compare the Zs of the different quantizations if (oldangle-newangle > ANG30 && oldangle-newangle < ANGLE_180) { // Allow for a bit of sticking - this value can be adjusted later mo->standingslope = oldslope; +#ifdef HWRENDER + mo->modeltilt = mo->standingslope; +#endif P_SlopeLaunch(mo); //CONS_Printf("launched off of slope - "); @@ -2389,6 +2392,9 @@ static boolean P_ZMovement(mobj_t *mo) if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM)) { mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope; +#ifdef HWRENDER + mo->modeltilt = mo->standingslope; +#endif P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope); } #endif @@ -6173,7 +6179,12 @@ void P_RunShadows(void) for (mobj = shadowcap; mobj; mobj = next) { - fixed_t floorz; + boolean flip; + fixed_t newz; + sector_t *sec; +#ifdef ESLOPE + pslope_t *slope = NULL; +#endif next = mobj->hnext; P_SetTarget(&mobj->hnext, NULL); @@ -6184,16 +6195,106 @@ void P_RunShadows(void) continue; // shouldn't you already be dead? } - if (mobj->target->player) - floorz = mobj->target->floorz; - else // FOR SOME REASON, plain floorz is not reliable for normal objects, only players?! - floorz = P_FloorzAtPos(mobj->target->x, mobj->target->y, mobj->target->z, mobj->target->height); - K_MatchGenericExtraFlags(mobj, mobj->target); + flip = (mobj->eflags & MFE_VERTICALFLIP); - if (((mobj->target->eflags & MFE_VERTICALFLIP) && mobj->target->z+mobj->target->height > mobj->target->ceilingz) - || (!(mobj->target->eflags & MFE_VERTICALFLIP) && mobj->target->z < floorz)) - mobj->flags2 |= MF2_DONTDRAW; + sec = R_PointInSubsector(mobj->target->x, mobj->target->y)->sector; + + if (flip) + { +#ifdef ESLOPE + if (sec->c_slope) + { + slope = sec->c_slope; + newz = P_GetZAt(sec->c_slope, mobj->target->x, mobj->target->y); + } + else +#endif + newz = sec->ceilingheight; + } + else + { +#ifdef ESLOPE + if (sec->f_slope) + { + slope = sec->f_slope; + newz = P_GetZAt(sec->f_slope, mobj->target->x, mobj->target->y); + } + else +#endif + newz = sec->floorheight; + } + + // Check FOFs for a better suited slope + if (sec->ffloors) + { + ffloor_t *rover; + + for (rover = sec->ffloors; rover; rover = rover->next) + { + fixed_t surface; + + if (!(rover->flags & FF_EXISTS)) + continue; + + if ((!(((rover->flags & FF_BLOCKPLAYER && mobj->target->player) + || (rover->flags & FF_BLOCKOTHERS && !mobj->target->player)) + || (rover->flags & FF_QUICKSAND)) + || (rover->flags & FF_SWIMMABLE))) + continue; + + if (flip) + { + surface = *rover->bottomheight; +#ifdef ESLOPE + if (*rover->b_slope) + surface = P_GetZAt(*rover->b_slope, mobj->target->x, mobj->target->y); +#endif + + if (surface < newz && surface > (mobj->target->z + mobj->target->height)) + { + newz = surface; +#ifdef ESLOPE + if (*rover->b_slope) + slope = *rover->b_slope; +#endif + } + } + else + { + surface = *rover->topheight; +#ifdef ESLOPE + if (*rover->t_slope) + surface = P_GetZAt(*rover->t_slope, mobj->target->x, mobj->target->y); +#endif + + if (surface > newz && surface < mobj->target->z) + { + newz = surface; +#ifdef ESLOPE + if (*rover->t_slope) + slope = *rover->t_slope; +#endif + } + } + } + } + + mobj->standingslope = slope; +#ifdef HWRENDER + mobj->modeltilt = mobj->standingslope; +#endif + + if (flip) + { + if ((mobj->target->z + mobj->target->height) > newz) + mobj->flags2 |= MF2_DONTDRAW; + } + else + { + if (mobj->target->z < newz) + mobj->flags2 |= MF2_DONTDRAW; + } // First scale to the same radius P_SetScale(mobj, FixedDiv(mobj->target->radius, mobj->info->radius)); @@ -6205,13 +6306,12 @@ void P_RunShadows(void) P_TeleportMove(mobj, dest->x, dest->y, mobj->target->z); - if (((mobj->eflags & MFE_VERTICALFLIP) && (mobj->ceilingz > mobj->z+mobj->height)) - || (!(mobj->eflags & MFE_VERTICALFLIP) && (floorz < mobj->z))) + if ((flip && newz > (mobj->z + mobj->height)) || (!flip && newz < mobj->z)) { INT32 i; fixed_t prevz; - mobj->z = (mobj->eflags & MFE_VERTICALFLIP ? mobj->ceilingz : floorz); + mobj->z = newz; for (i = 0; i < MAXFFLOORS; i++) { @@ -6223,7 +6323,7 @@ void P_RunShadows(void) // Check new position to see if you should still be on that ledge P_TeleportMove(mobj, dest->x, dest->y, mobj->z); - mobj->z = (mobj->eflags & MFE_VERTICALFLIP ? mobj->ceilingz : floorz); + mobj->z = newz; if (mobj->z == prevz) break; @@ -8132,6 +8232,9 @@ void P_MobjThinker(mobj_t *mobj) P_TeleportMove(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->z); P_SetScale(mobj, mobj->target->scale); +#ifdef HWRENDER + mobj->modeltilt = mobj->target->modeltilt; +#endif { player_t *p = NULL; diff --git a/src/p_mobj.h b/src/p_mobj.h index dfc8fc738..aec2ed951 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -370,6 +370,9 @@ typedef struct mobj_s #ifdef ESLOPE struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) +#ifdef HWRENDER + struct pslope_s *modeltilt; // Slope used for model tilting. Also is not synched, this is totally visual. +#endif #endif boolean colorized; // Whether the mobj uses the rainbow colormap diff --git a/src/p_saveg.c b/src/p_saveg.c index 7d2e9a307..a3b80633a 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2144,7 +2144,12 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p); #ifdef ESLOPE if (diff2 & MD2_SLOPE) + { mobj->standingslope = P_SlopeById(READUINT16(save_p)); +#ifdef HWRENDER + mobj->modeltilt = mobj->standingslope; +#endif + } #endif if (diff2 & MD2_COLORIZED) mobj->colorized = READUINT8(save_p); diff --git a/src/p_slopes.c b/src/p_slopes.c index 76af7bfde..47e624da9 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -827,6 +827,9 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) if (P_MobjFlip(thing)*(thing->momz) < 0) { // falling, land on slope thing->momz = -P_MobjFlip(thing); thing->standingslope = slope; +#ifdef HWRENDER + thing->modeltilt = thing->standingslope; +#endif } return; } @@ -843,6 +846,9 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) thing->momz = -P_MobjFlip(thing); thing->standingslope = slope; +#ifdef HWRENDER + thing->modeltilt = thing->standingslope; +#endif } } diff --git a/src/p_user.c b/src/p_user.c index 61d8f36f3..6802a9120 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1675,12 +1675,16 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->frame |= tr_trans50<fuse = ghost->info->damage; ghost->skin = mobj->skin; + ghost->standingslope = mobj->standingslope; +#ifdef HWRENDER + ghost->modeltilt = mobj->modeltilt; +#endif if (mobj->flags2 & MF2_OBJECTFLIP) ghost->flags |= MF2_OBJECTFLIP; if (!(mobj->flags & MF_DONTENCOREMAP)) - mobj->flags &= ~MF_DONTENCOREMAP; + ghost->flags &= ~MF_DONTENCOREMAP; return ghost; } From f3f0b5eddaf97e1621d84f3285bac297e5e31358 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 30 May 2019 03:07:31 -0400 Subject: [PATCH 6/8] Fix FOF shadows again --- src/p_mobj.c | 69 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 17 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index a58ff3387..67f540fde 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6264,7 +6264,8 @@ void P_RunShadows(void) for (rover = sec->ffloors; rover; rover = rover->next) { - fixed_t surface; + fixed_t top, bottom; + fixed_t d1, d2; if (!(rover->flags & FF_EXISTS)) continue; @@ -6275,17 +6276,41 @@ void P_RunShadows(void) || (rover->flags & FF_SWIMMABLE))) continue; +#ifdef ESLOPE + if (*rover->t_slope) + top = P_GetZAt(*rover->t_slope, mobj->target->x, mobj->target->y); + else +#endif + top = *rover->topheight; + +#ifdef ESLOPE + if (*rover->b_slope) + bottom = P_GetZAt(*rover->b_slope, mobj->target->x, mobj->target->y); + else +#endif + bottom = *rover->bottomheight; + if (flip) { - surface = *rover->bottomheight; -#ifdef ESLOPE - if (*rover->b_slope) - surface = P_GetZAt(*rover->b_slope, mobj->target->x, mobj->target->y); -#endif - - if (surface < newz && surface > (mobj->target->z + mobj->target->height)) + if (rover->flags & FF_QUICKSAND) { - newz = surface; + if (mobj->target->z < top && (mobj->target->z + mobj->target->height) > bottom) + { + if (newz > (mobj->target->z + mobj->target->height)) + { + newz = (mobj->target->z + mobj->target->height); + slope = NULL; + } + } + continue; + } + + d1 = (mobj->target->z + mobj->target->height) - (top + ((bottom - top)/2)); + d2 = mobj->target->z - (top + ((bottom - top)/2)); + + if (bottom < newz && abs(d1) < abs(d2)) + { + newz = bottom; #ifdef ESLOPE if (*rover->b_slope) slope = *rover->b_slope; @@ -6294,15 +6319,25 @@ void P_RunShadows(void) } else { - surface = *rover->topheight; -#ifdef ESLOPE - if (*rover->t_slope) - surface = P_GetZAt(*rover->t_slope, mobj->target->x, mobj->target->y); -#endif - - if (surface > newz && surface < mobj->target->z) + if (rover->flags & FF_QUICKSAND) { - newz = surface; + if (mobj->target->z < top && (mobj->target->z + mobj->target->height) > bottom) + { + if (newz < mobj->target->z) + { + newz = mobj->target->z; + slope = NULL; + } + } + continue; + } + + d1 = mobj->target->z - (bottom + ((top - bottom)/2)); + d2 = (mobj->target->z + mobj->target->height) - (bottom + ((top - bottom)/2)); + + if (top > newz && abs(d1) < abs(d2)) + { + newz = top; #ifdef ESLOPE if (*rover->t_slope) slope = *rover->t_slope; From 24feb8167195ab18bd556dea102a2ea8d582478d Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 31 May 2019 01:08:04 -0400 Subject: [PATCH 7/8] Improve shadow code yet again by testing highest value of slopes This makes it follow the sprites a bit better on slopes. Also split into a sub-function so that Banana doesn't need the duplicated code anymore. The accuracy can be further improved on by doing the calculation 3 extra times for every surface, for each corner of the hitbox -- it wouldn't be THAT much more expensive, but it would only make subtle differences on sector boundaries that we usually zoom past anyway, so I figured it wasn't worth it. (It'll be easy enough to do so if we decide that we want the uber-accuracy) --- src/k_kart.c | 77 +------------ src/p_local.h | 1 + src/p_mobj.c | 291 ++++++++++++++++++++++++++++---------------------- 3 files changed, 170 insertions(+), 199 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index b3c75a599..45c8652c8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4527,82 +4527,11 @@ static void K_MoveHeldObjects(player_t *player) P_TeleportMove(cur, targx, targy, cur->z); #ifdef ESLOPE - // We gotta do ALL of this... just so that bananas can tilt in OGL :V if (P_IsObjectOnGround(cur)) { - pslope_t *slope = NULL; - sector_t *sec = R_PointInSubsector(cur->x, cur->y)->sector; - boolean flip = (cur->eflags & MFE_VERTICALFLIP); - - if (flip) - { - if (sec->c_slope) - { - slope = sec->c_slope; - targz = P_GetZAt(sec->c_slope, cur->x, cur->y); - } - else - targz = sec->ceilingheight; - } - else - { - if (sec->f_slope) - { - slope = sec->f_slope; - targz = P_GetZAt(sec->f_slope, cur->x, cur->y); - } - else - targz = sec->floorheight; - } - - // Check FOFs for a better suited slope - if (sec->ffloors) - { - ffloor_t *rover; - - for (rover = sec->ffloors; rover; rover = rover->next) - { - fixed_t surface; - - if (!(rover->flags & FF_EXISTS)) - continue; - - if (!((rover->flags & FF_BLOCKOTHERS) || (rover->flags & FF_QUICKSAND)) || (rover->flags & FF_SWIMMABLE)) - continue; - - if (flip) - { - surface = *rover->bottomheight; - if (*rover->b_slope) - surface = P_GetZAt(*rover->b_slope, cur->x, cur->y); - - if (surface < targz && surface > (cur->z + cur->height)) - { - targz = surface; - if (*rover->b_slope) - slope = *rover->b_slope; - } - } - else - { - surface = *rover->topheight; - if (*rover->t_slope) - surface = P_GetZAt(*rover->t_slope, cur->x, cur->y); - - if (surface > targz && surface < cur->z) - { - targz = surface; - if (*rover->t_slope) - slope = *rover->t_slope; - } - } - } - } - - cur->standingslope = slope; -#ifdef HWRENDER - cur->modeltilt = cur->standingslope; -#endif + // Slope values are set in the function, but we DON'T want to use its return value. + P_CalculateShadowFloor(cur, cur->x, cur->y, cur->z, + cur->radius, cur->height, (cur->eflags & MFE_VERTICALFLIP), false); } #endif diff --git a/src/p_local.h b/src/p_local.h index bc25affd4..d4da9fe29 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -227,6 +227,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state); boolean P_SetMobjState(mobj_t *mobj, statenum_t state); //void P_RunShields(void); void P_RunOverlays(void); +fixed_t P_CalculateShadowFloor(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z, fixed_t radius, fixed_t height, boolean flip, boolean player); void P_RunShadows(void); void P_MobjThinker(mobj_t *mobj); boolean P_RailThinker(mobj_t *mobj); diff --git a/src/p_mobj.c b/src/p_mobj.c index 67f540fde..c2a14cd45 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6205,6 +6205,170 @@ static void P_RemoveOverlay(mobj_t *thing) } } +// Simplified version of a code bit in P_MobjFloorZ +static fixed_t P_ShadowSlopeZ(pslope_t *slope, fixed_t x, fixed_t y, fixed_t radius, boolean ceiling) +{ + fixed_t testx, testy; + + if (slope->d.x < 0) + testx = radius; + else + testx = -radius; + + if (slope->d.y < 0) + testy = radius; + else + testy = -radius; + + if ((slope->zdelta > 0) ^ !!(ceiling)) + { + testx = -testx; + testy = -testy; + } + + testx += x; + testy += y; + + return P_GetZAt(slope, testx, testy); +} + +// Sets standingslope/modeltilt, returns z position for shadows; used also for stuff like bananas +// (I would've preferred to be able to return both the slope & z, but I'll take what I can get...) +fixed_t P_CalculateShadowFloor(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z, fixed_t radius, fixed_t height, boolean flip, boolean player) +{ + fixed_t newz; + sector_t *sec; +#ifdef ESLOPE + pslope_t *slope = NULL; +#endif + + sec = R_PointInSubsector(x, y)->sector; + + if (flip) + { +#ifdef ESLOPE + if (sec->c_slope) + { + slope = sec->c_slope; + newz = P_ShadowSlopeZ(slope, x, y, radius, true); + } + else +#endif + newz = sec->ceilingheight; + } + else + { +#ifdef ESLOPE + if (sec->f_slope) + { + slope = sec->f_slope; + newz = P_ShadowSlopeZ(slope, x, y, radius, false); + } + else +#endif + newz = sec->floorheight; + } + + // Check FOFs for a better suited slope + if (sec->ffloors) + { + ffloor_t *rover; + + for (rover = sec->ffloors; rover; rover = rover->next) + { + fixed_t top, bottom; + fixed_t d1, d2; + + if (!(rover->flags & FF_EXISTS)) + continue; + + if ((!(((rover->flags & FF_BLOCKPLAYER && player) + || (rover->flags & FF_BLOCKOTHERS && !player)) + || (rover->flags & FF_QUICKSAND)) + || (rover->flags & FF_SWIMMABLE))) + continue; + +#ifdef ESLOPE + if (*rover->t_slope) + top = P_ShadowSlopeZ(*rover->t_slope, x, y, radius, false); + else +#endif + top = *rover->topheight; + +#ifdef ESLOPE + if (*rover->b_slope) + bottom = P_ShadowSlopeZ(*rover->b_slope, x, y, radius, true); + else +#endif + bottom = *rover->bottomheight; + + if (flip) + { + if (rover->flags & FF_QUICKSAND) + { + if (z < top && (z + height) > bottom) + { + if (newz > (z + height)) + { + newz = (z + height); + slope = NULL; + } + } + continue; + } + + d1 = (z + height) - (top + ((bottom - top)/2)); + d2 = z - (top + ((bottom - top)/2)); + + if (bottom < newz && abs(d1) < abs(d2)) + { + newz = bottom; +#ifdef ESLOPE + if (*rover->b_slope) + slope = *rover->b_slope; +#endif + } + } + else + { + if (rover->flags & FF_QUICKSAND) + { + if (z < top && (z + height) > bottom) + { + if (newz < z) + { + newz = z; + slope = NULL; + } + } + continue; + } + + d1 = z - (bottom + ((top - bottom)/2)); + d2 = (z + height) - (bottom + ((top - bottom)/2)); + + if (top > newz && abs(d1) < abs(d2)) + { + newz = top; +#ifdef ESLOPE + if (*rover->t_slope) + slope = *rover->t_slope; +#endif + } + } + } + } + +#if 0 + mobj->standingslope = slope; +#endif +#ifdef HWRENDER + mobj->modeltilt = slope; +#endif + + return newz; +} + void P_RunShadows(void) { mobj_t *mobj, *next, *dest; @@ -6213,10 +6377,6 @@ void P_RunShadows(void) { boolean flip; fixed_t newz; - sector_t *sec; -#ifdef ESLOPE - pslope_t *slope = NULL; -#endif next = mobj->hnext; P_SetTarget(&mobj->hnext, NULL); @@ -6230,127 +6390,8 @@ void P_RunShadows(void) K_MatchGenericExtraFlags(mobj, mobj->target); flip = (mobj->eflags & MFE_VERTICALFLIP); - sec = R_PointInSubsector(mobj->target->x, mobj->target->y)->sector; - - if (flip) - { -#ifdef ESLOPE - if (sec->c_slope) - { - slope = sec->c_slope; - newz = P_GetZAt(sec->c_slope, mobj->target->x, mobj->target->y); - } - else -#endif - newz = sec->ceilingheight; - } - else - { -#ifdef ESLOPE - if (sec->f_slope) - { - slope = sec->f_slope; - newz = P_GetZAt(sec->f_slope, mobj->target->x, mobj->target->y); - } - else -#endif - newz = sec->floorheight; - } - - // Check FOFs for a better suited slope - if (sec->ffloors) - { - ffloor_t *rover; - - for (rover = sec->ffloors; rover; rover = rover->next) - { - fixed_t top, bottom; - fixed_t d1, d2; - - if (!(rover->flags & FF_EXISTS)) - continue; - - if ((!(((rover->flags & FF_BLOCKPLAYER && mobj->target->player) - || (rover->flags & FF_BLOCKOTHERS && !mobj->target->player)) - || (rover->flags & FF_QUICKSAND)) - || (rover->flags & FF_SWIMMABLE))) - continue; - -#ifdef ESLOPE - if (*rover->t_slope) - top = P_GetZAt(*rover->t_slope, mobj->target->x, mobj->target->y); - else -#endif - top = *rover->topheight; - -#ifdef ESLOPE - if (*rover->b_slope) - bottom = P_GetZAt(*rover->b_slope, mobj->target->x, mobj->target->y); - else -#endif - bottom = *rover->bottomheight; - - if (flip) - { - if (rover->flags & FF_QUICKSAND) - { - if (mobj->target->z < top && (mobj->target->z + mobj->target->height) > bottom) - { - if (newz > (mobj->target->z + mobj->target->height)) - { - newz = (mobj->target->z + mobj->target->height); - slope = NULL; - } - } - continue; - } - - d1 = (mobj->target->z + mobj->target->height) - (top + ((bottom - top)/2)); - d2 = mobj->target->z - (top + ((bottom - top)/2)); - - if (bottom < newz && abs(d1) < abs(d2)) - { - newz = bottom; -#ifdef ESLOPE - if (*rover->b_slope) - slope = *rover->b_slope; -#endif - } - } - else - { - if (rover->flags & FF_QUICKSAND) - { - if (mobj->target->z < top && (mobj->target->z + mobj->target->height) > bottom) - { - if (newz < mobj->target->z) - { - newz = mobj->target->z; - slope = NULL; - } - } - continue; - } - - d1 = mobj->target->z - (bottom + ((top - bottom)/2)); - d2 = (mobj->target->z + mobj->target->height) - (bottom + ((top - bottom)/2)); - - if (top > newz && abs(d1) < abs(d2)) - { - newz = top; -#ifdef ESLOPE - if (*rover->t_slope) - slope = *rover->t_slope; -#endif - } - } - } - } - - mobj->standingslope = slope; -#ifdef HWRENDER - mobj->modeltilt = mobj->standingslope; -#endif + newz = P_CalculateShadowFloor(mobj, mobj->target->x, mobj->target->y, mobj->target->z, + mobj->target->radius, mobj->target->height, flip, (mobj->target->player != NULL)); if (flip) { From 407157496a56b97925dbf9034910da585643fd65 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 16 Jul 2019 16:03:31 -0400 Subject: [PATCH 8/8] Fix colors looking washed-out on models --- src/hardware/hw_md2.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index b610d410c..21deed84b 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -849,27 +849,17 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, { // Color strength depends on image alpha INT32 tempcolor; - INT16 tempmult, tempalpha; - tempalpha = -(abs(blendimage->s.red-127)-127)*2; - if (tempalpha > 255) - tempalpha = 255; - else if (tempalpha < 0) - tempalpha = 0; - - tempmult = (blendimage->s.red-127)*2; - if (tempmult > 255) - tempmult = 255; - else if (tempmult < 0) - tempmult = 0; - - tempcolor = (image->s.red*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.red)/255)) * blendimage->s.alpha)/255; + tempcolor = ((image->s.red * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.red * blendimage->s.alpha) / 255); + tempcolor = min(255, tempcolor); cur->s.red = (UINT8)tempcolor; - tempcolor = (image->s.green*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.green)/255)) * blendimage->s.alpha)/255; + tempcolor = ((image->s.green * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.green * blendimage->s.alpha) / 255); + tempcolor = min(255, tempcolor); cur->s.green = (UINT8)tempcolor; - tempcolor = (image->s.blue*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.blue)/255)) * blendimage->s.alpha)/255; + tempcolor = ((image->s.blue * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.blue * blendimage->s.alpha) / 255); + tempcolor = min(255, tempcolor); cur->s.blue = (UINT8)tempcolor; cur->s.alpha = image->s.alpha; }