Skip to content

Commit

Permalink
port: better light glare hit detection
Browse files Browse the repository at this point in the history
  • Loading branch information
fgsfdsfgs committed May 12, 2024
1 parent 1300312 commit 15c0327
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 33 deletions.
22 changes: 22 additions & 0 deletions src/game/bg.c
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,9 @@ Gfx *bgRenderScene(Gfx *gdl)
s16 roomorder[60];
RoomNum roomnums[60];

#ifdef PLATFORM_N64
g_NumRoomsWithGlares = 0;
#endif

if (g_Vars.currentplayer->visionmode == VISIONMODE_XRAY) {
gdl = bgRenderSceneInXray(gdl);
Expand Down Expand Up @@ -1206,13 +1208,15 @@ Gfx *bgRenderScene(Gfx *gdl)
gdl = propsRender(gdl, thing->roomnum, RENDERPASS_XLU, roomnumsbyprop);
}

#ifdef PLATFORM_N64 // on PC we do this earlier, before prop matrices turn into garbage
if (!g_Vars.mplayerisrunning) {
artifactsCalculateGlaresForRoom(thing->roomnum);

if (g_NumRoomsWithGlares < 100) {
g_GlareRooms[g_NumRoomsWithGlares++] = thing->roomnum;
}
}
#endif
}

#if VERSION < VERSION_NTSC_1_0
Expand Down Expand Up @@ -6397,3 +6401,21 @@ void bgFindEnteredRooms(struct coord *bbmin, struct coord *bbmax, RoomNum *rooms
end:
rooms[len] = -1;
}

#ifndef PLATFORM_N64

void bgCalculateGlaresForVisibleRooms(void)
{
s32 i;
g_NumRoomsWithGlares = 0;
for (i = 1; i < g_Vars.roomcount; i++) {
if (g_Rooms[i].flags & ROOMFLAG_ONSCREEN) {
artifactsCalculateGlaresForRoom(i);
if (g_NumRoomsWithGlares < 100) {
g_GlareRooms[g_NumRoomsWithGlares++] = i;
}
}
}
}

#endif
44 changes: 13 additions & 31 deletions src/game/game_13c510.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include "lib/collision.h"
#include "lib/lib_17ce0.h"
#include "game/player.h"
f32 fabsf(f32 value);
#include "game/prop.h"
#endif

u8 *var800a41a0;
Expand Down Expand Up @@ -104,8 +104,10 @@ s32 func0f13c710(f32 arg0)

#ifndef PLATFORM_N64

bool artifactTestLos(struct coord *spec, struct coord *roompos)
bool artifactTestLos(struct coord *spec, struct coord *roompos, s32 xi, s32 yi)
{
s32 i = 0;

if (!g_Vars.currentplayer) {
return false;
}
Expand All @@ -115,35 +117,15 @@ bool artifactTestLos(struct coord *spec, struct coord *roompos)
endpos.y = roompos->y + spec->y;
endpos.z = roompos->z + spec->z;

// get what rooms the LOS goes through
RoomNum outrooms[17], tmprooms[8], srcrooms[2];
srcrooms[0] = g_Vars.currentplayer->cam_room;
srcrooms[1] = -1;
outrooms[16] = -1;
portal00018148(&g_Vars.currentplayer->cam_pos, &endpos, srcrooms, tmprooms, outrooms, 16);

// cheaper LOS test against props first
const u32 cdtype = CDTYPE_OBJS | CDTYPE_DOORS | CDTYPE_PLAYERS | CDTYPE_CHRS;
const u16 geoflags = GEOFLAG_BLOCK_SIGHT | GEOFLAG_BLOCK_SHOOT;
if (!cdTestAToB(&g_Vars.currentplayer->cam_pos, &endpos, outrooms, cdtype, geoflags, true, 1, 0, 0)) {
return false;
}

// no prop was hit; check for bg hits
struct hitthing hit;
for (s32 i = 0; outrooms[i] != -1; ++i) {
if (bgTestHitInRoom(&g_Vars.currentplayer->cam_pos, &endpos, outrooms[i], &hit)) {
// check if it's far enough away from the end point
if (fabsf(hit.pos.x - endpos.x) >= 0.1f ||
fabsf(hit.pos.y - endpos.y) >= 0.1f ||
fabsf(hit.pos.z - endpos.z) >= 0.1f) {
return false;
}
}
}
struct coord gundir2d;
struct coord gunpos2d = {{ 0.f, 0.f, 0.f }};
struct coord gundir3d;
struct coord gunpos3d = g_Vars.currentplayer->cam_pos;
f32 crosspos[2] = { (f32)xi, (f32)yi };
cam0f0b4c3c(crosspos, &gundir2d, 1.f);
mtx4RotateVec(camGetProjectionMtxF(), &gundir2d, &gundir3d);

// nothing hit
return true;
return shotTestLos(&gunpos2d, &gundir2d, &gunpos3d, &gundir3d, &endpos);
}

