mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-03-23 03:12:38 +00:00
Merge branch 'bbox' into 'next'
Hitbox Renderer See merge request STJr/SRB2!1838
This commit is contained in:
commit
f428759150
11 changed files with 607 additions and 21 deletions
|
@ -64,6 +64,7 @@ r_skins.c
|
|||
r_sky.c
|
||||
r_splats.c
|
||||
r_things.c
|
||||
r_bbox.c
|
||||
r_textures.c
|
||||
r_patch.c
|
||||
r_patchrotation.c
|
||||
|
|
|
@ -873,6 +873,9 @@ void D_RegisterClientCommands(void)
|
|||
// screen.c
|
||||
CV_RegisterVar(&cv_fullscreen);
|
||||
CV_RegisterVar(&cv_renderview);
|
||||
CV_RegisterVar(&cv_renderhitboxinterpolation);
|
||||
CV_RegisterVar(&cv_renderhitboxgldepth);
|
||||
CV_RegisterVar(&cv_renderhitbox);
|
||||
CV_RegisterVar(&cv_renderer);
|
||||
CV_RegisterVar(&cv_scr_depth);
|
||||
CV_RegisterVar(&cv_scr_width);
|
||||
|
|
|
@ -136,6 +136,7 @@ typedef struct
|
|||
// Predefined shader types
|
||||
enum
|
||||
{
|
||||
SHADER_NONE = -1,
|
||||
SHADER_DEFAULT = 0,
|
||||
|
||||
SHADER_FLOOR,
|
||||
|
@ -237,7 +238,8 @@ enum EPolyFlags
|
|||
PF_RemoveYWrap = 0x00010000, // Forces clamp texture on Y
|
||||
PF_ForceWrapX = 0x00020000, // Forces repeat texture on X
|
||||
PF_ForceWrapY = 0x00040000, // Forces repeat texture on Y
|
||||
PF_Ripple = 0x00100000 // Water ripple effect. The current backend doesn't use it for anything.
|
||||
PF_Ripple = 0x00100000, // Water ripple effect. The current backend doesn't use it for anything.
|
||||
PF_WireFrame = 0x00200000, // Draws vertices as lines instead of triangles
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ typedef struct gl_vissprite_s
|
|||
|
||||
boolean flip, vflip;
|
||||
boolean precip; // Tails 08-25-2002
|
||||
boolean bbox;
|
||||
boolean rotated;
|
||||
UINT8 translucency; //alpha level 0-255
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ static void HWR_ProjectSprite(mobj_t *thing);
|
|||
#ifdef HWPRECIP
|
||||
static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
|
||||
#endif
|
||||
static void HWR_ProjectBoundingBox(mobj_t *thing);
|
||||
|
||||
void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap);
|
||||
void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
|
||||
|
@ -4038,6 +4039,54 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
|
|||
HWR_LinkDrawHackAdd(wallVerts, spr);
|
||||
}
|
||||
|
||||
static void HWR_DrawBoundingBox(gl_vissprite_t *vis)
|
||||
{
|
||||
FOutVector v[24];
|
||||
FSurfaceInfo Surf = {0};
|
||||
|
||||
//
|
||||
// create a cube (side view)
|
||||
//
|
||||
// 5--4 3
|
||||
// |
|
||||
// |
|
||||
// 0--1 2
|
||||
//
|
||||
// repeat this 4 times (overhead)
|
||||
//
|
||||
//
|
||||
// 17 20 21 11
|
||||
// 16 15 14 10
|
||||
// 27 22 *--* 07 12
|
||||
// | |
|
||||
// 26 23 *--* 06 13
|
||||
// 24 00 01 02
|
||||
// 25 05 04 03
|
||||
//
|
||||
|
||||
v[000].x = v[005].x = v[015].x = v[016].x = v[017].x = v[020].x =
|
||||
v[022].x = v[023].x = v[024].x = v[025].x = v[026].x = v[027].x = vis->x1; // west
|
||||
|
||||
v[001].x = v[002].x = v[003].x = v[004].x = v[006].x = v[007].x =
|
||||
v[010].x = v[011].x = v[012].x = v[013].x = v[014].x = v[021].x = vis->x2; // east
|
||||
|
||||
v[000].z = v[001].z = v[002].z = v[003].z = v[004].z = v[005].z =
|
||||
v[006].z = v[013].z = v[023].z = v[024].z = v[025].z = v[026].z = vis->z1; // south
|
||||
|
||||
v[007].z = v[010].z = v[011].z = v[012].z = v[014].z = v[015].z =
|
||||
v[016].z = v[017].z = v[020].z = v[021].z = v[022].z = v[027].z = vis->z2; // north
|
||||
|
||||
v[000].y = v[001].y = v[002].y = v[006].y = v[007].y = v[010].y =
|
||||
v[014].y = v[015].y = v[016].y = v[022].y = v[023].y = v[024].y = vis->gz; // bottom
|
||||
|
||||
v[003].y = v[004].y = v[005].y = v[011].y = v[012].y = v[013].y =
|
||||
v[017].y = v[020].y = v[021].y = v[025].y = v[026].y = v[027].y = vis->gzt; // top
|
||||
|
||||
Surf.PolyColor = V_GetColor(R_GetBoundingBoxColor(vis->mobj));
|
||||
|
||||
HWR_ProcessPolygon(&Surf, v, 24, (cv_renderhitboxgldepth.value ? 0 : PF_NoDepthTest)|PF_Modulated|PF_NoTexture|PF_WireFrame, SHADER_NONE, false);
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
// HWR_DrawSprite : Draw flat sprites
|
||||
// : (monsters, bonuses, weapons, lights, ...)
|
||||
|
@ -4482,9 +4531,16 @@ static int CompareVisSprites(const void *p1, const void *p2)
|
|||
int transparency1;
|
||||
int transparency2;
|
||||
|
||||
int linkdraw1;
|
||||
int linkdraw2;
|
||||
|
||||
// draw bbox after everything else
|
||||
if (spr1->bbox || spr2->bbox)
|
||||
return (spr1->bbox - spr2->bbox);
|
||||
|
||||
// check for precip first, because then sprX->mobj is actually a precipmobj_t and does not have flags2 or tracer
|
||||
int linkdraw1 = !spr1->precip && (spr1->mobj->flags2 & MF2_LINKDRAW) && spr1->mobj->tracer;
|
||||
int linkdraw2 = !spr2->precip && (spr2->mobj->flags2 & MF2_LINKDRAW) && spr2->mobj->tracer;
|
||||
linkdraw1 = !spr1->precip && (spr1->mobj->flags2 & MF2_LINKDRAW) && spr1->mobj->tracer;
|
||||
linkdraw2 = !spr2->precip && (spr2->mobj->flags2 & MF2_LINKDRAW) && spr2->mobj->tracer;
|
||||
|
||||
// ^ is the XOR operation
|
||||
// if comparing a linkdraw and non-linkdraw sprite or 2 linkdraw sprites with different tracers, then use
|
||||
|
@ -4854,6 +4910,9 @@ static void HWR_DrawSprites(void)
|
|||
for (i = 0; i < gl_visspritecount; i++)
|
||||
{
|
||||
gl_vissprite_t *spr = gl_vsprorder[i];
|
||||
if (spr->bbox)
|
||||
HWR_DrawBoundingBox(spr);
|
||||
else
|
||||
#ifdef HWPRECIP
|
||||
if (spr->precip)
|
||||
HWR_DrawPrecipitationSprite(spr);
|
||||
|
@ -4953,8 +5012,15 @@ static void HWR_AddSprites(sector_t *sec)
|
|||
hoop_limit_dist = (fixed_t)(cv_drawdist_nights.value) << FRACBITS;
|
||||
for (thing = sec->thinglist; thing; thing = thing->snext)
|
||||
{
|
||||
if (R_ThingVisibleWithinDist(thing, limit_dist, hoop_limit_dist))
|
||||
HWR_ProjectSprite(thing);
|
||||
if (R_ThingWithinDist(thing, limit_dist, hoop_limit_dist))
|
||||
{
|
||||
if (R_ThingVisible(thing))
|
||||
{
|
||||
HWR_ProjectSprite(thing);
|
||||
}
|
||||
|
||||
HWR_ProjectBoundingBox(thing);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HWPRECIP
|
||||
|
@ -5472,6 +5538,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
vis->vflip = vflip;
|
||||
|
||||
vis->precip = false;
|
||||
vis->bbox = false;
|
||||
|
||||
vis->angle = interp.angle;
|
||||
}
|
||||
|
@ -5594,6 +5661,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
vis->gz = vis->gzt - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height);
|
||||
|
||||
vis->precip = true;
|
||||
vis->bbox = false;
|
||||
|
||||
// okay... this is a hack, but weather isn't networked, so it should be ok
|
||||
if (!(thing->precipflags & PCF_THUNK))
|
||||
|
@ -5607,6 +5675,61 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void HWR_ProjectBoundingBox(mobj_t *thing)
|
||||
{
|
||||
gl_vissprite_t *vis;
|
||||
float tr_x, tr_y;
|
||||
float tz;
|
||||
float rad;
|
||||
|
||||
if (!thing)
|
||||
return;
|
||||
|
||||
if (!R_ThingBoundingBoxVisible(thing))
|
||||
return;
|
||||
|
||||
// uncapped/interpolation
|
||||
boolean interpolate = cv_renderhitboxinterpolation.value;
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
if (R_UsingFrameInterpolation() && !paused && interpolate)
|
||||
{
|
||||
R_InterpolateMobjState(thing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolateMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
// transform the origin point
|
||||
tr_x = FIXED_TO_FLOAT(interp.x) - gl_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(interp.y) - gl_viewy;
|
||||
|
||||
// rotation around vertical axis
|
||||
tz = (tr_x * gl_viewcos) + (tr_y * gl_viewsin);
|
||||
|
||||
// thing is behind view plane?
|
||||
if (tz < ZCLIP_PLANE)
|
||||
return;
|
||||
|
||||
tr_x += gl_viewx;
|
||||
tr_y += gl_viewy;
|
||||
|
||||
rad = FIXED_TO_FLOAT(thing->radius);
|
||||
|
||||
vis = HWR_NewVisSprite();
|
||||
vis->x1 = tr_x - rad;
|
||||
vis->x2 = tr_x + rad;
|
||||
vis->z1 = tr_y - rad;
|
||||
vis->z2 = tr_y + rad;
|
||||
vis->gz = FIXED_TO_FLOAT(interp.z);
|
||||
vis->gzt = vis->gz + FIXED_TO_FLOAT(thing->height);
|
||||
vis->mobj = thing;
|
||||
|
||||
vis->precip = false;
|
||||
vis->bbox = true;
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Sky dome rendering, ported from PrBoom+
|
||||
// ==========================================================================
|
||||
|
|
|
@ -1030,6 +1030,12 @@ EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boole
|
|||
EXPORT void HWRAPI(SetShader) (int type)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
if (type == SHADER_NONE)
|
||||
{
|
||||
UnSetShader();
|
||||
return;
|
||||
}
|
||||
|
||||
if (gl_allowshaders != HWD_SHADEROPTION_OFF)
|
||||
{
|
||||
gl_shader_t *shader = gl_shaderstate.current;
|
||||
|
@ -2290,7 +2296,7 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUI
|
|||
|
||||
pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x);
|
||||
pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s);
|
||||
pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts);
|
||||
pglDrawArrays(PolyFlags & PF_WireFrame ? GL_LINES : GL_TRIANGLE_FAN, 0, iNumPts);
|
||||
|
||||
if (PolyFlags & PF_RemoveYWrap)
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
|
|
@ -122,7 +122,7 @@ typedef enum
|
|||
MF_AMBIENT = 1<<10,
|
||||
// Slide this object when it hits a wall.
|
||||
MF_SLIDEME = 1<<11,
|
||||
// Player cheat.
|
||||
// Don't collide with walls or solid objects. Two MF_NOCLIP objects can't touch each other at all!
|
||||
MF_NOCLIP = 1<<12,
|
||||
// Allow moves to any height, no gravity. For active floaters.
|
||||
MF_FLOAT = 1<<13,
|
||||
|
|
318
src/r_bbox.c
Normal file
318
src/r_bbox.c
Normal file
|
@ -0,0 +1,318 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 2022 by Kart Krew.
|
||||
// Copyright (C) 1999-2022 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file r_bbox.c
|
||||
/// \brief Boundary box (cube) renderer
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "command.h"
|
||||
#include "r_local.h"
|
||||
#include "screen.h" // cv_renderhitbox
|
||||
#include "v_video.h" // V_DrawFill
|
||||
|
||||
enum {
|
||||
RENDERHITBOX_OFF,
|
||||
RENDERHITBOX_TANGIBLE,
|
||||
RENDERHITBOX_ALL,
|
||||
RENDERHITBOX_INTANGIBLE,
|
||||
RENDERHITBOX_RINGS,
|
||||
};
|
||||
|
||||
static CV_PossibleValue_t renderhitbox_cons_t[] = {
|
||||
{RENDERHITBOX_OFF, "Off"},
|
||||
{RENDERHITBOX_TANGIBLE, "Tangible"},
|
||||
{RENDERHITBOX_ALL, "All"},
|
||||
{RENDERHITBOX_INTANGIBLE, "Intangible"},
|
||||
{RENDERHITBOX_RINGS, "Rings"},
|
||||
{0}};
|
||||
|
||||
consvar_t cv_renderhitbox = CVAR_INIT ("renderhitbox", "Off", CV_CHEAT, renderhitbox_cons_t, NULL);
|
||||
consvar_t cv_renderhitboxinterpolation = CVAR_INIT ("renderhitbox_interpolation", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
consvar_t cv_renderhitboxgldepth = CVAR_INIT ("renderhitbox_gldepth", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
|
||||
struct bbox_col {
|
||||
INT32 x;
|
||||
INT32 y;
|
||||
INT32 h;
|
||||
};
|
||||
|
||||
struct bbox_config {
|
||||
fixed_t height;
|
||||
fixed_t tz;
|
||||
struct bbox_col col[4];
|
||||
UINT8 color;
|
||||
};
|
||||
|
||||
static inline void
|
||||
raster_bbox_seg
|
||||
( INT32 x,
|
||||
fixed_t y,
|
||||
fixed_t h,
|
||||
UINT8 pixel)
|
||||
{
|
||||
y /= FRACUNIT;
|
||||
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
|
||||
h = y + (FixedCeil(abs(h)) / FRACUNIT);
|
||||
|
||||
if (h >= viewheight)
|
||||
h = viewheight;
|
||||
|
||||
while (y < h)
|
||||
{
|
||||
topleft[x + y * vid.width] = pixel;
|
||||
y++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
draw_bbox_col
|
||||
( struct bbox_config * bb,
|
||||
size_t p,
|
||||
fixed_t tx,
|
||||
fixed_t ty)
|
||||
{
|
||||
struct bbox_col *col = &bb->col[p];
|
||||
|
||||
fixed_t xscale, yscale;
|
||||
|
||||
if (ty < FRACUNIT) // projection breaks down here
|
||||
ty = FRACUNIT;
|
||||
|
||||
xscale = FixedDiv(projection, ty);
|
||||
yscale = FixedDiv(projectiony, ty);
|
||||
|
||||
col->x = (centerxfrac + FixedMul(tx, xscale)) / FRACUNIT;
|
||||
col->y = (centeryfrac - FixedMul(bb->tz, yscale));
|
||||
col->h = FixedMul(bb->height, yscale);
|
||||
|
||||
// Using this function is TOO EASY!
|
||||
V_DrawFill(
|
||||
viewwindowx + col->x,
|
||||
viewwindowy + col->y / FRACUNIT, 1,
|
||||
col->h / FRACUNIT, V_NOSCALESTART | bb->color);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_bbox_row
|
||||
( struct bbox_config * bb,
|
||||
size_t p1,
|
||||
size_t p2)
|
||||
{
|
||||
struct bbox_col
|
||||
*a = &bb->col[p1],
|
||||
*b = &bb->col[p2];
|
||||
|
||||
INT32 x1, x2; // left, right
|
||||
INT32 dx; // width
|
||||
|
||||
fixed_t y1, y2; // top, bottom
|
||||
fixed_t s1, s2; // top and bottom increment
|
||||
|
||||
if (a->x > b->x)
|
||||
{
|
||||
struct bbox_col *c = a;
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
|
||||
x1 = a->x;
|
||||
x2 = b->x;
|
||||
|
||||
if (x2 >= viewwidth)
|
||||
x2 = viewwidth - 1;
|
||||
|
||||
if (x1 == x2 || x1 >= viewwidth || x2 < 0)
|
||||
return;
|
||||
|
||||
dx = x2 - x1;
|
||||
|
||||
y1 = a->y;
|
||||
y2 = b->y;
|
||||
s1 = (y2 - y1) / dx;
|
||||
|
||||
y2 = y1 + a->h;
|
||||
s2 = ((b->y + b->h) - y2) / dx;
|
||||
|
||||
// FixedCeil needs a minimum!!! :D :D
|
||||
|
||||
if (s1 == 0)
|
||||
s1 = 1;
|
||||
|
||||
if (s2 == 0)
|
||||
s2 = 1;
|
||||
|
||||
if (x1 < 0)
|
||||
{
|
||||
y1 -= x1 * s1;
|
||||
y2 -= x1 * s2;
|
||||
x1 = 0;
|
||||
}
|
||||
|
||||
while (x1 < x2)
|
||||
{
|
||||
raster_bbox_seg(x1, y1, s1, bb->color);
|
||||
raster_bbox_seg(x1, y2, s2, bb->color);
|
||||
|
||||
y1 += s1;
|
||||
y2 += s2;
|
||||
|
||||
x1++;
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 R_GetBoundingBoxColor(mobj_t *thing)
|
||||
{
|
||||
UINT32 flags = thing->flags;
|
||||
|
||||
if (thing->player)
|
||||
return 255; // 0FF
|
||||
|
||||
if (flags & (MF_NOCLIPTHING))
|
||||
return 7; // BFBFBF
|
||||
|
||||
if (flags & (MF_BOSS|MF_ENEMY))
|
||||
return 35; // F00
|
||||
|
||||
if (flags & (MF_MISSILE|MF_PAIN))
|
||||
return 54; // F70
|
||||
|
||||
if (flags & (MF_SPECIAL|MF_MONITOR))
|
||||
return 73; // FF0
|
||||
|
||||
if (flags & MF_PUSHABLE)
|
||||
return 112; // 0F0
|
||||
|
||||
if (flags & (MF_SPRING))
|
||||
return 181; // F0F
|
||||
|
||||
if (flags & (MF_NOCLIP))
|
||||
return 152; // 00F
|
||||
|
||||
return 0; // FFF
|
||||
}
|
||||
|
||||
void R_DrawThingBoundingBox(vissprite_t *vis)
|
||||
{
|
||||
// radius offsets
|
||||
fixed_t rs = vis->scale;
|
||||
fixed_t rc = vis->xscale;
|
||||
|
||||
// translated coordinates
|
||||
fixed_t tx = vis->gx;
|
||||
fixed_t ty = vis->gy;
|
||||
|
||||
struct bbox_config bb = {
|
||||
.height = vis->thingheight,
|
||||
.tz = vis->texturemid,
|
||||
.color = R_GetBoundingBoxColor(vis->mobj),
|
||||
};
|
||||
|
||||
// 1--3
|
||||
// | |
|
||||
// 0--2
|
||||
|
||||
// left
|
||||
|
||||
draw_bbox_col(&bb, 0, tx, ty); // bottom
|
||||
draw_bbox_col(&bb, 1, tx - rc, ty + rs); // top
|
||||
|
||||
// right
|
||||
|
||||
tx += rs;
|
||||
ty += rc;
|
||||
|
||||
draw_bbox_col(&bb, 2, tx, ty); // bottom
|
||||
draw_bbox_col(&bb, 3, tx - rc, ty + rs); // top
|
||||
|
||||
// connect all four columns
|
||||
|
||||
draw_bbox_row(&bb, 0, 1);
|
||||
draw_bbox_row(&bb, 1, 3);
|
||||
draw_bbox_row(&bb, 3, 2);
|
||||
draw_bbox_row(&bb, 2, 0);
|
||||
}
|
||||
|
||||
static boolean is_tangible (mobj_t *thing)
|
||||
{
|
||||
// These objects can never touch another
|
||||
if (thing->flags & (MF_NOCLIPTHING))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// These objects probably do nothing! :D
|
||||
if ((thing->flags & (MF_SPECIAL|MF_SOLID|MF_SHOOTABLE
|
||||
|MF_PUSHABLE|MF_BOSS|MF_MISSILE|MF_SPRING
|
||||
|MF_BOUNCE|MF_MONITOR|MF_FIRE|MF_ENEMY
|
||||
|MF_PAIN|MF_STICKY
|
||||
|MF_GRENADEBOUNCE)) == 0U)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean R_ThingBoundingBoxVisible(mobj_t *thing)
|
||||
{
|
||||
INT32 cvmode = cv_renderhitbox.value;
|
||||
|
||||
// Do not render bbox for these
|
||||
switch (thing->type)
|
||||
{
|
||||
default:
|
||||
// First person / awayviewmobj -- rendering
|
||||
// a bbox too close to the viewpoint causes
|
||||
// anomalies and these are exactly on the
|
||||
// viewpoint!
|
||||
if (thing != r_viewmobj)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// FALLTHRU
|
||||
|
||||
case MT_SKYBOX:
|
||||
// Ditto for skybox viewpoint but because they
|
||||
// are rendered using portals in Software,
|
||||
// r_viewmobj does not point here.
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (cvmode)
|
||||
{
|
||||
case RENDERHITBOX_OFF:
|
||||
return false;
|
||||
|
||||
case RENDERHITBOX_ALL:
|
||||
return true;
|
||||
|
||||
case RENDERHITBOX_INTANGIBLE:
|
||||
return !is_tangible(thing);
|
||||
|
||||
case RENDERHITBOX_TANGIBLE:
|
||||
// Exclude rings from here, lots of them!
|
||||
if (thing->type == MT_RING)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return is_tangible(thing);
|
||||
|
||||
case RENDERHITBOX_RINGS:
|
||||
return (thing->type == MT_RING || thing->type == MT_BLUESPHERE);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
150
src/r_things.c
150
src/r_things.c
|
@ -1426,6 +1426,105 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
|
|||
objectsdrawn++;
|
||||
}
|
||||
|
||||
static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis)
|
||||
{
|
||||
fixed_t gx, gy;
|
||||
fixed_t tx, tz;
|
||||
|
||||
vissprite_t *box;
|
||||
|
||||
if (!R_ThingBoundingBoxVisible(thing))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// uncapped/interpolation
|
||||
boolean interpolate = cv_renderhitboxinterpolation.value;
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
// do interpolation
|
||||
if (R_UsingFrameInterpolation() && !paused && interpolate)
|
||||
{
|
||||
R_InterpolateMobjState(thing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolateMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
// 1--3
|
||||
// | |
|
||||
// 0--2
|
||||
|
||||
// start in the (0) corner
|
||||
gx = interp.x - thing->radius - viewx;
|
||||
gy = interp.y - thing->radius - viewy;
|
||||
|
||||
tz = FixedMul(gx, viewcos) + FixedMul(gy, viewsin);
|
||||
|
||||
// thing is behind view plane?
|
||||
// if parent vis is visible, ignore this
|
||||
if (!vis && (tz < FixedMul(MINZ, interp.scale)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tx = FixedMul(gx, viewsin) - FixedMul(gy, viewcos);
|
||||
|
||||
// too far off the side?
|
||||
if (!vis && abs(tx) > FixedMul(tz, fovtan)<<2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
box = R_NewVisSprite();
|
||||
box->mobj = thing;
|
||||
box->mobjflags = thing->flags;
|
||||
box->thingheight = thing->height;
|
||||
box->cut = SC_BBOX;
|
||||
|
||||
box->gx = tx;
|
||||
box->gy = tz;
|
||||
|
||||
box->scale = 2 * FixedMul(thing->radius, viewsin);
|
||||
box->xscale = 2 * FixedMul(thing->radius, viewcos);
|
||||
|
||||
box->pz = interp.z;
|
||||
box->pzt = box->pz + box->thingheight;
|
||||
|
||||
box->gzt = box->pzt;
|
||||
box->gz = box->pz;
|
||||
box->texturemid = box->gzt - viewz;
|
||||
|
||||
if (vis)
|
||||
{
|
||||
box->x1 = vis->x1;
|
||||
box->x2 = vis->x2;
|
||||
box->szt = vis->szt;
|
||||
box->sz = vis->sz;
|
||||
|
||||
box->sortscale = vis->sortscale; // link sorting to sprite
|
||||
box->dispoffset = vis->dispoffset + 5;
|
||||
|
||||
box->cut |= SC_LINKDRAW;
|
||||
}
|
||||
else
|
||||
{
|
||||
fixed_t xscale = FixedDiv(projection, tz);
|
||||
fixed_t yscale = FixedDiv(projectiony, tz);
|
||||
fixed_t top = (centeryfrac - FixedMul(box->texturemid, yscale));
|
||||
|
||||
box->x1 = (centerxfrac + FixedMul(box->gx, xscale)) / FRACUNIT;
|
||||
box->x2 = box->x1;
|
||||
|
||||
box->szt = top / FRACUNIT;
|
||||
box->sz = (top + FixedMul(box->thingheight, yscale)) / FRACUNIT;
|
||||
|
||||
box->sortscale = yscale;
|
||||
box->dispoffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// R_ProjectSprite
|
||||
// Generates a vissprite for a thing
|
||||
|
@ -2187,6 +2286,8 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
if (oldthing->shadowscale && cv_shadow.value)
|
||||
R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, basetz);
|
||||
|
||||
R_ProjectBoundingBox(oldthing, vis);
|
||||
|
||||
// Debug
|
||||
++objectsdrawn;
|
||||
}
|
||||
|
@ -2412,8 +2513,26 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
|
|||
hoop_limit_dist = (fixed_t)(cv_drawdist_nights.value) << FRACBITS;
|
||||
for (thing = sec->thinglist; thing; thing = thing->snext)
|
||||
{
|
||||
if (R_ThingVisibleWithinDist(thing, limit_dist, hoop_limit_dist))
|
||||
R_ProjectSprite(thing);
|
||||
if (R_ThingWithinDist(thing, limit_dist, hoop_limit_dist))
|
||||
{
|
||||
const INT32 oldobjectsdrawn = objectsdrawn;
|
||||
|
||||
if (R_ThingVisible(thing))
|
||||
{
|
||||
R_ProjectSprite(thing);
|
||||
}
|
||||
|
||||
// I'm so smart :^)
|
||||
if (objectsdrawn == oldobjectsdrawn)
|
||||
{
|
||||
/*
|
||||
Object is invisible OR is off screen but
|
||||
render its bbox even if the latter because
|
||||
radius could be bigger than sprite.
|
||||
*/
|
||||
R_ProjectBoundingBox(thing, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off
|
||||
|
@ -2501,6 +2620,10 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e
|
|||
if (dsfirst->cut & SC_SHADOW)
|
||||
continue;
|
||||
|
||||
// don't connect to your bounding box!
|
||||
if (dsfirst->cut & SC_BBOX)
|
||||
continue;
|
||||
|
||||
// don't connect if it's not the tracer
|
||||
if (dsfirst->mobj != ds->mobj)
|
||||
continue;
|
||||
|
@ -2941,7 +3064,9 @@ static void R_DrawSprite(vissprite_t *spr)
|
|||
mfloorclip = spr->clipbot;
|
||||
mceilingclip = spr->cliptop;
|
||||
|
||||
if (spr->cut & SC_SPLAT)
|
||||
if (spr->cut & SC_BBOX)
|
||||
R_DrawThingBoundingBox(spr);
|
||||
else if (spr->cut & SC_SPLAT)
|
||||
R_DrawFloorSplat(spr);
|
||||
else
|
||||
R_DrawVisSprite(spr);
|
||||
|
@ -3180,9 +3305,13 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
|
|||
for (; clippedvissprites < visspritecount; clippedvissprites++)
|
||||
{
|
||||
vissprite_t *spr = R_GetVisSprite(clippedvissprites);
|
||||
INT32 x1 = (spr->cut & SC_SPLAT) ? 0 : spr->x1;
|
||||
INT32 x2 = (spr->cut & SC_SPLAT) ? viewwidth : spr->x2;
|
||||
R_ClipVisSprite(spr, x1, x2, dsstart, portal);
|
||||
|
||||
if (!(spr->cut & SC_BBOX)) // Do not clip bounding boxes
|
||||
{
|
||||
INT32 x1 = (spr->cut & SC_SPLAT) ? 0 : spr->x1;
|
||||
INT32 x2 = (spr->cut & SC_SPLAT) ? viewwidth : spr->x2;
|
||||
R_ClipVisSprite(spr, x1, x2, dsstart, portal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3196,16 +3325,11 @@ boolean R_ThingVisible (mobj_t *thing)
|
|||
));
|
||||
}
|
||||
|
||||
boolean R_ThingVisibleWithinDist (mobj_t *thing,
|
||||
boolean R_ThingWithinDist (mobj_t *thing,
|
||||
fixed_t limit_dist,
|
||||
fixed_t hoop_limit_dist)
|
||||
{
|
||||
fixed_t approx_dist;
|
||||
|
||||
if (! R_ThingVisible(thing))
|
||||
return false;
|
||||
|
||||
approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y);
|
||||
const fixed_t approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y);
|
||||
|
||||
if (thing->sprite == SPR_HOOP)
|
||||
{
|
||||
|
|
|
@ -66,9 +66,12 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel);
|
|||
void R_InitSprites(void);
|
||||
void R_ClearSprites(void);
|
||||
|
||||
UINT8 R_GetBoundingBoxColor(mobj_t *thing);
|
||||
boolean R_ThingBoundingBoxVisible(mobj_t *thing);
|
||||
|
||||
boolean R_ThingVisible (mobj_t *thing);
|
||||
|
||||
boolean R_ThingVisibleWithinDist (mobj_t *thing,
|
||||
boolean R_ThingWithinDist (mobj_t *thing,
|
||||
fixed_t draw_dist,
|
||||
fixed_t nights_draw_dist);
|
||||
|
||||
|
@ -132,6 +135,7 @@ typedef enum
|
|||
SC_SHADOW = 1<<10,
|
||||
SC_SHEAR = 1<<11,
|
||||
SC_SPLAT = 1<<12,
|
||||
SC_BBOX = 1<<13,
|
||||
// masks
|
||||
SC_CUTMASK = SC_TOP|SC_BOTTOM,
|
||||
SC_FLAGMASK = ~SC_CUTMASK
|
||||
|
@ -221,6 +225,9 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal);
|
|||
void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, portal_t* portal);
|
||||
|
||||
boolean R_SpriteIsFlashing(vissprite_t *vis);
|
||||
|
||||
void R_DrawThingBoundingBox(vissprite_t *spr);
|
||||
|
||||
UINT8 *R_GetSpriteTranslation(vissprite_t *vis);
|
||||
|
||||
// ----------
|
||||
|
|
|
@ -200,6 +200,7 @@ extern INT32 scr_bpp;
|
|||
extern UINT8 *scr_borderpatch; // patch used to fill the view borders
|
||||
|
||||
extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_renderer, cv_fullscreen;
|
||||
extern consvar_t cv_renderhitbox, cv_renderhitboxinterpolation, cv_renderhitboxgldepth;
|
||||
// wait for page flipping to end or not
|
||||
extern consvar_t cv_vidwait;
|
||||
extern consvar_t cv_timescale;
|
||||
|
|
Loading…
Reference in a new issue