From 43f517234de412ecdb96f261b4b0fd9af4d71d22 Mon Sep 17 00:00:00 2001 From: Jeff Harris Date: Tue, 13 Apr 2021 14:04:03 +1200 Subject: [PATCH] Set Initial Grid Position (#46) * Implements SetInitialPosition, fixed prepareGroups vertices --- .github/workflows/linux.yml | 1 - .github/workflows/windows.yml | 4 +- src/BRSRC13/CORE/MATH/angles.h | 5 - src/BRSRC13/CORE/MATH/matrix34.c | 96 +++++++++- src/BRSRC13/CORE/MATH/transfrm.c | 8 +- src/BRSRC13/CORE/V1DB/prepmesh.c | 7 +- src/BRSRC13/br_defs.h | 45 +++++ src/BRSRC13/br_types.h | 30 +--- src/BRSRC13/brender.h | 9 + src/DETHRACE/common/car.c | 137 +++++++++++++- src/DETHRACE/common/finteray.c | 27 ++- src/DETHRACE/common/opponent.c | 12 +- src/DETHRACE/common/opponent.h | 63 +++++++ src/DETHRACE/common/pedestrn.c | 8 +- src/DETHRACE/common/racestrt.c | 165 ++++++++++++++++- src/DETHRACE/common/raycast.c | 297 ++++++++++++++++++++++++++++++- src/DETHRACE/common/raycast.h | 10 ++ src/DETHRACE/common/sound.c | 3 +- src/DETHRACE/common/world.c | 24 +-- 19 files changed, 856 insertions(+), 95 deletions(-) create mode 100644 src/BRSRC13/br_defs.h diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 4b97b35a..b014c8db 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -1,7 +1,6 @@ name: linux on: - pull_request: push: release: types: published diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index dce4cec6..d5d19d6f 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -45,11 +45,11 @@ jobs: echo "$Env:TEMP\ninja" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append ninja --version - - name: Configure Deathrace + - name: Configure run: | cmake -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DSDL2=ON "-DSDL2_ROOT_DIR=$($Env:TEMP)\SDL2-2.0.12" -B build - - name: Build Deathrace + - name: Build run: | cmake --build build --config RelWithDebInfo diff --git a/src/BRSRC13/CORE/MATH/angles.h b/src/BRSRC13/CORE/MATH/angles.h index beb3bbe0..9c6673b4 100644 --- a/src/BRSRC13/CORE/MATH/angles.h +++ b/src/BRSRC13/CORE/MATH/angles.h @@ -4,11 +4,6 @@ #include "br_types.h" #include -#define BrAngleToRadian(a) ((br_scalar)((a) * (M_PI / 32768.0))) -#define BrRadianToAngle(r) ((br_angle)(long)((r) * (32768.0 / M_PI))) - -#define BR_COS(a) ((br_scalar)cos(BrAngleToRadian(a))) - br_matrix34* BrEulerToMatrix34(br_matrix34* mat, br_euler* euler); br_euler* BrMatrix34ToEuler(br_euler* euler, br_matrix34* mat); diff --git a/src/BRSRC13/CORE/MATH/matrix34.c b/src/BRSRC13/CORE/MATH/matrix34.c index 09e80f14..7b61886e 100644 --- a/src/BRSRC13/CORE/MATH/matrix34.c +++ b/src/BRSRC13/CORE/MATH/matrix34.c @@ -86,7 +86,22 @@ void BrMatrix34RotateY(br_matrix34* mat, br_angle ry) { br_scalar s; br_scalar c; LOG_TRACE("(%p, %d)", mat, ry); - NOT_IMPLEMENTED(); + + s = BR_SIN(ry); + c = BR_COS(ry); + + M(0, 0) = c; + M(0, 1) = 0; + M(0, 2) = -s; + M(1, 0) = 0; + M(1, 1) = 1; + M(1, 2) = 0; + M(2, 0) = s; + M(2, 1) = 0; + M(2, 2) = c; + M(3, 0) = 0; + M(3, 1) = 0; + M(3, 2) = 0; } // IDA: void __cdecl BrMatrix34RotateZ(br_matrix34 *mat, br_angle rz) @@ -177,7 +192,69 @@ br_scalar BrMatrix34Inverse(br_matrix34* B, br_matrix34* A) { float BF[4][3]; int i; LOG_TRACE("(%p, %p)", B, A); - NOT_IMPLEMENTED(); + +#define AF(x, y) (AF[x][y]) +#define BF(x, y) (BF[x][y]) + +#define ACCUMULATE \ + if (temp >= 0.0) \ + pos += temp; \ + else \ + neg += temp; +#define PRECISION_LIMIT BR_SCALAR(1.0e-15) +#define ABS(a) (((a) < 0) ? -(a) : (a)) + + for (i = 0; i < 4; i++) { + AF(i, 0) = A(i, 0); + AF(i, 1) = A(i, 1); + AF(i, 2) = A(i, 2); + } + + pos = neg = 0.0F; + temp = AF(0, 0) * AF(1, 1) * AF(2, 2); + ACCUMULATE + temp = AF(0, 1) * AF(1, 2) * AF(2, 0); + ACCUMULATE + temp = AF(0, 2) * AF(1, 0) * AF(2, 1); + ACCUMULATE + temp = -AF(0, 2) * AF(1, 1) * AF(2, 0); + ACCUMULATE + temp = -AF(0, 1) * AF(1, 0) * AF(2, 2); + ACCUMULATE + temp = -AF(0, 0) * AF(1, 2) * AF(2, 1); + ACCUMULATE + det = pos + neg; + + if (ABS(det) <= PRECISION_LIMIT) + return 0; + + if ((ABS(det / (pos - neg)) < PRECISION_LIMIT)) { + return 0; + } + + idet = 1.0F / det; + + BF(0, 0) = (AF(1, 1) * AF(2, 2) - AF(1, 2) * AF(2, 1)) * idet; + BF(1, 0) = -(AF(1, 0) * AF(2, 2) - AF(1, 2) * AF(2, 0)) * idet; + BF(2, 0) = (AF(1, 0) * AF(2, 1) - AF(1, 1) * AF(2, 0)) * idet; + BF(0, 1) = -(AF(0, 1) * AF(2, 2) - AF(0, 2) * AF(2, 1)) * idet; + BF(1, 1) = (AF(0, 0) * AF(2, 2) - AF(0, 2) * AF(2, 0)) * idet; + BF(2, 1) = -(AF(0, 0) * AF(2, 1) - AF(0, 1) * AF(2, 0)) * idet; + BF(0, 2) = (AF(0, 1) * AF(1, 2) - AF(0, 2) * AF(1, 1)) * idet; + BF(1, 2) = -(AF(0, 0) * AF(1, 2) - AF(0, 2) * AF(1, 0)) * idet; + BF(2, 2) = (AF(0, 0) * AF(1, 1) - AF(0, 1) * AF(1, 0)) * idet; + + BF(3, 0) = -(AF(3, 0) * BF(0, 0) + AF(3, 1) * BF(1, 0) + AF(3, 2) * BF(2, 0)); + BF(3, 1) = -(AF(3, 0) * BF(0, 1) + AF(3, 1) * BF(1, 1) + AF(3, 2) * BF(2, 1)); + BF(3, 2) = -(AF(3, 0) * BF(0, 2) + AF(3, 1) * BF(1, 2) + AF(3, 2) * BF(2, 2)); + + for (i = 0; i < 4; i++) { + B(i, 0) = BF(i, 0); + B(i, 1) = BF(i, 1); + B(i, 2) = BF(i, 2); + } + + return det; } // IDA: void __cdecl BrMatrix34LPInverse(br_matrix34 *A, br_matrix34 *B) @@ -243,7 +320,10 @@ void BrMatrix34ApplyP(br_vector3* A, br_vector3* B, br_matrix34* C) { // IDA: void __cdecl BrMatrix34ApplyV(br_vector3 *A, br_vector3 *B, br_matrix34 *C) void BrMatrix34ApplyV(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(1, 0), B->v[2], C(2, 0)); + A->v[1] = BR_MAC3(B->v[0], C(0, 1), B->v[1], C(1, 1), B->v[2], C(2, 1)); + A->v[2] = BR_MAC3(B->v[0], C(0, 2), B->v[1], C(1, 2), B->v[2], C(2, 2)); } // IDA: void __cdecl BrMatrix34TApply(br_vector4 *A, br_vector4 *B, br_matrix34 *C) @@ -294,7 +374,10 @@ void BrMatrix34PostRotateX(br_matrix34* mat, br_angle rx) { // IDA: void __cdecl BrMatrix34PreRotateY(br_matrix34 *mat, br_angle ry) void BrMatrix34PreRotateY(br_matrix34* mat, br_angle ry) { LOG_TRACE("(%p, %d)", mat, ry); - NOT_IMPLEMENTED(); + + BrMatrix34RotateY(&mattmp1, ry); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); } // IDA: void __cdecl BrMatrix34PostRotateY(br_matrix34 *mat, br_angle ry) @@ -351,7 +434,10 @@ void BrMatrix34PreScale(br_matrix34* mat, br_scalar sx, br_scalar sy, br_scalar // IDA: void __cdecl BrMatrix34PostScale(br_matrix34 *mat, br_scalar sx, br_scalar sy, br_scalar sz) void BrMatrix34PostScale(br_matrix34* mat, br_scalar sx, br_scalar sy, br_scalar sz) { LOG_TRACE("(%p, %f, %f, %f)", mat, sx, sy, sz); - NOT_IMPLEMENTED(); + + BrMatrix34Scale(&mattmp1, sx, sy, sz); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); } // IDA: void __cdecl BrMatrix34PreShearX(br_matrix34 *mat, br_scalar sy, br_scalar sz) diff --git a/src/BRSRC13/CORE/MATH/transfrm.c b/src/BRSRC13/CORE/MATH/transfrm.c index 090324a8..74e42830 100644 --- a/src/BRSRC13/CORE/MATH/transfrm.c +++ b/src/BRSRC13/CORE/MATH/transfrm.c @@ -97,7 +97,13 @@ void BrMatrix34PreTransform(br_matrix34* mat, br_transform* xform) { void BrMatrix34PostTransform(br_matrix34* mat, br_transform* xform) { br_matrix34 tmp; LOG_TRACE("(%p, %p)", mat, xform); - NOT_IMPLEMENTED(); + + if (xform->type == BR_TRANSFORM_IDENTITY) { + return; + } + + BrTransformToMatrix34(&tmp, xform); + BrMatrix34Post(mat, &tmp); } // IDA: void __cdecl BrMatrix4PreTransform(br_matrix4 *mat, br_transform *xform) diff --git a/src/BRSRC13/CORE/V1DB/prepmesh.c b/src/BRSRC13/CORE/V1DB/prepmesh.c index d645000d..fbe4bd51 100644 --- a/src/BRSRC13/CORE/V1DB/prepmesh.c +++ b/src/BRSRC13/CORE/V1DB/prepmesh.c @@ -476,10 +476,11 @@ void PrepareGroups(br_model* model) { for (g = 0; g < ng; g++) { for (f = 0; f < v11g[g].nfaces; f++) { + i = v11g[g].vertices - v11v; v = v11g[g].face_user[f] * 3; - v11g[g].faces[f].vertices[0] = temp_verts[v + 0].v; - v11g[g].faces[f].vertices[1] = temp_verts[v + 1].v; - v11g[g].faces[f].vertices[2] = temp_verts[v + 2].v; + v11g[g].faces[f].vertices[0] = temp_verts[v + 0].v - i; + v11g[g].faces[f].vertices[1] = temp_verts[v + 1].v - i; + v11g[g].faces[f].vertices[2] = temp_verts[v + 2].v - i; } } BrScratchFree(temp_verts); diff --git a/src/BRSRC13/br_defs.h b/src/BRSRC13/br_defs.h new file mode 100644 index 00000000..8a388e7c --- /dev/null +++ b/src/BRSRC13/br_defs.h @@ -0,0 +1,45 @@ +#ifndef BR_DEFS_H +#define BR_DEFS_H + +#define PI 3.14159265358979323846 + +#define BrAngleToRadian(a) ((br_scalar)((a) * (PI / 32768.0))) // a * 0.00009587379924285257 +#define BrRadianToAngle(r) ((br_angle)(long)((r) * (32768.0 / PI))) // r * 10430.378350470453 + +#define BR_COLOUR_RGB(r, g, b) \ + ((((unsigned int)(r)) << 16) | (((unsigned int)(g)) << 8) | ((unsigned int)(b))) + +#define BR_ANGLE_DEG(deg) ((br_angle)((deg)*182)) +#define BR_ANGLE_RAD(rad) ((br_angle)((rad)*10430)) +#define BrDegreeToRadian(d) ((br_scalar)((d) * (PI / 180.0))) + +#define BR_SCALAR(x) ((br_scalar)(x)) + +#define BR_COLOUR_RGBA(r, g, b, a) \ + ((((unsigned int)(a)) << 24) | (((unsigned int)(r)) << 16) | (((unsigned int)(g)) << 8) | ((unsigned int)(b))) + +#define BR_LENGTH3(a, b, c) ((br_scalar)sqrt((a) * (a) + (b) * (b) + (c) * (c))) +#define BR_SCALAR_EPSILON 1.192092896e-7f +#define BR_SCALAR_MAX 3.402823466e+38f +#define BR_SCALAR_MIN (-3.402823466e+38f) + +#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 V_X 0 +#define V_Y 1 +#define V_Z 2 +#define V_W 3 + +#define BR_FONTF_PROPORTIONAL 1 + +#define BR_SIN(a) ((br_scalar)sin(BrAngleToRadian(a))) +#define BR_COS(a) ((br_scalar)cos(BrAngleToRadian(a))) +#define BR_TAN(a) ((br_scalar)tan(BrAngleToRadian(a))) +#define BR_ASIN(a) BrRadianToAngle(asin(a)) +#define BR_ACOS(a) BrRadianToAngle(acos(a)) +#define BR_ATAN2(a, b) BrRadianToAngle(atan2((a), (b))) +#define BR_ATAN2FAST(a, b) BrRadianToAngle(atan2((a), (b))) + +#endif /* BR_DEFS_H */ \ No newline at end of file diff --git a/src/BRSRC13/br_types.h b/src/BRSRC13/br_types.h index b60e9d23..2870693b 100644 --- a/src/BRSRC13/br_types.h +++ b/src/BRSRC13/br_types.h @@ -1,6 +1,7 @@ #ifndef BR_TYPES_H #define BR_TYPES_H +#include "br_defs.h" #include #include @@ -2795,6 +2796,7 @@ 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; @@ -3003,32 +3005,4 @@ enum { MODF_USES_DEFAULT = 0x8000 }; -#define BR_COLOUR_RGB(r, g, b) \ - ((((unsigned int)(r)) << 16) | (((unsigned int)(g)) << 8) | ((unsigned int)(b))) - -#define BR_ANGLE_DEG(deg) ((br_angle)((deg)*182)) -#define BR_ANGLE_RAD(rad) ((br_angle)((rad)*10430)) -#define BrDegreeToRadian(d) ((br_scalar)((d) * (M_PI / 180.0))) - -#define BR_SCALAR(x) ((br_scalar)(x)) - -#define BR_COLOUR_RGBA(r, g, b, a) \ - ((((unsigned int)(a)) << 24) | (((unsigned int)(r)) << 16) | (((unsigned int)(g)) << 8) | ((unsigned int)(b))) - -#define BR_LENGTH3(a, b, c) ((br_scalar)sqrt((a) * (a) + (b) * (b) + (c) * (c))) -#define BR_SCALAR_EPSILON 1.192092896e-7f -#define BR_SCALAR_MAX 3.402823466e+38f -#define BR_SCALAR_MIN (-3.402823466e+38f) - -#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 V_X 0 -#define V_Y 1 -#define V_Z 2 -#define V_W 3 - -#define BR_FONTF_PROPORTIONAL 1 - #endif /* BR_TYPES_H */ \ No newline at end of file diff --git a/src/BRSRC13/brender.h b/src/BRSRC13/brender.h index 0c8b7446..f3b9ab19 100644 --- a/src/BRSRC13/brender.h +++ b/src/BRSRC13/brender.h @@ -56,12 +56,18 @@ br_uint_32 BrMaterialEnum(char* pattern, br_material_enum_cbfn* callback, void* void BrMatrix23Identity(br_matrix23* mat); void BrMatrix34Identity(br_matrix34* mat); +void BrMatrix34ApplyV(br_vector3* A, br_vector3* B, br_matrix34* C); br_scalar BrMatrix34Inverse(br_matrix34* B, br_matrix34* A); 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); void BrMatrix34Mul(br_matrix34* A, br_matrix34* B, br_matrix34* C); void BrMatrix34Copy(br_matrix34* A, br_matrix34* B); +void BrMatrix34PreRotateY(br_matrix34* mat, br_angle ry); +void BrMatrix34RotateY(br_matrix34* mat, br_angle ry); +void BrMatrix34PostScale(br_matrix34* mat, br_scalar sx, br_scalar sy, br_scalar sz); +void BrMatrix34PreTransform(br_matrix34* mat, br_transform* xform); +void BrMatrix34PostTransform(br_matrix34* mat, br_transform* xform); // BrMem void BrMemFree(void* block); @@ -106,6 +112,9 @@ br_pixelmap* BrTableFind(char* pattern); br_pixelmap* BrTableRemove(br_pixelmap* pixelmap); br_uint_32 BrTableAddMany(br_pixelmap** items, int n); +// BrTransform +void BrTransformToMatrix34(br_matrix34* mat, br_transform* xform); + // BrV1db void BrV1dbBeginWrapper_Float(); diff --git a/src/DETHRACE/common/car.c b/src/DETHRACE/common/car.c index 05ae9d3f..4b661e37 100644 --- a/src/DETHRACE/common/car.c +++ b/src/DETHRACE/common/car.c @@ -1,4 +1,12 @@ #include "car.h" +#include "brender.h" +#include "globvars.h" +#include "globvrkm.h" +#include "globvrpb.h" +#include "netgame.h" +#include "opponent.h" +#include "raycast.h" +#include "utility.h" #include float gEngine_powerup_factor[6]; @@ -205,7 +213,8 @@ void InitialiseCar2(tCar_spec* pCar, int pClear_disabled_flag) { // IDA: void __usercall InitialiseCar(tCar_spec *pCar@) void InitialiseCar(tCar_spec* pCar) { LOG_TRACE("(%p)", pCar); - NOT_IMPLEMENTED(); + + InitialiseCar2(pCar, 1); } // IDA: void __usercall InitialiseCarsEtc(tRace_info *pThe_race@) @@ -216,7 +225,33 @@ void InitialiseCarsEtc(tRace_info* pThe_race) { tCar_spec* car; br_bounds bnds; LOG_TRACE("(%p)", pThe_race); - NOT_IMPLEMENTED(); + + gProgram_state.initial_position = pThe_race->initial_position; + gProgram_state.initial_yaw = pThe_race->initial_yaw; + BrActorToBounds(&bnds, gProgram_state.track_spec.the_actor); + gMin_world_y = bnds.min.v[1]; + gNum_active_non_cars = 0; + for (cat = eVehicle_self; cat <= eVehicle_not_really; ++cat) { + if (cat) { + car_count = GetCarCount(cat); + } else { + car_count = 1; + } + for (i = 0; car_count > i; ++i) { + PossibleService(); + if (cat) { + car = GetCarSpec(cat, i); + } else { + car = &gProgram_state.current_car; + } + if (cat != eVehicle_not_really) { + InitialiseCar(car); + } + } + } + gCamera_yaw = 0; + InitialiseExternalCamera(); + gMechanics_time_sync = 0; } // IDA: void __usercall GetAverageGridPosition(tRace_info *pThe_race@) @@ -250,14 +285,108 @@ void SetInitialPosition(tRace_info* pThe_race, int pCar_index, int pGrid_index) br_matrix34 initial_yaw_matrix; br_bounds bnds; LOG_TRACE("(%p, %d, %d)", pThe_race, pCar_index, pGrid_index); - NOT_IMPLEMENTED(); + + car_actor = pThe_race->opponent_list[pCar_index].car_spec->car_master_actor; + car = pThe_race->opponent_list[pCar_index].car_spec; + BrMatrix34Identity(&car_actor->t.t.mat); + place_on_grid = 1; + if (gNet_mode && !gCurrent_net_game->options.grid_start && pThe_race->number_of_net_start_points) { + TELL_ME_IF_WE_PASS_THIS_WAY(); + // start_i = IRandomBetween(0, pThe_race->number_of_net_start_points - 1); + // i = start_i; + // while (1) { + // PossibleService(); + // for (j = 0; gNumber_of_net_players > j; ++j) { + // if (j != pCar_index) { + // v19 = pThe_race->opponent_list[j].car_spec->car_master_actor->t.t.translate.t.v[0]; + // v20 = pThe_race->opponent_list[j].car_spec->car_master_actor->t.t.translate.t.v[1]; + // v21 = pThe_race->opponent_list[j].car_spec->car_master_actor->t.t.translate.t.v[2]; + // if (v19 > 500.0) { + // v19 = v19 - 1000.0f; + // v20 = v20 - 1000.0f; + // v21 = v21 - 1000.0f; + // } + // dist.v[0] = v19 - pThe_race->net_starts[start_i].pos.v[0]; + // dist.v[1] = v20 - pThe_race->net_starts[start_i].pos.v[1]; + // dist.v[2] = v21 - pThe_race->net_starts[start_i].pos.v[2]; + // if (dist.v[1] * dist.v[1] + dist.v[2] * dist.v[2] + dist.v[0] * dist.v[0] < 16.0) { + // break; + // } + // } + // } + // if (gNumber_of_net_players == j) { + // break; + // } + // if (pThe_race->number_of_net_start_points == ++start_i) { + // start_i = 0; + // } + // if (i == start_i) { + // goto LABEL_17; + // } + // } + // car_actor->t.t.translate.t.v[0] = pThe_race->net_starts[start_i].pos.v[0]; + // car_actor->t.t.translate.t.v[1] = pThe_race->net_starts[start_i].pos.v[1]; + // car_actor->t.t.translate.t.v[2] = pThe_race->net_starts[start_i].pos.v[2]; + // initial_yaw[0] = (__int64)(pThe_race->net_starts[start_i].yaw * 182.0444444444445); + // place_on_grid = 0; + } +LABEL_17: + if (place_on_grid) { + initial_yaw = (pThe_race->initial_yaw * 182.0444444444445); + BrMatrix34RotateY(&initial_yaw_matrix, initial_yaw); + grid_offset.v[0] = 0.0 - pGrid_index % 2; + grid_offset.v[1] = 0.0; + grid_offset.v[2] = (double)(pGrid_index / 2) * 2.0 + (double)(pGrid_index % 2) * 0.40000001; + LOG_DEBUG("grid offset: %f, %f, %f", grid_offset.v[0], grid_offset.v[1], grid_offset.v[2]); + BrMatrix34ApplyV(&car_actor->t.t.translate.t, &grid_offset, &initial_yaw_matrix); + car_actor->t.t.translate.t.v[0] += pThe_race->initial_position.v[0]; + car_actor->t.t.translate.t.v[1] += pThe_race->initial_position.v[1]; + car_actor->t.t.translate.t.v[2] += pThe_race->initial_position.v[2]; + LOG_DEBUG("yaw: %f, pos: %f, %f, %f", pThe_race->initial_yaw, pThe_race->initial_position.v[0], pThe_race->initial_position.v[1], pThe_race->initial_position.v[2]); + } + LOG_DEBUG("grid pos: %d, pos: x=%f, z=%f", pGrid_index, car_actor->t.t.translate.t.v[0], car_actor->t.t.translate.t.v[2]); + FindBestY( + &car_actor->t.t.translate.t, + gTrack_actor, + 10.0, + &nearest_y_above, + &nearest_y_below, + &above_model, + &below_model, + &above_face_index, + &below_face_index); + if (nearest_y_above == 30000.0) { + if (nearest_y_below == -30000.0) { + LOG_DEBUG("found pos 1: %f", 0); + car_actor->t.t.translate.t.v[1] = 0.0; + } else { + LOG_DEBUG("found pos 2: %f", nearest_y_below); + car_actor->t.t.translate.t.v[1] = nearest_y_below; + } + } else { + // 20.345 + LOG_DEBUG("found pos 3: %f, x: %f, z: %f", nearest_y_above, car_actor->t.t.translate.t.v[0], car_actor->t.t.translate.t.v[2]); + car_actor->t.t.translate.t.v[1] = nearest_y_above; + } + BrMatrix34PreRotateY(&car_actor->t.t.mat, initial_yaw); + if (gNet_mode) { + BrMatrix34Copy( + &gNet_players[pThe_race->opponent_list[pCar_index].net_player_index].initial_position, + &car->car_master_actor->t.t.mat); + } + if (gNet_mode && car->disabled && car_actor->t.t.translate.t.v[0] < 500.0) { + DisableCar(car); + } } // IDA: void __usercall SetInitialPositions(tRace_info *pThe_race@) void SetInitialPositions(tRace_info* pThe_race) { int i; LOG_TRACE("(%p)", pThe_race); - NOT_IMPLEMENTED(); + + for (i = 0; i < pThe_race->number_of_racers; i++) { + SetInitialPosition(pThe_race, i, i); + } } // IDA: void __usercall InitialiseNonCar(tNon_car_spec *non_car@) diff --git a/src/DETHRACE/common/finteray.c b/src/DETHRACE/common/finteray.c index 39baf68e..ae6a995b 100644 --- a/src/DETHRACE/common/finteray.c +++ b/src/DETHRACE/common/finteray.c @@ -1,5 +1,7 @@ #include "finteray.h" #include "brender.h" +#include "globvars.h" +#include "raycast.h" #include br_matrix34 gPick_model_to_view; @@ -18,7 +20,9 @@ tFace_ref* gPling_face; // IDA: void __usercall DRVector2AccumulateScale(br_vector2 *a@, br_vector2 *b@, br_scalar s) void DRVector2AccumulateScale(br_vector2* a, br_vector2* b, br_scalar s) { LOG_TRACE("(%p, %p, %f)", a, b, s); - NOT_IMPLEMENTED(); + + a->v[0] = b->v[0] * s + a->v[0]; + a->v[1] = b->v[1] * s + a->v[1]; } // IDA: int __usercall ActorRayPick2D@(br_actor *ap@, br_vector3 *pPosition@, br_vector3 *pDir@, br_model *model@, br_material *material, dr_pick2d_cbfn *callback) @@ -47,13 +51,30 @@ int DRSceneRayPick2D(br_actor* world, br_vector3* pPosition, br_vector3* pDir, d // 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) int 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) { LOG_TRACE("(%p, %p, %p, %p, %f, %d, %d, %d, %p, %p, %p)", pModel, pMaterial, pRay_pos, pRay_dir, pT, pF, pE, pV, pPoint, pMap, pArg); - NOT_IMPLEMENTED(); + + if (pPoint->v[1] > gCurrent_y) { + if (gLowest_y_above > pPoint->v[1]) { + gLowest_y_above = pPoint->v[1]; + gAbove_face_index = pF; + gAbove_model = pModel; + } + } else if (pPoint->v[1] > gHighest_y_below) { + gHighest_y_below = pPoint->v[1]; + gBelow_face_index = pF; + gBelow_model = pModel; + } + return 0; } // IDA: int __cdecl FindHighestCallBack(br_actor *pActor, br_model *pModel, br_material *pMaterial, br_vector3 *pRay_pos, br_vector3 *pRay_dir, br_scalar pT_near, br_scalar pT_far, void *pArg) int FindHighestCallBack(br_actor* pActor, br_model* pModel, br_material* pMaterial, br_vector3* pRay_pos, br_vector3* pRay_dir, br_scalar pT_near, br_scalar pT_far, void* pArg) { LOG_TRACE("(%p, %p, %p, %p, %p, %f, %f, %p)", pActor, pModel, pMaterial, pRay_pos, pRay_dir, pT_near, pT_far, pArg); - NOT_IMPLEMENTED(); + + if (gProgram_state.current_car.current_car_actor < 0 + || gProgram_state.current_car.car_model_actors[gProgram_state.current_car.current_car_actor].actor != pActor) { + DRModelPick2D(pModel, pMaterial, pRay_pos, pRay_dir, pT_near, pT_far, FindHighestPolyCallBack, pArg); + } + return 0; } // IDA: void __usercall FindFace(br_vector3 *pPosition@, br_vector3 *pDir@, br_vector3 *nor@, br_scalar *t@, br_material **material) diff --git a/src/DETHRACE/common/opponent.c b/src/DETHRACE/common/opponent.c index 16a8f7d9..ec5a2b94 100644 --- a/src/DETHRACE/common/opponent.c +++ b/src/DETHRACE/common/opponent.c @@ -13,7 +13,7 @@ br_scalar gIn_view_distance; tU8* gBit_per_node; int gGrudge_reduction_per_period; int gSFS_max_cycles; -int gChallenger_index; +int gChallenger_index_oppo; // added _oppo suffix to avoid name collision int gSFS_cycles_this_time; br_scalar gMinimum_yness_before_knackerisation; int gWanky_arse_tit_fuck; @@ -643,7 +643,9 @@ void CalcOpponentConspicuousnessWithAViewToCheatingLikeFuck(tOpponent_spec* pOpp // IDA: void __usercall ChallengeOccurred(int pChallenger_index@, int pAccepted@) void ChallengeOccurred(int pChallenger_index, int pAccepted) { LOG_TRACE("(%d, %d)", pChallenger_index, pAccepted); - NOT_IMPLEMENTED(); + if (pAccepted) { + gChallenger_index_oppo = pChallenger_index; + } } // IDA: void __cdecl LoadCopCars() @@ -866,7 +868,8 @@ void MungeOpponents(tU32 pFrame_period) { void SetInitialCopPositions() { int i; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + STUB(); } // IDA: void __usercall InitOpponents(tRace_info *pRace_info@) @@ -877,7 +880,8 @@ void InitOpponents(tRace_info* pRace_info) { int skill_dependent_difficulty; br_bounds bounds; LOG_TRACE("(%p)", pRace_info); - NOT_IMPLEMENTED(); + + STUB(); } // IDA: void __cdecl DisposeOpponents() diff --git a/src/DETHRACE/common/opponent.h b/src/DETHRACE/common/opponent.h index 451abf84..e4531daf 100644 --- a/src/DETHRACE/common/opponent.h +++ b/src/DETHRACE/common/opponent.h @@ -4,7 +4,70 @@ #include "br_types.h" #include "dr_types.h" +extern char gOppo_path_filename[256]; +extern br_scalar gIn_view_distance; +extern tU8* gBit_per_node; +extern int gGrudge_reduction_per_period; +extern int gSFS_max_cycles; +extern int gChallenger_index_oppo; // added _oppo suffix to avoid name collision +extern int gSFS_cycles_this_time; +extern br_scalar gMinimum_yness_before_knackerisation; +extern int gWanky_arse_tit_fuck; +extern br_scalar gHead_on_cos_value; +extern int gSFS_count; +extern int gSFS_total_cycles; +extern tU32 gNext_grudge_reduction; +extern br_scalar gCop_pursuit_speed_percentage_multiplier; +extern br_scalar gDefinite_cop_pursuit_speed; +extern int gAcknowledged_start; +extern int gMin_bangness; +extern int gStart_jumped; +extern int gNum_of_opponents_getting_near; +extern tU32 gNext_elastication; +extern int gNumber_of_cops_before_faffage; +extern int gFirst_frame; +extern tU32 gAcme_frame_count; +extern char* gDrone_name; +extern br_scalar gDefinite_no_cop_pursuit_speed; +extern tU32 gNext_write_during_elastication; +extern int gNum_of_opponents_completing_race; +extern int gNum_of_opponents_pursuing; +extern int gMax_bangness; +extern int gActive_car_list_rebuild_required; +extern char* gCop_name; +extern br_scalar gFrame_period_for_this_munging_in_secs; +extern int gBig_bang; +extern char* gPath_section_type_names[3]; +extern br_material* gMat_lt_blu; +extern int gFaces_used_in_non_edit_paths; +extern br_material* gMat_dk_blu; +extern int gMats_allocated; +extern int gBIG_APC_index; +extern br_material* gMat_lt_red; +extern int gTest_toggle; +extern int gVertices_used_in_non_edit_paths; +extern br_material* gMat_lt_turq; +extern br_material* gMat_lt_grn; +extern int gAlready_elasticating; +extern br_material* gMat_dk_red; +extern int gOppo_paths_shown; +extern br_material* gMat_dk_turq; +extern br_material* gMat_lt_gry; +extern br_material* gMat_md_gry; +extern br_material* gMat_dk_grn; +extern int gMellow_opponents; +extern int gMade_path_filename; +extern int gProcessing_opponents; +extern br_material* gMat_dk_gry; +extern br_material* gMat_dk_yel; +extern br_material* gMat_lt_yel; +extern br_material* gMat_md_yel; +extern br_model* gOppo_path_model; +extern br_actor* gOppo_path_actor; +extern tU32 gFrame_period_for_this_munging; +extern tU32 gTime_stamp_for_this_munging; extern float gOpponent_nastyness_frigger; +extern tS16 gMobile_section; void PointActorAlongThisBloodyVector(br_actor* pThe_actor, br_vector3* pThe_vector); diff --git a/src/DETHRACE/common/pedestrn.c b/src/DETHRACE/common/pedestrn.c index e346a25f..53d677dd 100644 --- a/src/DETHRACE/common/pedestrn.c +++ b/src/DETHRACE/common/pedestrn.c @@ -898,10 +898,10 @@ void CreatePedestrian(FILE* pG, tPedestrian_instruction* pInstructions, int pIns the_pedestrian->killers_ID = -1; the_pedestrian->murderer = -1; the_pedestrian->sent_dead_message = 0; - minnest_min = 3.4028235e38; - maxest_min = -3.4028235e38; - minnest_max = 3.4028235e38; - maxest_max = -3.4028235e38; + minnest_min = BR_SCALAR_MAX; + maxest_min = BR_SCALAR_MIN; + minnest_max = BR_SCALAR_MAX; + maxest_max = BR_SCALAR_MIN; the_pedestrian->number_of_actions = GetAnInt(pG); the_pedestrian->action_list = BrMemAllocate(sizeof(tPedestrian_action) * the_pedestrian->number_of_actions, kMem_ped_action_list); the_action = the_pedestrian->action_list; diff --git a/src/DETHRACE/common/racestrt.c b/src/DETHRACE/common/racestrt.c index 8f6fb101..70c0edb8 100644 --- a/src/DETHRACE/common/racestrt.c +++ b/src/DETHRACE/common/racestrt.c @@ -2,6 +2,7 @@ #include "brender.h" #include "displays.h" #include "drmem.h" +#include "errors.h" #include "flicplay.h" #include "globvars.h" #include "grafdata.h" @@ -9,6 +10,7 @@ #include "input.h" #include "intrface.h" #include "loading.h" +#include "opponent.h" #include "pd/sys.h" #include "sound.h" #include "structur.h" @@ -1129,31 +1131,176 @@ void ChallengeStart() { tPath_name the_path; char s[256]; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + InitialiseFlicPanel( + 0, + gCurrent_graf_data->start_race_panel_left, + gCurrent_graf_data->start_race_panel_top, + gCurrent_graf_data->start_race_panel_right - gCurrent_graf_data->start_race_panel_left, + gCurrent_graf_data->start_race_panel_bottom - gCurrent_graf_data->start_race_panel_top); + ChangePanelFlic( + 0, + gOpponents[gChallenger_index].mug_shot_image_data, + gOpponents[gChallenger_index].mug_shot_image_data_length); + if (gScreen->row_bytes < 0) { + BrFatal("C:\\Msdev\\Projects\\DethRace\\Racestrt.c", 2610, "Bruce bug at line %d, file C:\\Msdev\\Projects\\DethRace\\Racestrt.c", 50); + } + the_map = DRPixelmapAllocate( + gScreen->type, + gCurrent_graf_data->dare_mugshot_width, + gCurrent_graf_data->dare_mugshot_height, + 0, + 0); + + BrPixelmapRectangleCopy(the_map, 0, 0, GetPanelPixelmap(0), gCurrent_graf_data->dare_mug_left_margin, gCurrent_graf_data->dare_mug_top_margin, gCurrent_graf_data->dare_mugshot_width, gCurrent_graf_data->dare_mugshot_height); + DisposeFlicPanel(0); + TellyInImage(the_map, gCurrent_graf_data->dare_mugshot_left, gCurrent_graf_data->dare_mugshot_top); + BrPixelmapFree(the_map); + the_map = DRPixelmapAllocate(gScreen->type, gCurrent_graf_data->dare_text_width, gCurrent_graf_data->dare_mugshot_height, 0, 0); + BrPixelmapFill(the_map, 0); + TransBrPixelmapText(the_map, 0, 0, 1u, gBig_font, (signed char*)gOpponents[gChallenger_index].abbrev_name); + PathCat(the_path, gApplication_path, "DARES.TXT"); + f = DRfopen(the_path, "rt"); + if (!f) { + FatalError(100); + } + + dare_index = IRandomBetween(0, GetAnInt(f) - 1); + for (i = 0; i < dare_index; i++) { + line_count = GetAnInt(f); + for (j = 0; j < line_count; j++) { + GetALineAndDontArgue(f, s); + } + } + line_count = GetAnInt(f); + for (i = 0; i < line_count; i++) { + GetALineAndDontArgue(f, s); + TransBrPixelmapText(the_map, 0, 2 * (i + 1) * gBig_font->glyph_y, 0x86u, gBig_font, (signed char*)s); + } + fclose(f); + BrPixelmapLine(the_map, 0, gBig_font->glyph_y + 2, the_map->width, gBig_font->glyph_y + 2, 45); + TellyInImage(the_map, gCurrent_graf_data->dare_text_left, gCurrent_graf_data->dare_mugshot_top); + BrPixelmapFree(the_map); + UnlockOpponentMugshot(gChallenger_index); + gDare_start_time = PDGetTotalTime(); } // IDA: int __usercall CheckNextStage@(int *pCurrent_choice@, int *pCurrent_mode@) int CheckNextStage(int* pCurrent_choice, int* pCurrent_mode) { LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + if (gDare_start_time && (unsigned int)(PDGetTotalTime() - gDare_start_time) >= 7500) { + BrPixelmapRectangleFill( + gBack_screen, + gCurrent_graf_data->grid_left_clip, + gCurrent_graf_data->dare_mugshot_top, + gCurrent_graf_data->grid_right_clip - gCurrent_graf_data->grid_left_clip, + gCurrent_graf_data->dare_mugshot_height, + 0); + DoGridTransition(gOur_starting_position, gChallenger_position); + gDraw_grid_status = eGrid_draw_icons_only; + gDare_start_time = 0; + } + return 0; } // IDA: int __usercall ChallengeDone@(int pCurrent_choice@, int pCurrent_mode@, int pGo_ahead@, int pEscaped@, int pTimed_out) int ChallengeDone(int pCurrent_choice, int pCurrent_mode, int pGo_ahead, int pEscaped, int pTimed_out) { LOG_TRACE("(%d, %d, %d, %d, %d)", pCurrent_choice, pCurrent_mode, pGo_ahead, pEscaped, pTimed_out); - NOT_IMPLEMENTED(); + + if (!pEscaped || gDare_start_time) { + if (!pEscaped && gDare_start_time) { + ActuallySwapOrder(gOur_starting_position, gChallenger_position); + ChallengeOccurred(gChallenger_index, 1); + } + } else { + DoGridTransition(gOur_starting_position, gOriginal_position); + ActuallySwapOrder(gOur_starting_position, gOriginal_position); + ChallengeOccurred(gChallenger_index, 0); + } + ChallengeOccurred(gChallenger_index, pEscaped == 0); + if (pTimed_out) { + return 0; + } else { + return pCurrent_choice; + } } // IDA: void __cdecl DoChallengeScreen() void DoChallengeScreen() { - static tFlicette flicker_on[2]; - static tFlicette flicker_off[2]; - static tFlicette push[2]; - static tMouse_area mouse_areas[2]; - static tInterface_spec interface_spec; + static tFlicette flicker_on[2] = { { 43, { 54, 108 }, { 157, 377 } }, { 43, { 218, 436 }, { 157, 377 } } }; + static tFlicette flicker_off[2] = { { 42, { 54, 108 }, { 157, 377 } }, { 42, { 218, 436 }, { 157, 377 } } }; + static tFlicette push[2] = { { 304, { 54, 108 }, { 157, 377 } }, { 305, { 218, 436 }, { 157, 377 } } }; + static tMouse_area mouse_areas[2] = { + { { 54, 108 }, { 157, 377 }, { 117, 234 }, { 178, 427 }, 0, 0, 0, NULL }, + { { 218, 436 }, { 157, 377 }, { 281, 562 }, { 178, 427 }, 1, 0, 0, NULL } + }; + static tInterface_spec interface_spec = { + 0, // initial_imode + 301, // first_opening_flic + 0, // second_opening_flic + -1, // end_flic_go_ahead + -1, // end_flic_escaped + -1, // end_flic_otherwise + 0, // flic_bunch_to_load + { -1, 0 }, // move_left_new_mode + { -1, 0 }, // move_left_delta + { 0, 0 }, // move_left_min + { 1, 0 }, // move_left_max + { NULL, NULL }, // move_left_proc + { -1, 0 }, // move_right_new_mode + { 1, 0 }, // move_right_delta + { 0, 0 }, // move_right_min + { 1, 0 }, // move_right_max + { NULL, NULL }, // move_right_proc + { -1, 0 }, // move_up_new_mode + { 0, 0 }, // move_up_delta + { 0, 0 }, // move_up_min + { 0, 0 }, // move_up_max + { NULL, NULL }, // move_up_proc + { -1, 0 }, // move_down_new_mode + { 0, 0 }, // move_down_delta + { 0, 0 }, // move_down_min + { 0, 0 }, // move_down_max + { NULL, NULL }, // move_down_proc + { 1, 1 }, // go_ahead_allowed + { NULL, NULL }, // go_ahead_proc + { 1, 1 }, // escape_allowed + { NULL, NULL }, // escape_proc + &CheckNextStage, // exit_proc + &GridDraw, // draw_proc + 0u, // time_out + NULL, // start_proc1 + &ChallengeStart, // start_proc2 + &ChallengeDone, // done_proc + 0, // font_needed + { 0, 0 }, // typeable + NULL, // get_original_string + 1, // escape_code + 1, // dont_save_or_load + 2, // number_of_button_flics + flicker_on, // flicker_on_flics + flicker_off, // flicker_off_flics + push, // pushed_flics + 2, // number_of_mouse_areas + mouse_areas, // mouse_areas + 0, // number_of_recopy_areas + NULL // recopy_areas + }; + int result; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + gOriginal_position = gOur_starting_position; + gChallenger_position = IRandomBetween(0, 1); + if (gOpponents[gCurrent_race.opponent_list[gChallenger_position].index].car_number < 0) { + gChallenger_position ^= 1u; + } + gChallenger_index = gCurrent_race.opponent_list[gChallenger_position].index; + LoadOpponentMugShot(gChallenger_index); + gDraw_grid_status = eGrid_draw_none; + gGrid_y_adjust = gCurrent_graf_data->dare_y_adjust; + DoInterfaceScreen(&interface_spec, 0, 0); } // IDA: int __usercall GridDone@(int pCurrent_choice@, int pCurrent_mode@, int pGo_ahead@, int pEscaped@, int pTimed_out) diff --git a/src/DETHRACE/common/raycast.c b/src/DETHRACE/common/raycast.c index cb9d299f..efb22c0d 100644 --- a/src/DETHRACE/common/raycast.c +++ b/src/DETHRACE/common/raycast.c @@ -1,5 +1,6 @@ #include "raycast.h" -#include "CORE/V1DB/actsupt.h" +#include "brender.h" +#include "finteray.h" #include br_matrix34 gPick_model_to_view_raycast; //added _raycast suffix to avoid name collision @@ -12,10 +13,25 @@ br_scalar gHighest_y_below; br_actor* gY_picking_camera; br_scalar gLowest_y_above; +br_model* model_unk1; +br_material* material_unk1; + // 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); - NOT_IMPLEMENTED(); + + if (world == a) { + BrMatrix34Identity(m); + return 1; + } else { + BrTransformToMatrix34(m, &a->t); + for (a = a->parent; a && world != a; a = a->parent) { + if (a->t.type != BR_TRANSFORM_IDENTITY) { + BrMatrix34PostTransform(m, &a->t); + } + } + return world == a; + } } // IDA: void __cdecl InitRayCasting() @@ -45,8 +61,9 @@ void InitRayCasting() { // IDA: int __cdecl BadDiv(br_scalar a, br_scalar b) int BadDiv(br_scalar a, br_scalar b) { - LOG_TRACE("(%f, %f)", a, b); - NOT_IMPLEMENTED(); + //LOG_TRACE("(%f, %f)", a, b); + + return fabs(b) < 1.0 && fabs(a) > fabs(b) * BR_SCALAR_MAX; } // IDA: int __usercall PickBoundsTestRay@(br_bounds *b@, br_vector3 *rp@, br_vector3 *rd@, br_scalar t_near, br_scalar t_far, br_scalar *new_t_near, br_scalar *new_t_far) @@ -55,7 +72,56 @@ int PickBoundsTestRay(br_bounds* b, br_vector3* rp, br_vector3* rd, br_scalar t_ 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); - NOT_IMPLEMENTED(); + + 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 ActorPick2D@(br_actor *ap@, br_model *model@, br_material *material@, dr_pick2d_cbfn *callback@, void *arg) @@ -68,8 +134,86 @@ int ActorPick2D(br_actor* ap, br_model* model, br_material* material, dr_pick2d_ br_scalar t_near; br_scalar t_far; int r; + br_vector3 dir; LOG_TRACE("(%p, %p, %p, %p, %p)", ap, model, material, callback, arg); - NOT_IMPLEMENTED(); + + r = 0; + 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 == BR_RSTYLE_NONE) { + return 0; + } + m_to_v = gPick_model_to_view_raycast; + + BrMatrix34PreTransform(&gPick_model_to_view_raycast, &ap->t); + if (ap->type == BR_ACTOR_MODEL) { + BrMatrix34Inverse(&v_to_m, &gPick_model_to_view_raycast); + if (PickBoundsTestRay( + &this_model->bounds, + (br_vector3*)v_to_m.m[3], + (br_vector3*)v_to_m.m[2], + 0.0, + BR_SCALAR_MAX, + &t_near, + &t_far)) { + dir.v[0] = -v_to_m.m[2][0]; + dir.v[1] = -v_to_m.m[2][1]; + dir.v[2] = -v_to_m.m[2][2]; + + r = callback( + ap, + this_model, + this_material, + (br_vector3*)v_to_m.m[3], + &dir, + t_near, + t_far, + arg); + if (r) { + gPick_model_to_view_raycast = m_to_v; + return r; + } + } + if (r) { + gPick_model_to_view_raycast = m_to_v; + return r; + } + } else if (ap->type == BR_ACTOR_BOUNDS || ap->type == BR_ACTOR_BOUNDS_CORRECT) { + BrMatrix34Inverse(&v_to_m, &gPick_model_to_view_raycast); + if (PickBoundsTestRay( + (br_bounds*)ap->type_data, + (br_vector3*)v_to_m.m[3], + (br_vector3*)v_to_m.m[2], + 0.0, + BR_SCALAR_MAX, + &t_near, + &t_far)) { + for (a = ap->children; a != NULL; a = a->next) { + r = ActorPick2D(a, this_model, this_material, callback, arg); + if (r) { + break; + } + } + } + gPick_model_to_view_raycast = m_to_v; + return r; + } + for (a = ap->children; a != NULL; a = a->next) { + r = ActorPick2D(a, this_model, this_material, callback, arg); + if (r) { + break; + } + } + gPick_model_to_view_raycast = m_to_v; + return r; } // IDA: int __usercall DRScenePick2DXY@(br_actor *world@, br_actor *camera@, br_pixelmap *viewport@, int pick_x@, int pick_y, dr_pick2d_cbfn *callback, void *arg) @@ -90,7 +234,15 @@ int DRScenePick2D(br_actor* world, br_actor* camera, dr_pick2d_cbfn* callback, v br_scalar scale; br_camera* camera_data; LOG_TRACE("(%p, %p, %p, %p)", world, camera, callback, arg); - NOT_IMPLEMENTED(); + + camera_data = (br_camera*)camera->type_data; + DRActorToRoot(camera, world, &camera_tfm); + BrMatrix34Inverse(&gPick_model_to_view_raycast, &camera_tfm); + scale = cos(BrAngleToRadian(camera_data->field_of_view / 2)); + scale = scale / sin(scale); + + BrMatrix34PostScale(&gPick_model_to_view_raycast, scale / camera_data->aspect, scale, 1.0); + return ActorPick2D(world, model_unk1, material_unk1, callback, arg); } // IDA: int __usercall DRModelPick2D@(br_model *model@, br_material *material@, br_vector3 *ray_pos@, br_vector3 *ray_dir@, br_scalar t_near, br_scalar t_far, dr_modelpick2d_cbfn *callback, void *arg) @@ -127,13 +279,140 @@ int DRModelPick2D(br_model* model, br_material* material, br_vector3* ray_pos, b br_scalar numerator; 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); - NOT_IMPLEMENTED(); + + 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->flags & 0x1800) != 0 || d <= 0.0)) // BR_MATF_TWO_SIDED | BR_MATF_ALWAYS_VISIBLE + { + 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(numerator, d)) { + t = -(numerator / d); + if (t >= (t_near - 0.001) && t <= (t_far + 0.001)) { + 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_d = v0i2 * v1 - u1 * v0i1; + f_n = u2 * v1 - u1 * v2; + if (f_d == 0) { + continue; + } + beta = f_d / f_n; + alpha = (v0i1 - beta * v2) / v1; + } else { + beta = v0i1 / v2; + alpha = (v0i2 - beta * u2) / u1; + } + + if (alpha >= 0.0 && beta >= 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( + &map, + &V11MODEL(model)->groups[group].vertices[fp->vertices[2]].map, + s_beta); + DRVector2AccumulateScale( + &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; + } + } + r = callback( + model, + this_material, + ray_pos, + ray_dir, + t, + f, + e, + v, + &p, + &map, + arg); + if (r) { + return r; + } + } + } + } + } + } + } + return 0; } // IDA: void __usercall FindBestY(br_vector3 *pPosition@, br_actor *gWorld@, br_scalar pStarting_height, br_scalar *pNearest_y_above, br_scalar *pNearest_y_below, br_model **pNearest_above_model, br_model **pNearest_below_model, int *pNearest_above_face_index, int *pNearest_below_face_index) void FindBestY(br_vector3* pPosition, br_actor* gWorld, br_scalar pStarting_height, br_scalar* pNearest_y_above, br_scalar* pNearest_y_below, br_model** pNearest_above_model, br_model** pNearest_below_model, int* pNearest_above_face_index, int* pNearest_below_face_index) { LOG_TRACE("(%p, %p, %f, %p, %p, %p, %p, %p, %p)", pPosition, gWorld, pStarting_height, pNearest_y_above, pNearest_y_below, pNearest_above_model, pNearest_below_model, pNearest_above_face_index, pNearest_below_face_index); - NOT_IMPLEMENTED(); + + gLowest_y_above = 30000.0; + gHighest_y_below = -30000.0; + gCurrent_y = pPosition->v[1] + 0.000011920929; + gY_picking_camera->t.t.euler.t = *pPosition; + gY_picking_camera->t.t.mat.m[3][1] = gY_picking_camera->t.t.mat.m[3][1] + pStarting_height; + DRScenePick2D(gWorld, gY_picking_camera, FindHighestCallBack, 0); + *pNearest_y_above = gLowest_y_above; + *pNearest_y_below = gHighest_y_below; + *pNearest_above_model = gAbove_model; + *pNearest_below_model = gBelow_model; + *pNearest_above_face_index = gAbove_face_index; + *pNearest_below_face_index = gBelow_face_index; + LOG_DEBUG("FindBestY %f %f '%s' '%s' %d %d", gLowest_y_above, gHighest_y_below, gAbove_model->identifier, gBelow_model->identifier, gAbove_face_index, gBelow_face_index); } // IDA: int __cdecl FindYVerticallyBelowPolyCallBack(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) diff --git a/src/DETHRACE/common/raycast.h b/src/DETHRACE/common/raycast.h index 36781f45..ab85ec12 100644 --- a/src/DETHRACE/common/raycast.h +++ b/src/DETHRACE/common/raycast.h @@ -4,6 +4,16 @@ #include "br_types.h" #include "dr_types.h" +extern br_matrix34 gPick_model_to_view_raycast; //added _raycast suffix to avoid name collision +extern int gBelow_face_index; +extern br_scalar gCurrent_y; +extern int gAbove_face_index; +extern br_model* gAbove_model; +extern br_model* gBelow_model; +extern br_scalar gHighest_y_below; +extern br_actor* gY_picking_camera; +extern br_scalar gLowest_y_above; + int DRActorToRoot(br_actor* a, br_actor* world, br_matrix34* m); void InitRayCasting(); diff --git a/src/DETHRACE/common/sound.c b/src/DETHRACE/common/sound.c index c2007e85..7602062c 100644 --- a/src/DETHRACE/common/sound.c +++ b/src/DETHRACE/common/sound.c @@ -198,7 +198,8 @@ void InitSoundSources() { int toggle; tCar_spec* the_car; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + STUB(); } // IDA: void __cdecl DisposeSoundSources() diff --git a/src/DETHRACE/common/world.c b/src/DETHRACE/common/world.c index ae042e84..a4052261 100644 --- a/src/DETHRACE/common/world.c +++ b/src/DETHRACE/common/world.c @@ -2006,12 +2006,6 @@ void LoadTrack(char* pFile_name, tTrack_spec* pTrack_spec, tRace_info* pRace_inf p[0] = pRace_info->checkpoints[i].vertices[j][0]; p[1] = pRace_info->checkpoints[i].vertices[j][1]; p[2] = pRace_info->checkpoints[i].vertices[j][2]; - // v77 = p[1].v[0] - p[0].v[0]; - // v78 = p[1].v[1] - p[0].v[1]; - // v79 = p[1].v[2] - p[0].v[2]; - // v74 = p[2].v[0] - p[0].v[0]; - // v75 = p[2].v[1] - p[0].v[1]; - // v76 = p[2].v[2] - p[0].v[2]; pRace_info->checkpoints[i].normal[j].v[0] = (p[2].v[2] - p[0].v[2]) * (p[1].v[1] - p[0].v[1]) - (p[1].v[2] - p[0].v[2]) * (p[2].v[1] - p[0].v[1]); pRace_info->checkpoints[i].normal[j].v[1] = (p[1].v[2] - p[0].v[2]) * (p[2].v[0] - p[0].v[0]) - (p[2].v[2] - p[0].v[2]) * (p[1].v[0] - p[0].v[0]); pRace_info->checkpoints[i].normal[j].v[2] = (p[2].v[1] - p[0].v[1]) * (p[1].v[0] - p[0].v[0]) - (p[1].v[1] - p[0].v[1]) * (p[2].v[0] - p[0].v[0]); @@ -2104,18 +2098,16 @@ void LoadTrack(char* pFile_name, tTrack_spec* pTrack_spec, tRace_info* pRace_inf ExtractColumns(pTrack_spec); for (i = 0; gTrack_storage_space.models_count > i; ++i) { PossibleService(); - //v80 = 0; if (gTrack_storage_space.models[i] && gTrack_storage_space.models[i]->flags & 0x82) { gTrack_storage_space.models[i]->flags &= 0xFF7Du; - for (group = 0; V11MODEL(gTrack_storage_space.models[i])->ngroups > group; ++group) { - // TODO: ? - // material = gTrack_storage_space.models[i]->faces[V11MODEL(*gTrack_storage_space.models[i])->groups[group].face_user].material; - // *gTrack_storage_space.models[i]->prepared->groups[group].face_colours = (br_colour)material; - // if (material && !material->index_shade) { - // v9 = BrTableFind("DRRENDER.TAB"); - // material->index_shade = v9; - // BrMaterialUpdate(material, 0x7FFFu); - // } + for (group = 0; group < V11MODEL(gTrack_storage_space.models[i])->ngroups; group++) { + int f = V11MODEL(gTrack_storage_space.models[i])->groups[group].face_user[0]; + material = gTrack_storage_space.models[i]->faces[f].material; + V11MODEL(gTrack_storage_space.models[i])->groups[group].face_colours_material = material; + if (material && !material->index_shade) { + material->index_shade = BrTableFind("DRRENDER.TAB"); + BrMaterialUpdate(material, 0x7FFFu); + } } DodgyModelUpdate(gTrack_storage_space.models[i]); }