#endif
Expand Down Expand Up @@ -380,7 +362,7 @@ void artifactsCalculateGlaresForRoom(s32 roomnum)

if (index < MAX_ARTIFACTS) {
#ifndef PLATFORM_N64
artifact->unk02 = artifactTestLos(&spec, &g_BgRooms[roomnum].pos);
artifact->unk02 = artifactTestLos(&spec, &g_BgRooms[roomnum].pos, xi, yi);
#endif
artifact->unk04 = func0f13c574(f0) >> 2;
artifact->unk08 = &g_ZbufPtr1[viGetWidth() * yi + xi];
Expand Down
5 changes: 5 additions & 0 deletions src/game/lv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,11 @@ Gfx *lvRender(Gfx *gdl)
autoaimTick();
handsTickAttack();

#ifndef PLATFORM_N64
// glares calculated earlier on PC, before prop matrices turn into garbage
bgCalculateGlaresForVisibleRooms();
#endif

// Calculate lookingatprop
if (PLAYERCOUNT() == 1
|| g_Vars.coopplayernum >= 0
Expand Down
111 changes: 111 additions & 0 deletions src/game/prop.c
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,117 @@ struct prop *shotCalculateHits(s32 handnum, bool isshooting, struct coord *gunpo
return result;
}

#ifndef PLATFORM_N64

/**
* Checks if the specified line of sight (gunpos3d - endpos3d) intersects any props or BG,
* using the same process as shotCalculateHits, except with no side effects and cheap = true.
* Returns true if nothing was hit.
*/
bool shotTestLos(struct coord *gunpos2d, struct coord *gundir2d, struct coord *gunpos3d, struct coord *gundir3d, struct coord *endpos3d)
{
struct prop **propptr;
struct hitthing sp664;
struct coord delta;
struct shotdata shotdata;
s32 i;
RoomNum rooms[131];
RoomNum spc8[8];
RoomNum spb8[8];
RoomNum *roomsptr;
struct prop *prop;

shotdata.gunpos3d.x = gunpos3d->x;
shotdata.gunpos3d.y = gunpos3d->y;
shotdata.gunpos3d.z = gunpos3d->z;

shotdata.gunpos2d.x = gunpos2d->x;
shotdata.gunpos2d.y = gunpos2d->y;
shotdata.gunpos2d.z = gunpos2d->z;

shotdata.gundir3d.x = gundir3d->x;
shotdata.gundir3d.y = gundir3d->y;
shotdata.gundir3d.z = gundir3d->z;

shotdata.gundir2d.x = gundir2d->x;
shotdata.gundir2d.y = gundir2d->y;
shotdata.gundir2d.z = gundir2d->z;

// use falcon2 as a dummy weapon
shotdata.gset.weaponnum = WEAPON_FALCON2;
shotdata.gset.weaponfunc = 0;
shotdata.gset.unk063a = 0;
shotdata.gset.unk0639 = 0;

shotdata.penetration = 1;
shotdata.distance = 999999999.f;

for (i = 0; i < ARRAYCOUNT(shotdata.hits); i++) {
shotdata.hits[i].prop = NULL;
shotdata.hits[i].hitpart = 0;
shotdata.hits[i].bboxnode = NULL;
}

rooms[0] = rooms[130] = -1;
spc8[0] = g_Vars.currentplayer->cam_room;
spc8[1] = -1;
portal00018148(&shotdata.gunpos3d, endpos3d, spc8, spb8, rooms, 30);

roomsptr = rooms;

while (*roomsptr != -1) {
roomsptr++;
}

// Note this is being appended to rooms
bgGetForceOnscreenRooms(roomsptr, 100);

// Check for BG hits first
for (i = 0; rooms[i] != -1; i++) {
if (bgTestHitInRoom(&shotdata.gunpos3d, endpos3d, rooms[i], &sp664)) {
// check if it's far enough away from the end point
if (fabsf(sp664.pos.x - endpos3d->x) >= 0.1f ||
fabsf(sp664.pos.y - endpos3d->y) >= 0.1f ||
fabsf(sp664.pos.z - endpos3d->z) >= 0.1f) {
return false;
}
}
}

// didn't hit any bg, shrink distance to the line size
delta.x = endpos3d->x - gunpos3d->x;
delta.y = endpos3d->y - gunpos3d->y;
delta.z = endpos3d->z - gunpos3d->z;
shotdata.distance = sqrtf(delta.x * delta.x + delta.y * delta.y + delta.z * delta.z);

// and check props
propptr = g_Vars.endonscreenprops - 1;
while (propptr >= g_Vars.onscreenprops) {
prop = *propptr;
if (prop) {
if (prop->type == PROPTYPE_CHR
|| (prop->type == PROPTYPE_PLAYER && prop->chr && playermgrGetPlayerNumByProp(prop) != g_Vars.currentplayernum)) {
chrTestHit(prop, &shotdata, false, true);
} else if (prop->type == PROPTYPE_WEAPON || prop->type == PROPTYPE_DOOR
|| (prop->type == PROPTYPE_OBJ && prop->obj->type != OBJTYPE_GLASS && prop->obj->type != OBJTYPE_TINTEDGLASS)) {
objTestHit(prop, &shotdata);
}
if (shotdata.hits[0].prop) {
// ignore some glass parts and shields
if (shotdata.hits[0].slowsbullet && shotdata.hits[0].hitthing.texturenum != 10000) {
return false;
}
}
}
propptr--;
}

// did not hit anything
return true;
}

#endif

struct prop *propFindAimingAt(s32 handnum, bool isshooting, u32 context)
{
struct coord gundir2d;
Expand Down
2 changes: 1 addition & 1 deletion src/game/sky.c
Original file line number Diff line number Diff line change
Expand Up @@ -2518,7 +2518,7 @@ void skyCreateSunArtifact(struct artifact *artifact, s32 x, s32 y)
sunpos.x = env->suns[i].pos[0];
sunpos.y = env->suns[i].pos[1];
sunpos.z = env->suns[i].pos[2];
artifact->unk02 = artifactTestLos(&sunpos, &zero) * 0xfffc;
artifact->unk02 = artifactTestLos(&sunpos, &zero, x, y) * 0xfffc;
#endif
artifact->unk08 = &g_ZbufPtr1[(s32)camGetScreenWidth() * y + x];
artifact->unk0c.u16_2 = x;
Expand Down
3 changes: 3 additions & 0 deletions src/include/game/bg.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,8 @@ s32 bgFindPortalBetweenPositions(struct coord *pos1, struct coord *pos2);
bool bgIsBboxOverlapping(struct coord *arg0, struct coord *arg1, struct coord *arg2, struct coord *arg3);
void bgCalculatePortalBbox(s32 portalnum, struct coord *bbmin, struct coord *bbmax);
void bgFindEnteredRooms(struct coord *bbmin, struct coord *upper, RoomNum *rooms, s32 maxlen, bool arg4);
#ifndef PLATFORM_N64
void bgCalculateGlaresForVisibleRooms(void);
#endif

#endif
2 changes: 1 addition & 1 deletion src/include/game/game_13c510.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Gfx *artifactsConfigureForGlares(Gfx *gdl);
Gfx *artifactsUnconfigureForGlares(Gfx *gdl);
Gfx *artifactsRenderGlaresForRoom(Gfx *gdl, s32 roomnum);
#ifndef PLATFORM_N64
bool artifactTestLos(struct coord *spec, struct coord *roompos);
bool artifactTestLos(struct coord *spec, struct coord *roompos, s32 xi, s32 yi);
#endif

#endif
4 changes: 4 additions & 0 deletions src/include/game/prop.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,8 @@ void propsDefragRoomProps(void);
void propGetBbox(struct prop *prop, f32 *radius, f32 *ymax, f32 *ymin);
bool propUpdateGeometry(struct prop *prop, u8 **start, u8 **end);

#ifndef PLATFORM_N64
bool shotTestLos(struct coord *gunpos2d, struct coord *gundir2d, struct coord *gunpos3d, struct coord *gundir3d, struct coord *endpos3d);
#endif

#endif

0 comments on commit 15c0327

Please sign in to comment.