From 3244bdbd5544e697f4bb9201edbbab2f2542fb8c Mon Sep 17 00:00:00 2001 From: Jeff Harris Date: Sun, 18 Jul 2021 22:27:08 +1200 Subject: [PATCH] Awfully complicated camera collision bits (#54) * Awfully complicated camera collision bits --- src/BRSRC13/CORE/MATH/matrix34.c | 5 +- src/BRSRC13/CORE/V1DB/actsupt.c | 15 +- src/BRSRC13/br_defs.h | 1 + src/BRSRC13/br_types.h | 3 +- src/BRSRC13/brender.h | 2 + src/DETHRACE/common/brucetrk.c | 18 +- src/DETHRACE/common/car.c | 202 +++++++++- src/DETHRACE/common/depth.c | 2 +- src/DETHRACE/common/finteray.c | 648 ++++++++++++++++++++++++++++++- src/DETHRACE/common/init.c | 5 +- src/DETHRACE/common/opponent.c | 4 +- src/DETHRACE/common/raycast.c | 19 +- src/DETHRACE/common/world.c | 3 +- 13 files changed, 887 insertions(+), 40 deletions(-) diff --git a/src/BRSRC13/CORE/MATH/matrix34.c b/src/BRSRC13/CORE/MATH/matrix34.c index f7f5a1c6..701e049b 100644 --- a/src/BRSRC13/CORE/MATH/matrix34.c +++ b/src/BRSRC13/CORE/MATH/matrix34.c @@ -372,7 +372,10 @@ void BrMatrix34TApplyP(br_vector3* A, br_vector3* B, br_matrix34* C) { // IDA: void __cdecl BrMatrix34TApplyV(br_vector3 *A, br_vector3 *B, br_matrix34 *C) void BrMatrix34TApplyV(br_vector3* A, br_vector3* B, br_matrix34* C) { LOG_TRACE("(%p, %p, %p)", A, B, C); - NOT_IMPLEMENTED(); + + A->v[0] = BR_MAC3(B->v[0], C(0, 0), B->v[1], C(0, 1), B->v[2], C(0, 2)); + A->v[1] = BR_MAC3(B->v[0], C(1, 0), B->v[1], C(1, 1), B->v[2], C(1, 2)); + A->v[2] = BR_MAC3(B->v[0], C(2, 0), B->v[1], C(2, 1), B->v[2], C(2, 2)); } // IDA: void __cdecl BrMatrix34Pre(br_matrix34 *mat, br_matrix34 *A) diff --git a/src/BRSRC13/CORE/V1DB/actsupt.c b/src/BRSRC13/CORE/V1DB/actsupt.c index 84d13713..8aeea95f 100644 --- a/src/BRSRC13/CORE/V1DB/actsupt.c +++ b/src/BRSRC13/CORE/V1DB/actsupt.c @@ -89,7 +89,20 @@ br_actor* BrActorAdd(br_actor* parent, br_actor* a) { br_actor* BrActorRemove(br_actor* a) { br_actor* ac; LOG_TRACE("(%p)", a); - NOT_IMPLEMENTED(); + + br_actor* ac2; //Added ? + + BrSimpleRemove((br_simple_node*)a); + a->parent = NULL; + a->depth = 0; + + for (ac2 = a->children; ac2; ac2 = ac2->next) { + ac2->depth = 1; + for (ac = ac2->children; ac; ac = ac->next) { + RenumberActor(ac, 2); + } + } + return a; } // IDA: void __cdecl BrActorRelink(br_actor *parent, br_actor *a) diff --git a/src/BRSRC13/br_defs.h b/src/BRSRC13/br_defs.h index affbb02e..c8ab941f 100644 --- a/src/BRSRC13/br_defs.h +++ b/src/BRSRC13/br_defs.h @@ -33,6 +33,7 @@ #define BR_SIMPLEHEAD(l) (void*)(((br_simple_list*)(l))->head) #define BR_SIMPLENEXT(n) (void*)(((br_simple_node*)(n))->next) #define BR_FOR_SIMPLELIST(list, ptr) for ((ptr) = BR_SIMPLEHEAD(list); (ptr); (ptr) = BR_SIMPLENEXT(ptr)) +#define BR_SIMPLEREMOVE(n) ((void*)BrSimpleRemove((br_simple_node*)(n))) #define V_X 0 #define V_Y 1 diff --git a/src/BRSRC13/br_types.h b/src/BRSRC13/br_types.h index f6e6fbce..68cd9e5e 100644 --- a/src/BRSRC13/br_types.h +++ b/src/BRSRC13/br_types.h @@ -2796,7 +2796,6 @@ typedef struct v11group { void* stored; v11face* faces; br_colour* face_colours; - br_material* face_colours_material; // Jeff added to avoid 64 bit issues trying to pack br_material* into br_colour br_uint_16* face_user; fmt_vertex* vertices; br_colour* vertex_colours; @@ -2804,6 +2803,8 @@ typedef struct v11group { br_uint_16 nfaces; br_uint_16 nvertices; br_uint_16 nedges; + + br_material* face_colours_material; // Added to avoid 64 bit issues trying to pack br_material* into br_colour. eek ;) } v11group; typedef struct v11model { diff --git a/src/BRSRC13/brender.h b/src/BRSRC13/brender.h index 8d88c919..652a715f 100644 --- a/src/BRSRC13/brender.h +++ b/src/BRSRC13/brender.h @@ -60,6 +60,7 @@ void BrMatrix34Identity(br_matrix34* mat); void BrMatrix34Pre(br_matrix34* mat, br_matrix34* A); void BrMatrix34ApplyV(br_vector3* A, br_vector3* B, br_matrix34* C); br_scalar BrMatrix34Inverse(br_matrix34* B, br_matrix34* A); +void BrMatrix34LPInverse(br_matrix34* A, br_matrix34* B); void BrMatrix34ApplyP(br_vector3* A, br_vector3* B, br_matrix34* C); void BrMatrix34Scale(br_matrix34* mat, br_scalar sx, br_scalar sy, br_scalar sz); void BrMatrix34PostTranslate(br_matrix34* mat, br_scalar x, br_scalar y, br_scalar z); @@ -71,6 +72,7 @@ void BrMatrix34PostScale(br_matrix34* mat, br_scalar sx, br_scalar sy, br_scalar void BrMatrix34PreTransform(br_matrix34* mat, br_transform* xform); void BrMatrix34PostTransform(br_matrix34* mat, br_transform* xform); void BrMatrix34PreRotateX(br_matrix34* mat, br_angle rx); +void BrMatrix34TApplyV(br_vector3* A, br_vector3* B, br_matrix34* C); // BrMem void BrMemFree(void* block); diff --git a/src/DETHRACE/common/brucetrk.c b/src/DETHRACE/common/brucetrk.c index 617ca739..3286ded5 100644 --- a/src/DETHRACE/common/brucetrk.c +++ b/src/DETHRACE/common/brucetrk.c @@ -41,7 +41,23 @@ void XZToColumnXZ(tU8* pColumn_x, tU8* pColumn_z, br_scalar pX, br_scalar pZ, tT br_scalar x; br_scalar z; LOG_TRACE("(%p, %p, %f, %f, %p)", pColumn_x, pColumn_z, pX, pZ, pTrack_spec); - NOT_IMPLEMENTED(); + + x = (pX - pTrack_spec->origin_x) / pTrack_spec->column_size_x; + z = (pZ - pTrack_spec->origin_z) / pTrack_spec->column_size_z; + if (x < 0.0) { + x = 0.0; + } + if (pTrack_spec->ncolumns_x <= x) { + x = pTrack_spec->ncolumns_x - 1.0; + } + if (z < 0.0) { + z = 0.0; + } + if (pTrack_spec->ncolumns_z <= z) { + z = pTrack_spec->ncolumns_z - 1.0; + } + *pColumn_x = x; + *pColumn_z = z; } // IDA: void __usercall StripBlendedFaces(br_actor *pActor@, br_model *pModel@) diff --git a/src/DETHRACE/common/car.c b/src/DETHRACE/common/car.c index 665e4671..68d0ae60 100644 --- a/src/DETHRACE/common/car.c +++ b/src/DETHRACE/common/car.c @@ -1988,8 +1988,196 @@ int CollideCamera2(br_vector3* car_pos, br_vector3* cam_pos, br_vector3* old_cam tFace_ref face_list[3]; LOG_TRACE("(%p, %p, %p, %d)", car_pos, cam_pos, old_camera_pos, manual_move); - SILENT_STUB(); - return 0; + hither = ((br_camera*)gCamera->type_data)->hither_z * 3.0; + gCamera_has_collided = 0; + for (i = 0; i < 1; i++) { + tv.v[0] = cam_pos->v[0] - car_pos->v[0]; + tv.v[1] = cam_pos->v[1] - car_pos->v[1]; + tv.v[2] = cam_pos->v[2] - car_pos->v[2]; + dist = sqrt(tv.v[1] * tv.v[1] + tv.v[2] * tv.v[2] + tv.v[0] * tv.v[0]); + tv.v[0] = tv.v[0] * 1.2; + tv.v[1] = tv.v[1] * 1.2; + tv.v[2] = tv.v[2] * 1.2; + FindFace(car_pos, &tv, &a, &ts, &material); + if (ts <= 1.0) { + gCamera_has_collided = 1; + if (a.v[1] * tv.v[1] + a.v[2] * tv.v[2] + a.v[0] * tv.v[0] > 0.0) { + a.v[0] = -a.v[0]; + a.v[1] = -a.v[1]; + a.v[2] = -a.v[2]; + } + if (gCamera_mode == 1 && !manual_move) { + tv2.v[0] = car_pos->v[0] - old_camera_pos->v[0]; + tv2.v[1] = car_pos->v[1] - old_camera_pos->v[1]; + tv2.v[2] = car_pos->v[2] - old_camera_pos->v[2]; + FindFace(old_camera_pos, &tv2, &b, &ts2, &material); + if (ts2 > 1.0) { + *cam_pos = *old_camera_pos; + return i; + } + } + tv.v[0] = tv.v[0] * ts; + tv.v[1] = tv.v[1] * ts; + tv.v[2] = tv.v[2] * ts; + tv2.v[0] = a.v[0] * hither; + tv2.v[1] = a.v[1] * hither; + tv2.v[2] = a.v[2] * hither; + tv.v[0] = tv2.v[0] + tv.v[0]; + tv.v[1] = tv2.v[1] + tv.v[1]; + tv.v[2] = tv2.v[2] + tv.v[2]; + dist = sqrt(tv.v[1] * tv.v[1] + tv.v[2] * tv.v[2] + tv.v[0] * tv.v[0]); + cam_pos->v[0] = car_pos->v[0] + tv.v[0]; + cam_pos->v[1] = car_pos->v[1] + tv.v[1]; + cam_pos->v[2] = car_pos->v[2] + tv.v[2]; + if (gMin_camera_car_distance > dist && !i && a.v[1] > -0.7) { + tv2.v[0] = -a.v[1] * a.v[0]; + tv2.v[1] = -a.v[1] * a.v[1]; + tv2.v[2] = -a.v[1] * a.v[2]; + tv2.v[1] = tv2.v[1] + 1.0; + if (gProgram_state.current_car.car_master_actor->t.t.mat.m[1][1] < 0.0) { + tv2.v[0] = -tv2.v[0]; + tv2.v[1] = -tv2.v[1]; + tv2.v[2] = -tv2.v[2]; + } + d = tv2.v[1] * tv2.v[1] + tv2.v[2] * tv2.v[2] + tv2.v[0] * tv2.v[0]; + l = tv2.v[1] * tv.v[1] + tv2.v[2] * tv.v[2] + tv2.v[0] * tv.v[0]; + alpha = tv.v[1] * tv.v[1] + + tv.v[2] * tv.v[2] + + tv.v[0] * tv.v[0] + - gMin_camera_car_distance * gMin_camera_car_distance; + ts2 = l * l - alpha * d * 4.0; + if (alpha >= 0 && d != 0.0) { + sa = (sqrt(ts2) - l) / (d * 2.0); + tv2.v[0] = tv2.v[0] * sa; + tv2.v[1] = tv2.v[1] * sa; + tv2.v[2] = tv2.v[2] * sa; + FindFace(cam_pos, &tv2, &a, &ts, &material); + if (ts < 1.0) { + tv2.v[0] = tv2.v[0] * ts; + tv2.v[1] = tv2.v[1] * ts; + tv2.v[2] = tv2.v[2] * ts; + } + b.v[0] = tv.v[0]; + b.v[1] = 0.0; + b.v[2] = tv.v[2]; + dist = sqrt(0.0 * 0.0 + tv.v[2] * tv.v[2] + tv.v[0] * tv.v[0]); + if (alpha <= 2.3841858e-7) { + b.v[0] = 1.0; + b.v[1] = 0.0; + b.v[2] = 0.0; + } else { + alpha = 1.0 / dist; + b.v[0] = b.v[0] * alpha; + b.v[1] = b.v[1] * alpha; + b.v[2] = b.v[2] * alpha; + } + tv.v[0] = tv2.v[0] + tv.v[0]; + tv.v[1] = tv2.v[1] + tv.v[1]; + tv.v[2] = tv2.v[2] + tv.v[2]; + ts2 = tv.v[1] * b.v[1] + tv.v[2] * b.v[2] + b.v[0] * tv.v[0]; + if (ts2 < 0.029999999 && !gAction_replay_mode) { + dist = sqrt(tv2.v[1] * tv2.v[1] + tv2.v[2] * tv2.v[2] + tv2.v[0] * tv2.v[0]); + if (dist <= 2.3841858e-7) { + tv2.v[0] = 1.0; + tv2.v[1] = 0.0; + tv2.v[2] = 0.0; + } else { + alpha = 1.0 / dist; + tv2.v[0] = tv2.v[0] * alpha; + tv2.v[1] = tv2.v[1] * alpha; + tv2.v[2] = tv2.v[2] * alpha; + } + if (tv2.v[2] * b.v[2] + tv2.v[0] * b.v[0] + tv2.v[1] * b.v[1] < -0.029999999) + alpha = tv2.v[1] * b.v[1] + tv2.v[2] * b.v[2] + b.v[0] * tv2.v[0]; + alpha = (0.029999999 - ts2) / alpha; + tv2.v[0] = tv2.v[0] * alpha; + tv2.v[1] = tv2.v[1] * alpha; + tv2.v[2] = tv2.v[2] * alpha; + tv.v[0] = tv2.v[0] + tv.v[0]; + tv.v[1] = tv2.v[1] + tv.v[1]; + tv.v[2] = tv2.v[2] + tv.v[2]; + } + } + } + cam_pos->v[0] = car_pos->v[0] + tv.v[0]; + cam_pos->v[1] = car_pos->v[1] + tv.v[1]; + cam_pos->v[2] = car_pos->v[2] + tv.v[2]; + } + + bnds.mat = &mat; + BrMatrix34Identity(&mat); + tv2.v[0] = hither; + tv2.v[1] = hither; + tv2.v[2] = hither; + bnds.original_bounds.min.v[0] = cam_pos->v[0] - hither; + bnds.original_bounds.min.v[1] = cam_pos->v[1] - hither; + bnds.original_bounds.min.v[2] = cam_pos->v[2] - hither; + bnds.original_bounds.max.v[0] = cam_pos->v[0] + hither; + bnds.original_bounds.max.v[1] = cam_pos->v[1] + hither; + bnds.original_bounds.max.v[2] = cam_pos->v[2] + hither; + k = FindFacesInBox(&bnds, face_list, 3); + if (k > 0) { + tv2.v[0] = cam_pos->v[0] - face_list[0].v[0].v[0]; + tv2.v[1] = cam_pos->v[1] - face_list[0].v[0].v[1]; + tv2.v[2] = cam_pos->v[2] - face_list[0].v[0].v[2]; + sa = face_list[0].normal.v[2] * tv2.v[2] + + face_list[0].normal.v[1] * tv2.v[1] + + face_list[0].normal.v[0] * tv2.v[0]; + //ts2 = sa; + if (sa < hither && sa >= 0.0) { + tv2.v[0] = (hither - sa) * face_list[0].normal.v[0]; + tv2.v[1] = (hither - sa) * face_list[0].normal.v[1]; + tv2.v[2] = (hither - sa) * face_list[0].normal.v[2]; + cam_pos->v[0] = cam_pos->v[0] + tv2.v[0]; + cam_pos->v[1] = cam_pos->v[1] + tv2.v[1]; + cam_pos->v[2] = cam_pos->v[2] + tv2.v[2]; + } + if (k > 1) { + sb = face_list[1].normal.v[2] * face_list[0].normal.v[2] + + face_list[1].normal.v[1] * face_list[0].normal.v[1] + + face_list[1].normal.v[0] * face_list[0].normal.v[0]; + if (sb > 0.94999999 && k > 2) { + face_list[1].normal.v[0] = face_list[2].normal.v[0]; + face_list[1].normal.v[1] = face_list[2].normal.v[1]; + face_list[1].normal.v[2] = face_list[2].normal.v[2]; + face_list[1].v[0].v[0] = face_list[2].v[0].v[0]; + face_list[1].v[0].v[1] = face_list[2].v[0].v[1]; + face_list[1].v[0].v[2] = face_list[2].v[0].v[2]; + sb = face_list[2].normal.v[2] * face_list[0].normal.v[2] + + face_list[2].normal.v[1] * face_list[0].normal.v[1] + + face_list[2].normal.v[0] * face_list[0].normal.v[0]; + k = 2; + } + if (sb <= 0.94999999) { + tv2.v[0] = cam_pos->v[0] - face_list[1].v[0].v[0]; + tv2.v[1] = cam_pos->v[1] - face_list[1].v[0].v[1]; + tv2.v[2] = cam_pos->v[2] - face_list[1].v[0].v[2]; + sc = face_list[1].normal.v[2] * tv2.v[2] + + face_list[1].normal.v[1] * tv2.v[1] + + face_list[1].normal.v[0] * tv2.v[0]; + if (sc < hither && sc >= 0.0) { + sc = face_list[1].normal.v[2] * face_list[0].normal.v[2] + + face_list[1].normal.v[1] * face_list[0].normal.v[1] + + face_list[1].normal.v[0] * face_list[0].normal.v[0]; + b.v[0] = face_list[0].normal.v[0] * sc; + b.v[1] = face_list[0].normal.v[1] * sc; + b.v[2] = face_list[0].normal.v[2] * sc; + face_list[1].normal.v[0] = face_list[1].normal.v[0] - b.v[0]; + face_list[1].normal.v[1] = face_list[1].normal.v[1] - b.v[1]; + face_list[1].normal.v[2] = face_list[1].normal.v[2] - b.v[2]; + tv2.v[0] = (hither - ts2) * face_list[1].normal.v[0]; + tv2.v[1] = (hither - ts2) * face_list[1].normal.v[1]; + tv2.v[2] = (hither - ts2) * face_list[1].normal.v[2]; + cam_pos->v[0] = cam_pos->v[0] + tv2.v[0]; + cam_pos->v[1] = cam_pos->v[1] + tv2.v[1]; + cam_pos->v[2] = cam_pos->v[2] + tv2.v[2]; + } + } + } + } + i += k; + } + return i; } // IDA: int __usercall BoundsTest@(br_bounds *bnds@, br_vector3 *p@) @@ -2449,7 +2637,11 @@ int TestOldMats(tCollision_info* c1, tCollision_info* c2, int newmats) { // IDA: int __usercall PullActorFromWorld@(br_actor *pActor@) int PullActorFromWorld(br_actor* pActor) { LOG_TRACE("(%p)", pActor); - NOT_IMPLEMENTED(); + + if (gDoing_physics) { + return DoPullActorFromWorld(pActor); + } + return 0; } // IDA: int __usercall DoPullActorFromWorld@(br_actor *pActor@) @@ -2459,7 +2651,9 @@ int DoPullActorFromWorld(br_actor* pActor) { tCollision_info* c; tNon_car_spec* non_car; LOG_TRACE("(%p)", pActor); - NOT_IMPLEMENTED(); + + STUB(); + return 0; } // IDA: void __usercall CheckForDeAttachmentOfNonCars(tU32 pTime@) diff --git a/src/DETHRACE/common/depth.c b/src/DETHRACE/common/depth.c index da78a463..5a6d1212 100644 --- a/src/DETHRACE/common/depth.c +++ b/src/DETHRACE/common/depth.c @@ -245,7 +245,7 @@ void ExternalSky(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer, br_act int repetitions; br_pixelmap* col_map; LOG_TRACE("(%p, %p, %p, %p)", pRender_buffer, pDepth_buffer, pCamera, pCamera_to_world); - + return; dx = 0; col_map = gHorizon_material->colour_map; camera = (br_camera*)pCamera->type_data; diff --git a/src/DETHRACE/common/finteray.c b/src/DETHRACE/common/finteray.c index 8b61b816..42ff3a04 100644 --- a/src/DETHRACE/common/finteray.c +++ b/src/DETHRACE/common/finteray.c @@ -1,6 +1,9 @@ #include "finteray.h" #include "brender.h" +#include "brucetrk.h" +#include "car.h" #include "globvars.h" +#include "world.h" #include br_matrix34 gPick_model_to_view; @@ -39,6 +42,56 @@ int PickBoundsTestRay_finteray(br_bounds* b, br_vector3* rp, br_vector3* rd, br_ float s; float t; LOG_TRACE("(%p, %p, %p, %f, %f, %p, %p)", b, rp, rd, t_near, t_far, new_t_near, new_t_far); + + for (i = 0; i < 3; i++) { + if (rd->v[i] >= -0.00000023841858) { + if (rd->v[i] <= 0.00000023841858) { + if (b->max.v[i] < rp->v[i] || rp->v[i] < b->min.v[i]) { + return 0; + } + } else { + s = (-1.0f / rd->v[i]) * (rp->v[i] - b->max.v[i]); + if (s >= BR_SCALAR_MIN) { + if (s < t_far) { + t_far = (-1.0f / rd->v[i]) * (rp->v[i] - b->max.v[i]); + } + } else { + t_far = BR_SCALAR_MIN; + } + t = (-1.0f / rd->v[i]) * (rp->v[i] - b->min.v[i]); + if (t <= BR_SCALAR_MAX) { + if (t > t_near) { + t_near = (-1.0f / rd->v[i]) * (rp->v[i] - b->min.v[i]); + } + } else { + t_near = BR_SCALAR_MAX; + } + } + } else { + s = (-1.0f / rd->v[i]) * (rp->v[i] - b->max.v[i]); + if (s <= BR_SCALAR_MAX) { + if (s > t_near) { + t_near = (-1.0f / rd->v[i]) * (rp->v[i] - b->max.v[i]); + } + } else { + t_near = BR_SCALAR_MAX; + } + t = (-1.0f / rd->v[i]) * (rp->v[i] - b->min.v[i]); + if (t >= BR_SCALAR_MIN) { + if (t < t_far) { + t_far = (-1.0f / rd->v[i]) * (rp->v[i] - b->min.v[i]); + } + } else { + t_far = BR_SCALAR_MIN; + } + } + } + if (t_far < t_near) { + return 0; + } + *new_t_near = t_near; + *new_t_far = t_far; + return 1; } // IDA: int __usercall ActorRayPick2D@(br_actor *ap@, br_vector3 *pPosition@, br_vector3 *pDir@, br_model *model@, br_material *material, dr_pick2d_cbfn *callback) @@ -55,13 +108,74 @@ int ActorRayPick2D(br_actor* ap, br_vector3* pPosition, br_vector3* pDir, br_mod br_vector3 dir; void* arg; LOG_TRACE("(%p, %p, %p, %p, %p, %p)", ap, pPosition, pDir, model, material, callback); - NOT_IMPLEMENTED(); + + t_near = 0.0; + t_far = 1.0; + r = 0; + arg = NULL; + if (ap->model) { + this_model = ap->model; + } else { + this_model = model; + } + if (ap->material) { + this_material = ap->material; + } else { + this_material = material; + } + if (ap->render_style == 1) { + return 0; + } + if (ap->identifier && *ap->identifier == '&') { + BrTransformToMatrix34(&mat, &ap->t); + BrMatrix34Inverse(&invmat, &mat); + BrMatrix34ApplyP(&pos, pPosition, &invmat); + BrMatrix34ApplyV(&dir, pDir, &invmat); + pPosition = &pos; + pDir = &dir; + } + if (ap->type == BR_ACTOR_MODEL) { + if (PickBoundsTestRay_finteray(&this_model->bounds, pPosition, pDir, t_near, t_far, &t_near, &t_far)) { + t_near = 0.0; + if (gNearest_T >= 1.0) { + t_far = 1.0; + } else { + t_far = gNearest_T; + } + r = callback(ap, this_model, this_material, pPosition, pDir, t_near, t_far, arg); + if (r) { + return r; + } + } + if (r) { + return r; + } + } else if (ap->type >= BR_ACTOR_BOUNDS && ap->type <= BR_ACTOR_BOUNDS_CORRECT) { + if (PickBoundsTestRay_finteray((br_bounds*)ap->type_data, pPosition, pDir, t_near, t_far, &t_near, &t_far)) { + for (a = ap->children; a; a = a->next) { + r = ActorRayPick2D(a, pPosition, pDir, this_model, this_material, callback); + if (r) { + break; + } + } + } + return r; + } + for (a = ap->children; a; a = a->next) { + r = ActorRayPick2D(a, pPosition, pDir, this_model, this_material, callback); + if (r) { + break; + } + } + return r; } // IDA: int __usercall DRSceneRayPick2D@(br_actor *world@, br_vector3 *pPosition@, br_vector3 *pDir@, dr_pick2d_cbfn *callback@) int DRSceneRayPick2D(br_actor* world, br_vector3* pPosition, br_vector3* pDir, dr_pick2d_cbfn* callback) { LOG_TRACE("(%p, %p, %p, %p)", world, pPosition, pDir, callback); - NOT_IMPLEMENTED(); + + BrMatrix34Inverse(&gPick_model_to_view, &world->t.t.mat); + return ActorRayPick2D(world, pPosition, pDir, NULL, NULL, callback); } // Offset: 1544 @@ -100,7 +214,129 @@ int DRModelPick2D_finteray(br_model* model, br_material* material, br_vector3* r float f_numerator; int group; LOG_TRACE("(%p, %p, %p, %p, %f, %f, %p, %p)", model, material, ray_pos, ray_dir, t_near, t_far, callback, arg); - NOT_IMPLEMENTED(); + + t_near -= 0.0000099999997; + t_far += 0.0000099999997; + for (group = 0; group < V11MODEL(model)->ngroups; group++) { + for (f = 0; f < V11MODEL(model)->groups[group].nfaces; f++) { + fp = &V11MODEL(model)->groups[group].faces[f]; + if (V11MODEL(model)->groups[group].face_colours_material) { + this_material = V11MODEL(model)->groups[group].face_colours_material; + } else { + this_material = material; + } + d = fp->eqn.v[1] * ray_dir->v[1] + fp->eqn.v[2] * ray_dir->v[2] + fp->eqn.v[0] * ray_dir->v[0]; + if (fabs(d) >= 0.00000023841858 && (!this_material || !this_material->identifier || *this_material->identifier != '!' || !gPling_materials) + && (!this_material || (this_material->flags & 0x1800) != 0 || d <= 0.0)) { + numerator = fp->eqn.v[1] * ray_pos->v[1] + + fp->eqn.v[2] * ray_pos->v[2] + + fp->eqn.v[0] * ray_pos->v[0] + - fp->eqn.v[3]; + if (!BadDiv_finteray(numerator, d)) { + t = -(numerator / d); + if (t >= t_near && t <= t_far) { + p.v[0] = ray_dir->v[0] * t; + p.v[1] = ray_dir->v[1] * t; + p.v[2] = ray_dir->v[2] * t; + p.v[0] = ray_pos->v[0] + p.v[0]; + p.v[1] = ray_pos->v[1] + p.v[1]; + p.v[2] = ray_pos->v[2] + p.v[2]; + axis_m = fabs(fp->eqn.v[0]) < fabs(fp->eqn.v[1]); + if (fabs(fp->eqn.v[2]) > fabs(fp->eqn.v[axis_m])) { + axis_m = 2; + } + if (axis_m) { + axis_0 = 0; + if (axis_m == 1) { + axis_1 = 2; + } else { + axis_1 = 1; + } + } else { + axis_0 = 1; + axis_1 = 2; + } + + v0 = V11MODEL(model)->groups[group].vertices[fp->vertices[0]].p.v[axis_0]; + u0 = V11MODEL(model)->groups[group].vertices[fp->vertices[0]].p.v[axis_1]; + v1 = V11MODEL(model)->groups[group].vertices[fp->vertices[1]].p.v[axis_0] - v0; + u1 = V11MODEL(model)->groups[group].vertices[fp->vertices[1]].p.v[axis_1] - u0; + v2 = V11MODEL(model)->groups[group].vertices[fp->vertices[2]].p.v[axis_0] - v0; + u2 = V11MODEL(model)->groups[group].vertices[fp->vertices[2]].p.v[axis_1] - u0; + + v0i1 = p.v[axis_0] - v0; + v0i2 = p.v[axis_1] - u0; + if (fabs(v1) > 0.0000002384185791015625) { + f_n = u2 * v1 - u1 * v2; + f_d = v0i2 * v1 - u1 * v0i1; + if (fabs(f_n) < fabs(f_d)) { + continue; + } + if (f_n == 0) { + continue; + } + beta = f_d / f_n; + if (beta < 0.0 || beta > 1.0 || v1 == 0.0) { + continue; + } + alpha = (v0i1 - beta * v2) / v1; + } else { + if (fabs(v2) < fabs(v0i1)) { + continue; + } + if (v2 == 0) { + continue; + } + + beta = v0i1 / v2; + if (beta < 0.0 || beta > 1.0 || u1 == 0.0) { + continue; + } + alpha = (v0i2 - beta * u2) / u1; + } + + if (alpha >= 0.0 && beta + alpha <= 1.0) { + s_alpha = alpha; + s_beta = beta; + map.v[0] = V11MODEL(model)->groups[group].vertices[fp->vertices[1]].map.v[0] * s_alpha; + map.v[1] = V11MODEL(model)->groups[group].vertices[fp->vertices[1]].map.v[1] * s_alpha; + DRVector2AccumulateScale_finteray( + &map, + &V11MODEL(model)->groups[group].vertices[fp->vertices[2]].map, + s_beta); + DRVector2AccumulateScale_finteray( + &map, + &V11MODEL(model)->groups[group].vertices[fp->vertices[0]].map, + 1.0 - (s_alpha + s_beta)); + v = 0; + e = 1; + if (s_alpha <= s_beta) { + if (0.5 - s_beta / 2.0 > s_alpha) { + e = 0; + } + if (1.0 - s_beta * 2.0 < s_alpha) { + v = 1; + } + } else { + if (1.0 - s_beta * 2.0 > s_alpha) { + e = 2; + } + if (0.5 - s_beta / 2.0 < s_alpha) { + v = 2; + } + } + gTemp_group = group; + r = callback(model, this_material, ray_pos, ray_dir, t, f, e, v, &p, &map, arg); + if (r) { + return r; + } + } + } + } + } + } + } + return 0; } // IDA: int __cdecl FindHighestPolyCallBack(br_model *pModel, br_material *pMaterial, br_vector3 *pRay_pos, br_vector3 *pRay_dir, br_scalar pT, int pF, int pE, int pV, br_vector3 *pPoint, br_vector2 *pMap, void *pArg) @@ -131,7 +367,17 @@ int FindHighestCallBack_finteray(br_actor* pActor, br_model* pModel, br_material void FindFace(br_vector3* pPosition, br_vector3* pDir, br_vector3* nor, br_scalar* t, br_material** material) { int group; LOG_TRACE("(%p, %p, %p, %p, %p)", pPosition, pDir, nor, t, material); - NOT_IMPLEMENTED(); + + gNearest_T = 100.0; + DRSceneRayPick2D(gTrack_actor, pPosition, pDir, FindHighestCallBack_finteray); + *t = gNearest_T; + if (*t < 100.0) { + group = gNearest_face_group; + nor->v[0] = V11MODEL(gNearest_model)->groups[gNearest_face_group].faces[gNearest_face].eqn.v[0]; + nor->v[1] = V11MODEL(gNearest_model)->groups[group].faces[gNearest_face].eqn.v[1]; + nor->v[2] = V11MODEL(gNearest_model)->groups[group].faces[gNearest_face].eqn.v[2]; + *material = V11MODEL(gNearest_model)->groups[group].face_colours_material; + } } // IDA: void __cdecl EnablePlingMaterials() @@ -249,7 +495,68 @@ int FindFacesInBox(tBounds* bnds, tFace_ref* face_list, int max_face) { tU8 cz_max; tTrack_spec* track_spec; LOG_TRACE("(%p, %p, %d)", bnds, face_list, max_face); - NOT_IMPLEMENTED(); + + j = 0; + track_spec = &gProgram_state.track_spec; + a.v[0] = bnds->original_bounds.min.v[0] + bnds->original_bounds.max.v[0]; + a.v[1] = bnds->original_bounds.min.v[1] + bnds->original_bounds.max.v[1]; + a.v[2] = bnds->original_bounds.min.v[2] + bnds->original_bounds.max.v[2]; + b.v[0] = a.v[0] * 0.5; + b.v[1] = a.v[1] * 0.5; + b.v[2] = a.v[2] * 0.5; + BrMatrix34ApplyP(&bnds->box_centre, &b, bnds->mat); + b.v[0] = bnds->original_bounds.max.v[0] - bnds->original_bounds.min.v[0]; + b.v[1] = bnds->original_bounds.max.v[1] - bnds->original_bounds.min.v[1]; + b.v[2] = bnds->original_bounds.max.v[2] - bnds->original_bounds.min.v[2]; + bnds->radius = sqrt(b.v[1] * b.v[1] + b.v[2] * b.v[2] + b.v[0] * b.v[0]) / 2.0; + BrMatrix34ApplyP(&bnds->real_bounds.min, &bnds->original_bounds.min, bnds->mat); + bnds->real_bounds.max = bnds->real_bounds.min; + for (i = 0; i < 3; ++i) { + c[i].v[0] = bnds->mat->m[i][0] * b.v[i]; + c[i].v[1] = bnds->mat->m[i][1] * b.v[i]; + c[i].v[2] = bnds->mat->m[i][2] * b.v[i]; + } + for (i = 0; i < 3; ++i) { + bnds->real_bounds.min.v[i] = (double)(c[2].v[i] < 0.0) * c[2].v[i] + + (double)(c[1].v[i] < 0.0) * c[1].v[i] + + (double)(c[0].v[i] < 0.0) * c[0].v[i] + + bnds->real_bounds.min.v[i]; + bnds->real_bounds.max.v[i] = (double)(c[2].v[i] > 0.0) * c[2].v[i] + + (double)(c[1].v[i] > 0.0) * c[1].v[i] + + (double)(c[0].v[i] > 0.0) * c[0].v[i] + + bnds->real_bounds.max.v[i]; + } + XZToColumnXZ(&cx_min, &cz_min, bnds->real_bounds.min.v[0], bnds->real_bounds.min.v[2], track_spec); + XZToColumnXZ(&cx_max, &cz_max, bnds->real_bounds.max.v[0], bnds->real_bounds.max.v[2], track_spec); + if (cx_min) { + cx_min--; + } + if (cz_min) { + cz_min--; + } + if (track_spec->ncolumns_x > cx_max + 1) { + cx_max++; + } + if (track_spec->ncolumns_z > cz_max + 1) { + cz_max++; + } + for (x = cx_min; cx_max >= x; ++x) { + for (z = cz_min; cz_max >= z; ++z) { + if (track_spec->columns[z][x]) { + if (track_spec->blends[z][x]) { + track_spec->blends[z][x]->render_style = BR_RSTYLE_FACES; + } + j = max_face - ActorBoxPick(bnds, track_spec->columns[z][x], NULL, NULL, &face_list[j], max_face - j, 0); + if (track_spec->blends[z][x]) { + track_spec->blends[z][x]->render_style = BR_RSTYLE_NONE; + } + } + if (track_spec->lollipops[z][x]) { + j = max_face - ActorBoxPick(bnds, track_spec->lollipops[z][x], NULL, NULL, &face_list[j], max_face - j, 0); + } + } + } + return j; } // IDA: int __usercall FindFacesInBox2@(tBounds *bnds@, tFace_ref *face_list@, int max_face@) @@ -279,7 +586,77 @@ int ActorBoxPick(tBounds* bnds, br_actor* ap, br_model* model, br_material* mate tBounds new_bounds; br_bounds br_bnds; LOG_TRACE("(%p, %p, %p, %p, %p, %d, %p)", bnds, ap, model, material, face_list, max_face, pMat); - NOT_IMPLEMENTED(); + + i = 0; + test_children = 1; + if (ap->model) { + this_model = ap->model; + } else { + this_model = model; + } + if (ap->material) { + this_material = ap->material; + } else { + this_material = material; + } + if (ap->render_style == 1) { + return max_face; + } + if (ap->identifier && *ap->identifier == '&') { + if (!ap->children + && (ap->type != BR_ACTOR_MODEL || !BoundsTransformTest(&this_model->bounds, &bnds->real_bounds, &ap->t.t.mat))) { + return max_face; + } + if (pMat) { + BrMatrix34Mul(&mat, &ap->t.t.mat, pMat); + pMat = &mat; + } else { + pMat = &ap->t.t.mat; + } + BrMatrix34LPInverse(&invmat, &ap->t.t.mat); + BrMatrix34Mul(&mat2, bnds->mat, &invmat); + new_bounds.mat = &mat2; + new_bounds.original_bounds = bnds->original_bounds; + BrMatrix34ApplyP(&new_bounds.box_centre, &bnds->box_centre, &invmat); + new_bounds.radius = bnds->radius; + GetNewBoundingBox(&new_bounds.real_bounds, &new_bounds.original_bounds, new_bounds.mat); + if (ap->identifier[1] >= '0' && ap->identifier[1] <= '9') { + if (!BoundsOverlapTest_finteray(&new_bounds.real_bounds, &this_model->bounds)) { + return max_face; + } + BrMatrix34LPInverse(&invmat, bnds->mat); + BrMatrix34Mul(&box_to_actor, &ap->t.t.mat, &invmat); + GetNewBoundingBox(&br_bnds, &ap->model->bounds, &box_to_actor); + if (!BoundsOverlapTest_finteray(&br_bnds, &bnds->original_bounds)) { + return max_face; + } + if (PullActorFromWorld(ap)) { + return max_face; + } + } + bnds = &new_bounds; + } + if (ap->type == BR_ACTOR_MODEL) { + if (BoundsOverlapTest_finteray(&bnds->real_bounds, &this_model->bounds)) { + n = ModelPickBox(ap, bnds, this_model, this_material, &face_list[i], max_face, pMat); + if (pMat && max_face != n) { + StopGroovidelic(ap); + } + i += max_face - n; + max_face = n; + } + } else if (ap->type >= 5u && ap->type <= 6u) { + test_children = BoundsOverlapTest_finteray(&bnds->real_bounds, (br_bounds*)ap->type_data); + } + if (test_children) { + for (a = ap->children; a; a = next_a) { + next_a = a->next; + n = ActorBoxPick(bnds, a, this_model, this_material, &face_list[i], max_face, pMat); + i += max_face - n; + max_face = n; + } + } + return max_face; } // IDA: int __usercall ModelPickBox@(br_actor *actor@, tBounds *bnds@, br_model *model@, br_material *model_material@, tFace_ref *face_list, int max_face, br_matrix34 *pMat) @@ -298,7 +675,145 @@ int ModelPickBox(br_actor* actor, tBounds* bnds, br_model* model, br_material* m br_scalar t; v11model* prepared; LOG_TRACE("(%p, %p, %p, %p, %p, %d, %p)", actor, bnds, model, model_material, face_list, max_face, pMat); - NOT_IMPLEMENTED(); + + prepared = model->prepared; + if (max_face <= 0) { + return 0; + } + for (group = 0; prepared->ngroups > group; group++) { + fp = prepared->groups[group].faces; + for (f = 0; f < prepared->groups[group].nfaces; f++) { + v1 = fp->vertices[0]; + a.v[0] = prepared->groups[group].vertices[v1].p.v[0] - bnds->box_centre.v[0]; + a.v[1] = prepared->groups[group].vertices[v1].p.v[1] - bnds->box_centre.v[1]; + a.v[2] = prepared->groups[group].vertices[v1].p.v[2] - bnds->box_centre.v[2]; + t = fp->eqn.v[1] * a.v[1] + fp->eqn.v[2] * a.v[2] + fp->eqn.v[0] * a.v[0]; + if (fabs(t) <= bnds->radius) { + v2 = fp->vertices[1]; + v3 = fp->vertices[2]; + t = bnds->real_bounds.min.v[0]; + if (prepared->groups[group].vertices[v1].p.v[0] >= (double)t + || prepared->groups[group].vertices[v2].p.v[0] >= (double)t + || prepared->groups[group].vertices[v3].p.v[0] >= (double)t) { + t = bnds->real_bounds.max.v[0]; + if (prepared->groups[group].vertices[v1].p.v[0] <= (double)t + || prepared->groups[group].vertices[v2].p.v[0] <= (double)t + || prepared->groups[group].vertices[v3].p.v[0] <= (double)t) { + t = bnds->real_bounds.min.v[1]; + if (prepared->groups[group].vertices[v1].p.v[1] >= (double)t + || prepared->groups[group].vertices[v2].p.v[1] >= (double)t + || prepared->groups[group].vertices[v3].p.v[1] >= (double)t) { + t = bnds->real_bounds.max.v[1]; + if (prepared->groups[group].vertices[v1].p.v[1] <= (double)t + || prepared->groups[group].vertices[v2].p.v[1] <= (double)t + || prepared->groups[group].vertices[v3].p.v[1] <= (double)t) { + t = bnds->real_bounds.min.v[2]; + if (prepared->groups[group].vertices[v1].p.v[2] >= (double)t + || prepared->groups[group].vertices[v2].p.v[2] >= (double)t + || prepared->groups[group].vertices[v3].p.v[2] >= (double)t) { + t = bnds->real_bounds.max.v[2]; + if (prepared->groups[group].vertices[v1].p.v[2] <= (double)t + || prepared->groups[group].vertices[v2].p.v[2] <= (double)t + || prepared->groups[group].vertices[v3].p.v[2] <= (double)t) { + polygon[1].v[0] = prepared->groups[group].vertices[v1].p.v[0] + - bnds->mat->m[3][0]; + polygon[1].v[1] = prepared->groups[group].vertices[v1].p.v[1] + - bnds->mat->m[3][1]; + polygon[1].v[2] = prepared->groups[group].vertices[v1].p.v[2] + - bnds->mat->m[3][2]; + polygon[2].v[0] = prepared->groups[group].vertices[v2].p.v[0] + - bnds->mat->m[3][0]; + polygon[2].v[1] = prepared->groups[group].vertices[v2].p.v[1] + - bnds->mat->m[3][1]; + polygon[2].v[2] = prepared->groups[group].vertices[v2].p.v[2] + - bnds->mat->m[3][2]; + polygon[3].v[0] = prepared->groups[group].vertices[v3].p.v[0] + - bnds->mat->m[3][0]; + polygon[3].v[1] = prepared->groups[group].vertices[v3].p.v[1] + - bnds->mat->m[3][1]; + polygon[3].v[2] = prepared->groups[group].vertices[v3].p.v[2] + - bnds->mat->m[3][2]; + BrMatrix34TApplyV(polygon, &polygon[1], bnds->mat); + BrMatrix34TApplyV(&polygon[1], &polygon[2], bnds->mat); + BrMatrix34TApplyV(&polygon[2], &polygon[3], bnds->mat); + n = 3; + for (i = 0; i < 3; i++) { + ClipToPlaneGE(polygon, &n, i, bnds->original_bounds.min.v[i]); + if (n < 3) { + break; + } + ClipToPlaneLE(polygon, &n, i, bnds->original_bounds.max.v[i]); + if (n < 3) { + break; + } + } + if (n >= 3) { + if (pMat) { + BrMatrix34ApplyP(&face_list->v[0], &prepared->groups[group].vertices[v1].p, pMat); + BrMatrix34ApplyP(&face_list->v[1], &prepared->groups[group].vertices[v2].p, pMat); + BrMatrix34ApplyP(&face_list->v[2], &prepared->groups[group].vertices[v3].p, pMat); + tv.v[0] = fp->eqn.v[0]; + tv.v[1] = fp->eqn.v[1]; + tv.v[2] = fp->eqn.v[2]; + BrMatrix34ApplyV(&face_list->normal, &tv, pMat); + } else { + face_list->v[0].v[0] = prepared->groups[group].vertices[v1].p.v[0]; + face_list->v[0].v[1] = prepared->groups[group].vertices[v1].p.v[1]; + face_list->v[0].v[2] = prepared->groups[group].vertices[v1].p.v[2]; + face_list->v[1].v[0] = prepared->groups[group].vertices[v2].p.v[0]; + face_list->v[1].v[1] = prepared->groups[group].vertices[v2].p.v[1]; + face_list->v[1].v[2] = prepared->groups[group].vertices[v2].p.v[2]; + face_list->v[2].v[0] = prepared->groups[group].vertices[v3].p.v[0]; + face_list->v[2].v[1] = prepared->groups[group].vertices[v3].p.v[1]; + face_list->v[2].v[2] = prepared->groups[group].vertices[v3].p.v[2]; + face_list->normal.v[0] = fp->eqn.v[0]; + face_list->normal.v[1] = fp->eqn.v[1]; + face_list->normal.v[2] = fp->eqn.v[2]; + } + if (prepared->groups[group].face_colours_material) { + face_list->material = prepared->groups[group].face_colours_material; + } else { + face_list->material = model_material; + } + face_list->flags = 0; + if (face_list->material && (face_list->material->flags & 0x1800) == 0) { + face_list->flags |= (v2 > v1) + 2 * (v3 > v2) + 4 * (v3 < v1); + } + if (pMat) { + face_list->d = face_list->v[0].v[2] * face_list->normal.v[2] + + face_list->v[0].v[1] * face_list->normal.v[1] + + face_list->v[0].v[0] * face_list->normal.v[0]; + } else { + face_list->d = fp->eqn.v[3]; + } + face_list->map[0] = &prepared->groups[group].vertices[v1].map; + face_list->map[1] = &prepared->groups[group].vertices[v2].map; + face_list->map[2] = &prepared->groups[group].vertices[v3].map; + if (face_list->material + && face_list->material->identifier + && *face_list->material->identifier == '!') { + gPling_face = face_list; + } + face_list++; + max_face--; + if (!max_face) { + break; + } + } + } + } + } + } + } + } + } + ++fp; + } + if (!max_face) { + break; + } + } + return max_face; } // IDA: void __usercall ClipToPlaneGE(br_vector3 *p@, int *nv@, int i@, br_scalar limit) @@ -309,7 +824,35 @@ void ClipToPlaneGE(br_vector3* p, int* nv, int i, br_scalar limit) { int k; br_vector3 p2[12]; LOG_TRACE("(%p, %p, %d, %f)", p, nv, i, limit); - NOT_IMPLEMENTED(); + + last_vertex = *nv - 1; + j = 0; + for (vertex = 0; *nv > vertex; ++vertex) { + if ((p[last_vertex].v[i] > limit) != (p[vertex].v[i] > limit)) { + for (k = 0; k < 3; ++k) { + if (i != k) { + p2[j].v[k] = (p[vertex].v[k] - p[last_vertex].v[k]) + * (limit - p[last_vertex].v[i]) + / (p[vertex].v[i] - p[last_vertex].v[i]) + + p[last_vertex].v[k]; + } + } + p2[j++].v[i] = limit; + } + if (p[vertex].v[i] >= limit) { + p2[j].v[0] = p[vertex].v[0]; + p2[j].v[1] = p[vertex].v[1]; + p2[j].v[2] = p[vertex].v[2]; + j++; + } + last_vertex = vertex; + } + *nv = j; + for (k = 0; k < j; k++) { + p[k].v[0] = p2[k].v[0]; + p[k].v[1] = p2[k].v[1]; + p[k].v[2] = p2[k].v[2]; + } } // IDA: void __usercall ClipToPlaneLE(br_vector3 *p@, int *nv@, int i@, br_scalar limit) @@ -320,13 +863,47 @@ void ClipToPlaneLE(br_vector3* p, int* nv, int i, br_scalar limit) { int k; br_vector3 p2[12]; LOG_TRACE("(%p, %p, %d, %f)", p, nv, i, limit); - NOT_IMPLEMENTED(); + + last_vertex = *nv - 1; + j = 0; + for (vertex = 0; *nv > vertex; ++vertex) { + if ((p[vertex].v[i] > limit) != (p[last_vertex].v[i] > limit)) { + for (k = 0; k < 3; ++k) { + if (k != i) { + p2[j].v[k] = (p[vertex].v[k] - p[last_vertex].v[k]) + * (limit - p[last_vertex].v[i]) + / (p[vertex].v[i] - p[last_vertex].v[i]) + + p[last_vertex].v[k]; + } + } + p2[j++].v[i] = limit; + } + if (p[vertex].v[i] <= (double)limit) { + p2[j].v[0] = p[vertex].v[0]; + p2[j].v[1] = p[vertex].v[1]; + p2[j].v[2] = p[vertex].v[2]; + j++; + } + last_vertex = vertex; + } + *nv = j; + for (k = 0; k < j; k++) { + p[k].v[0] = p2[k].v[0]; + p[k].v[1] = p2[k].v[1]; + p[k].v[2] = p2[k].v[2]; + } } // IDA: int __usercall BoundsOverlapTest@(br_bounds *b1@, br_bounds *b2@) int BoundsOverlapTest_finteray(br_bounds* b1, br_bounds* b2) { LOG_TRACE("(%p, %p)", b1, b2); - NOT_IMPLEMENTED(); + + return b1->min.v[0] <= b2->max.v[0] + && b1->max.v[0] >= b2->min.v[0] + && b1->min.v[1] <= b2->max.v[1] + && b2->min.v[1] <= b1->max.v[1] + && b1->min.v[2] <= b2->max.v[2] + && b1->max.v[2] >= b2->min.v[2]; } // IDA: int __usercall BoundsTransformTest@(br_bounds *b1@, br_bounds *b2@, br_matrix34 *M@) @@ -334,7 +911,56 @@ int BoundsTransformTest(br_bounds* b1, br_bounds* b2, br_matrix34* M) { br_scalar val; br_vector3 o; LOG_TRACE("(%p, %p, %p)", b1, b2, M); - NOT_IMPLEMENTED(); + + o.v[0] = b1->max.v[0] - b1->min.v[0]; + o.v[1] = b1->max.v[1] - b1->min.v[1]; + o.v[2] = b1->max.v[2] - b1->min.v[2]; + val = M->m[2][0] * b1->min.v[2] + b1->min.v[1] * M->m[1][0] + M->m[0][0] * b1->min.v[0] + M->m[3][0]; + + if ((M->m[0][0] <= 0.0 ? 0.0 : M->m[0][0] * o.v[0]) + + (M->m[1][0] <= 0.0 ? 0.0 : M->m[1][0] * o.v[1]) + + (M->m[2][0] <= 0.0 ? 0.0 : M->m[2][0] * o.v[2]) + + val + < b2->min.v[0]) { + return 0; + } + if ((M->m[0][0] < 0.0 ? M->m[0][0] * o.v[0] : 0.0) + + (M->m[1][0] < 0.0 ? M->m[1][0] * o.v[1] : 0.0) + + (M->m[2][0] < 0.0 ? M->m[2][0] * o.v[2] : 0.0) + + val + > b2->max.v[0]) { + return 0; + } + + val = M->m[1][2] * b1->min.v[1] + b1->min.v[2] * M->m[2][2] + M->m[0][2] * b1->min.v[0] + M->m[3][2]; + if ((M->m[0][2] <= 0.0 ? 0.0 : M->m[0][2] * o.v[0]) + + (M->m[1][2] <= 0.0 ? 0.0 : M->m[1][2] * o.v[1]) + + (M->m[2][2] <= 0.0 ? 0.0 : M->m[2][2] * o.v[2]) + + val + < b2->min.v[2]) { + return 0; + } + if ((M->m[0][2] < 0.0 ? M->m[0][2] * o.v[0] : 0.0) + + (M->m[1][2] < 0.0 ? M->m[1][2] * o.v[1] : 0.0) + + (M->m[2][2] < 0.0 ? M->m[2][2] * o.v[2] : 0.0) + + val + > b2->max.v[2]) { + return 0; + } + + val = b1->min.v[2] * M->m[2][1] + b1->min.v[1] * M->m[1][1] + M->m[0][1] * b1->min.v[0] + M->m[3][1]; + if ((M->m[0][1] <= 0.0 ? 0.0 : M->m[0][1] * o.v[0]) + + (M->m[1][1] <= 0.0 ? 0.0 : M->m[1][1] * o.v[1]) + + (M->m[2][1] <= 0.0 ? 0.0 : M->m[2][1] * o.v[2]) + + val + < b2->min.v[1]) { + return 0; + } + return ((M->m[0][1] < 0.0 ? M->m[0][1] * o.v[0] : 0.0) + + (M->m[1][1] < 0.0 ? M->m[1][1] * o.v[1] : 0.0) + + (M->m[2][1] < 0.0 ? M->m[2][1] * o.v[2] : 0.0) + + val + <= b2->max.v[1]); } // IDA: int __usercall LineBoxColl@(br_vector3 *o@, br_vector3 *p@, br_bounds *pB@, br_vector3 *pHit_point@) diff --git a/src/DETHRACE/common/init.c b/src/DETHRACE/common/init.c index 55c20191..1cdb7744 100644 --- a/src/DETHRACE/common/init.c +++ b/src/DETHRACE/common/init.c @@ -212,8 +212,6 @@ void ReinitialiseRenderStuff() { gProgram_state.current_render_top = gProgram_state.current_car.render_top[gProgram_state.cockpit_image_index]; gProgram_state.current_render_right = gProgram_state.current_car.render_right[gProgram_state.cockpit_image_index]; gProgram_state.current_render_bottom = gProgram_state.current_car.render_bottom[gProgram_state.cockpit_image_index]; - LOG_DEBUG("renderbottom %d", gProgram_state.current_render_bottom); - } else { gProgram_state.current_render_top = (gGraf_specs[gGraf_spec_index].total_height / 18 & 0xFFFFFFFE) * gRender_indent; gProgram_state.current_render_left = (gGraf_specs[gGraf_spec_index].total_width / 18 & 0xFFFFFFFC) * gRender_indent; @@ -614,7 +612,8 @@ void DisposeRace() { // IDA: int __cdecl GetScreenSize() int GetScreenSize() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + return gRender_indent; } // IDA: void __usercall SetScreenSize(int pNew_size@) diff --git a/src/DETHRACE/common/opponent.c b/src/DETHRACE/common/opponent.c index 809a02b1..e9a65e8a 100644 --- a/src/DETHRACE/common/opponent.c +++ b/src/DETHRACE/common/opponent.c @@ -159,7 +159,9 @@ tS16 FindNearestPathNode(br_vector3* pActor_coords, br_scalar* pDistance) { // IDA: tS16 __usercall FindNearestPathSection@(br_vector3 *pActor_coords@, br_vector3 *pPath_direction@, br_vector3 *pIntersect@, br_scalar *pDistance@) tS16 FindNearestPathSection(br_vector3* pActor_coords, br_vector3* pPath_direction, br_vector3* pIntersect, br_scalar* pDistance) { LOG_TRACE("(%p, %p, %p, %p)", pActor_coords, pPath_direction, pIntersect, pDistance); - NOT_IMPLEMENTED(); + + STUB(); + return 0; } // IDA: tS16 __usercall FindNearestGeneralSection@(tCar_spec *pPursuee@, br_vector3 *pActor_coords@, br_vector3 *pPath_direction@, br_vector3 *pIntersect@, br_scalar *pDistance) diff --git a/src/DETHRACE/common/raycast.c b/src/DETHRACE/common/raycast.c index 6bc2f06e..e3c44a16 100644 --- a/src/DETHRACE/common/raycast.c +++ b/src/DETHRACE/common/raycast.c @@ -16,8 +16,6 @@ br_scalar gLowest_y_above; br_model* model_unk1; br_material* material_unk1; -// Note: THIS is the _0 in Mac 3dfx build - // IDA: int __usercall DRActorToRoot@(br_actor *a@, br_actor *world@, br_matrix34 *m@) int DRActorToRoot(br_actor* a, br_actor* world, br_matrix34* m) { LOG_TRACE("(%p, %p, %p)", a, world, m); @@ -292,6 +290,8 @@ int DRModelPick2D_raycast(br_model* model, br_material* material, br_vector3* ra double f_numerator; LOG_TRACE("(%p, %p, %p, %p, %f, %f, %p, %p)", model, material, ray_pos, ray_dir, t_near, t_far, callback, arg); + t_near -= 0.001; + t_far += 0.001; for (group = 0; group < V11MODEL(model)->ngroups; group++) { for (f = 0; f < V11MODEL(model)->groups[group].nfaces; f++) { fp = &V11MODEL(model)->groups[group].faces[f]; @@ -309,7 +309,7 @@ int DRModelPick2D_raycast(br_model* model, br_material* material, br_vector3* ra - fp->eqn.v[3]; if (!BadDiv_raycast(numerator, d)) { t = -(numerator / d); - if (t >= (t_near - 0.001) && t <= (t_far + 0.001)) { + if (t >= t_near && t <= t_far) { p.v[0] = ray_dir->v[0] * t; p.v[1] = ray_dir->v[1] * t; p.v[2] = ray_dir->v[2] * t; @@ -384,18 +384,7 @@ int DRModelPick2D_raycast(br_model* model, br_material* material, br_vector3* ra v = 2; } } - r = callback( - model, - this_material, - ray_pos, - ray_dir, - t, - f, - e, - v, - &p, - &map, - arg); + r = callback(model, this_material, ray_pos, ray_dir, t, f, e, v, &p, &map, arg); if (r) { return r; } diff --git a/src/DETHRACE/common/world.c b/src/DETHRACE/common/world.c index 4ee8ba04..1db9b6f8 100644 --- a/src/DETHRACE/common/world.c +++ b/src/DETHRACE/common/world.c @@ -2612,7 +2612,8 @@ void StopGroovidelic(br_actor* pActor) { int i; tGroovidelic_spec* the_groove; LOG_TRACE("(%p)", pActor); - NOT_IMPLEMENTED(); + + STUB(); } // IDA: void __usercall SetGrooveInterrupt(int pGroove_index@, br_matrix34 *pMatrix@, int pPath_interrupt@, int pObject_interrupt@, float pPath_resumption, float pObject_resumption)