Textured horizons (#127)

* implements horizon textures
This commit is contained in:
Dethrace Engineering Department 2022-05-04 13:45:41 +12:00 committed by GitHub
parent 2db34d2913
commit 63d8c37b44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 82 additions and 114 deletions

View File

@ -11,7 +11,7 @@
#define BR_MAC3(a, b, c, d, e, f) ((a) * (b) + (c) * (d) + (e) * (f))
#define BR_SQR3(a, b, c) ((a) * (a) + (b) * (b) + (c) * (c))
#define BrAngleToRadian(a) ((br_scalar)((a) * (PI / 32768.0))) // a * 0.00009587379924285257
#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_VECTOR3(a, b, c) \
@ -25,8 +25,9 @@
#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 BrDegreeToAngle(d) ((br_angle)(long)((d) * (65536.0 / 360.0))) // "d * 182.044444444"
#define BrDegreeToAngle(d) ((br_angle)(long)((d) * (65536.0 / 360.0))) // "d * 182.044444444"
#define BrAngleToDegrees(a) ((br_angle)(long)((a) * (360.0 / 65536.0))) // "d * 0.0054931640625"
#define BR_SCALAR(x) ((br_scalar)(x))

View File

@ -107,4 +107,6 @@
BrVector3Scale(v1, v2, _scale); \
} while (0)
#define BR_ONE_LS 65536
#define BrFixedToFloat(s) ((float)((s) * (1.0 / (float)BR_ONE_LS)))
#endif

View File

@ -128,8 +128,7 @@ void InstantDepthChange(tDepth_effect_type pType, br_pixelmap* pSky_texture, int
// IDA: br_scalar __cdecl Tan(br_scalar pAngle)
br_scalar Tan(br_scalar pAngle) {
LOG_TRACE("(%f)", pAngle);
pAngle = sin(pAngle * 0.00009587379924285257);
return pAngle / cos(pAngle);
return sinf(BrAngleToRadian(pAngle)) / cosf(BrAngleToRadian(pAngle));
}
// IDA: br_scalar __usercall EdgeU@<ST0>(br_angle pSky@<EAX>, br_angle pView@<EDX>, br_angle pPerfect@<EBX>)
@ -349,80 +348,52 @@ void ExternalSky(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer, br_act
br_pixelmap* col_map;
LOG_TRACE("(%p, %p, %p, %p)", pRender_buffer, pDepth_buffer, pCamera, pCamera_to_world);
// TODO: Remove commented block in `ConditionallyFillWithSky` when we implement this properly
return;
dx = 0;
dst_x = 0;
col_map = gHorizon_material->colour_map;
camera = (br_camera*)pCamera->type_data;
// LOG_DEBUG("camera fov %d", camera->field_of_view);
tan_half_fov = Tan(camera->field_of_view / 2);
tan_half_hori_fov = tan_half_fov * camera->aspect;
tan_pitch = 0;
// LOG_DEBUG("tan_half_fov %f, tan_half_hori_fov %f, tan_pitch %f", tan_half_fov, tan_half_hori_fov, tan_pitch);
// LOG_DEBUG("pCamera->m[2][0] %f, pCamera->m[2][2] %f", pCamera->t.t.mat.m[2][0], pCamera->t.t.mat.m[2][2]);
// LOG_DEBUG("pCamera_to_world->m[2][0] %f, pCamera_to_world->m[2][2] %f", pCamera_to_world->m[2][0], pCamera_to_world->m[2][2]);
vert_sky = BrRadianToAngle(atan2(pCamera_to_world->m[2][0], pCamera_to_world->m[2][2]));
hori_sky = BrRadianToAngle(atan2(col_map->width * tan_half_hori_fov / (double)pRender_buffer->width, 1));
pitch = BrRadianToAngle(atan2(pCamera_to_world->m[2][0], pCamera_to_world->m[2][2]));
yaw = BrRadianToAngle(atan2(col_map->width * tan_half_hori_fov / (double)pRender_buffer->width, 1));
tan_pitch = -((double)pitch
* 0.0000152587890625
/ ((double)(uint16_t)(65520
/ (int)(1.0
/ ((double)(uint16_t)(2 * yaw) * 0.0000152587890625)
+ 0.5))
* 0.0000152587890625));
tan_half_hori_sky = -BrFixedToFloat(vert_sky) / BrFixedToFloat(BR_ANGLE_DEG(360) / (int)(1.0f / BrFixedToFloat(2 * hori_sky) + 0.5f));
// LOG_DEBUG("tan_half_fov %f, tan_half_hori_fov %f, tan_pitch %f", tan_half_fov, tan_half_hori_fov, tan_pitch);
// LOG_DEBUG("rep1 %d", (int)((double)col_map->width * tan_pitch));
for (repetitions = (int)((double)col_map->width * tan_pitch); repetitions < 0; repetitions += col_map->width) {
;
dx = col_map->width * tan_half_hori_sky;
while (dx < 0) {
dx += col_map->width;
}
// LOG_DEBUG("rep2 %d", repetitions);
while (col_map->width < repetitions) {
repetitions -= col_map->width;
while (dx > col_map->width) {
dx -= col_map->width;
}
// LOG_DEBUG("rep3 %d", repetitions);
top_y = -(pCamera_to_world->m[2][1] / sqrt(pCamera_to_world->m[2][1]) / tan_half_fov * (double)pRender_buffer->height / 2.0)
- (col_map->height - gSky_image_underground * col_map->height / gSky_image_height);
// LOG_DEBUG("gSky_image_underground %d, gSky_image_height %d", gSky_image_underground, gSky_image_height);
// LOG_DEBUG("top_y %d, r_o_x %d, repetitions %d", top_y, pRender_buffer->origin_x, repetitions);
while (pRender_buffer->width > dx) {
hori_pixels = col_map->width - repetitions;
if (hori_pixels >= pRender_buffer->width - dx) {
hori_pixels = pRender_buffer->width - dx;
hshift = col_map->height - gSky_image_underground * col_map->height / gSky_image_height;
tan_pitch = sqrtf(pCamera_to_world->m[2][0] * pCamera_to_world->m[2][0] + pCamera_to_world->m[2][2] * pCamera_to_world->m[2][2]);
hori_y = -(pCamera_to_world->m[2][1]
/ tan_pitch
/ tan_half_fov * pRender_buffer->height / 2.0f)
- hshift;
while (dst_x < pRender_buffer->width) {
hori_pixels = col_map->width - dx;
if (hori_pixels > pRender_buffer->width - dst_x) {
hori_pixels = pRender_buffer->width - dst_x;
}
DRPixelmapRectangleCopy(
pRender_buffer,
dx - pRender_buffer->origin_x,
top_y,
col_map,
repetitions - col_map->origin_x,
-col_map->origin_y,
hori_pixels,
col_map->height);
repetitions = 0;
dx += hori_pixels;
src_x = dx - col_map->origin_x;
DRPixelmapRectangleCopy(pRender_buffer, dst_x - pRender_buffer->origin_x, hori_y, col_map, src_x, -col_map->origin_y, hori_pixels, col_map->height);
dx = 0;
dst_x += hori_pixels;
}
if (top_y + pRender_buffer->origin_y > 0) {
DRPixelmapRectangleFill(
pRender_buffer,
-pRender_buffer->origin_x,
-pRender_buffer->origin_y,
pRender_buffer->width,
top_y + pRender_buffer->origin_y,
1);
top_y = hori_y + pRender_buffer->origin_y;
if (top_y > 0) {
top_col = ((tU8*)col_map->pixels)[0];
DRPixelmapRectangleFill(pRender_buffer, -pRender_buffer->origin_x, -pRender_buffer->origin_y, pRender_buffer->width, top_y, top_col);
}
bot_height = pRender_buffer->height - pRender_buffer->origin_y - top_y - col_map->height;
bot_height = pRender_buffer->height - pRender_buffer->origin_y - hori_y - col_map->height;
if (bot_height > 0) {
DRPixelmapRectangleFill(
pRender_buffer,
-pRender_buffer->origin_x,
top_y + col_map->height,
pRender_buffer->width,
bot_height,
*((tU8*)col_map->pixels + col_map->row_bytes * (col_map->height - 1) + 3));
bot_col = ((tU8*)col_map->pixels)[col_map->row_bytes * (col_map->height - 1)];
DRPixelmapRectangleFill(pRender_buffer, -pRender_buffer->origin_x, hori_y + col_map->height, pRender_buffer->width, bot_height, bot_col);
}
}
@ -478,7 +449,7 @@ void DepthEffectSky(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer, br_
LOG_TRACE("(%p, %p, %p, %p)", pRender_buffer, pDepth_buffer, pCamera, pCamera_to_world);
if (gProgram_state.current_depth_effect.sky_texture != NULL
&& (gLast_camera_special_volume == NULL || gLast_camera_special_volume->sky_col < 0)) {
&& (gLast_camera_special_volume == NULL || gLast_camera_special_volume->sky_col < 0)) {
DoHorizon(pRender_buffer, pDepth_buffer, pCamera, pCamera_to_world);
}
}
@ -671,7 +642,7 @@ void IncreaseAngle() {
for (i = 0; i < COUNT_OF(gCamera_list); i++) {
camera_ptr = gCamera_list[i]->type_data;
camera_ptr->field_of_view += 0x1c7; // 2.4993896484375 degrees
camera_ptr->field_of_view += 0x1c7; // 2.4993896484375 degrees
if (camera_ptr->field_of_view > 0x78e3) { // 169.9969482421875 degrees
camera_ptr->field_of_view = 0x78e3;
}
@ -693,7 +664,7 @@ void DecreaseAngle() {
for (i = 0; i < COUNT_OF(gCamera_list); i++) {
camera_ptr = gCamera_list[i]->type_data;
camera_ptr->field_of_view -= 0x1c7; // 2.4993896484375 degrees
camera_ptr->field_of_view -= 0x1c7; // 2.4993896484375 degrees
if (camera_ptr->field_of_view < 0x71c) { // 9.99755859375 degrees
camera_ptr->field_of_view = 0x71c;
}

View File

@ -1441,12 +1441,9 @@ int ConditionallyFillWithSky(br_pixelmap* pPixelmap) {
int bgnd_col;
LOG_TRACE("(%p)", pPixelmap);
// TODO: Uncomment when ExternalSky is fully implemented
LOG_WARN_ONCE("Uncomment this block when ExternalSky is fully implemented");
// if (gProgram_state.current_depth_effect.sky_texture != NULL
// && (gLast_camera_special_volume == NULL || gLast_camera_special_volume->sky_col < 0)) {
// return 0;
// }
if (gProgram_state.current_depth_effect.sky_texture != NULL && (gLast_camera_special_volume == NULL || gLast_camera_special_volume->sky_col < 0)) {
return 0;
}
if (gProgram_state.current_depth_effect.type == eDepth_effect_fog || gSwap_depth_effect_type == eDepth_effect_fog) {
bgnd_col = 255;

View File

@ -80,7 +80,7 @@ void AllocateCamera() {
camera_ptr = gCamera_list[i]->type_data;
camera_ptr->type = BR_CAMERA_PERSPECTIVE_FOV;
camera_ptr->field_of_view = BR_ANGLE_DEG(gCamera_angle);
camera_ptr->field_of_view = BrDegreeToAngle(gCamera_angle);
camera_ptr->hither_z = gCamera_hither;
camera_ptr->yon_z = gCamera_yon;
camera_ptr->aspect = (double)gWidth / (double)gHeight;
@ -105,7 +105,7 @@ void AllocateCamera() {
camera_ptr->hither_z = gCamera_hither;
camera_ptr->type = BR_CAMERA_PERSPECTIVE_FOV;
camera_ptr->yon_z = gCamera_yon;
camera_ptr->field_of_view = BR_ANGLE_DEG(gCamera_angle);
camera_ptr->field_of_view = BrDegreeToAngle(gCamera_angle);
camera_ptr->aspect = (double)gWidth / (double)gHeight;
gRearview_camera = BrActorAdd(gSelf, gRearview_camera);
if (gRearview_camera == NULL) {
@ -403,7 +403,7 @@ void InitialiseDeathRace(int pArgc, char** pArgv) {
PDInitialiseSystem();
InitialiseApplication(pArgc, pArgv);
//dword_112DF8 = 1; // never checked by game
// dword_112DF8 = 1; // never checked by game
}
// IDA: void __usercall InitGame(int pStart_race@<EAX>)
@ -501,7 +501,7 @@ void InitRace() {
LOG_TRACE("()");
SwitchToRealResolution();
//TODO: dword_5454C4 = 0;
// TODO: dword_5454C4 = 0;
ClearConcussion();
ClearWobbles();
ClearHeadups();
@ -510,7 +510,7 @@ void InitRace() {
PossibleService();
BuildColourTable(gRender_palette);
PossibleService();
//TODO: dword_55142C = 0;
// TODO: dword_55142C = 0;
gStart_race_sent = 0;
gProgram_state.frame_rate_headup = NewTextHeadupSlot(0, 0, 0, -1, "");
if (TranslationMode()) {
@ -619,7 +619,7 @@ void InitRace() {
// IDA: void __cdecl DisposeRace()
void DisposeRace() {
LOG_TRACE("()");
PossibleService();
DisposePiping();
PossibleService();

View File

@ -562,7 +562,7 @@ tRace_result MainGameLoop() {
gNasty_kludgey_cockpit_variable = 1;
ToggleCockpit();
}
gOur_pos = &gSelf->t.t.euler.t;
gOur_pos = &gSelf->t.t.translate.t;
PositionExternalCamera(&gProgram_state.current_car, camera_period);
BrActorToActorMatrix34(&gCamera_to_world, gCamera, gUniverse_actor);
BrActorToActorMatrix34(&gRearview_camera_to_world, gRearview_camera, gUniverse_actor);

View File

@ -18,7 +18,7 @@
#define FLAG_WAVING_BASTARD_REF 99
#define FOURCC(A,B,C,D) (((A & 0xff) << 24) | ((B & 0xff) << 16)| ((C & 0xff) << 8)| ((D & 0xff) << 0))
#define FOURCC(A, B, C, D) (((A & 0xff) << 24) | ((B & 0xff) << 16) | ((C & 0xff) << 8) | ((D & 0xff) << 0))
#define PEDESTRIAN_MAGIC FOURCC('P', 'e', 'd', '!')
#define ActorToPedestrianData(ACTOR) ((tPedestrian_data*)((ACTOR)->type_data))
@ -487,7 +487,7 @@ void MungePedModel(tPedestrian_data* pPedestrian) {
} else {
temp_scalar = ((double)(GetTotalTime() - pPedestrian->last_action_change) / pPedestrian->spin_period * 360.0 + 360.0);
}
DRMatrix34PostRotateZ(&pPedestrian->actor->t.t.mat, BR_ANGLE_DEG(temp_scalar));
DRMatrix34PostRotateZ(&pPedestrian->actor->t.t.mat, BrDegreeToAngle(temp_scalar));
BrMatrix34PostTranslate(&pPedestrian->actor->t.t.mat, 0.0, height_over2, 0.0);
}
temp_scalar = FastScalarArcTan2Angle(gCamera_to_world.m[2][0], gCamera_to_world.m[2][2]);
@ -781,8 +781,8 @@ int GetPedPosition(int pIndex, br_vector3* pPos) {
pedestrian = &gPedestrian_array[pIndex];
if (pedestrian->ref_number < 100) {
if (pedestrian->hit_points == -100 || pedestrian->current_action == pedestrian->fatal_car_impact_action
|| pedestrian->current_action == pedestrian->fatal_ground_impact_action
|| pedestrian->current_action == pedestrian->giblets_action) {
|| pedestrian->current_action == pedestrian->fatal_ground_impact_action
|| pedestrian->current_action == pedestrian->giblets_action) {
return 0;
} else {
*pPos = pedestrian->pos;

View File

@ -15,7 +15,7 @@ br_scalar gHighest_y_below;
br_actor* gY_picking_camera;
br_scalar gLowest_y_above;
//Added, probably can be replaced with NULL
// Added, probably can be replaced with NULL
br_model* model_unk1;
br_material* material_unk1;
@ -41,37 +41,35 @@ int DRActorToRoot(br_actor* a, br_actor* world, br_matrix34* m) {
void InitRayCasting() {
br_camera* camera_ptr;
LOG_TRACE("()");
br_actor* a;
a = BrActorAllocate(BR_ACTOR_CAMERA, NULL);
camera_ptr = a->type_data;
gY_picking_camera = BrActorAllocate(BR_ACTOR_CAMERA, NULL);
camera_ptr = gY_picking_camera->type_data;
camera_ptr->type = BR_CAMERA_PERSPECTIVE_FOV;
camera_ptr->field_of_view = BR_ANGLE_DEG(70.0f);
camera_ptr->hither_z = 0.001;
camera_ptr->yon_z = 1000.0;
camera_ptr->aspect = 1.0;
a->t.t.quat.q.x = 1.0;
a->t.t.quat.q.y = 0.0;
a->t.t.quat.q.z = 0.0;
a->t.t.quat.q.w = 0.0;
a->t.t.mat.m[1][1] = 0.0;
a->t.t.mat.m[1][2] = -1.0;
a->t.t.mat.m[2][0] = 0.0;
a->t.t.mat.m[2][1] = 1.0;
a->t.t.mat.m[2][2] = 0.0;
gY_picking_camera = a;
camera_ptr->field_of_view = BrDegreeToAngle(70.0f);
camera_ptr->hither_z = 0.001f;
camera_ptr->yon_z = 1000.0f;
camera_ptr->aspect = 1.0f;
gY_picking_camera->t.t.mat.m[0][0] = 1.0;
gY_picking_camera->t.t.mat.m[0][1] = 0.0;
gY_picking_camera->t.t.mat.m[0][2] = 0.0;
gY_picking_camera->t.t.mat.m[1][0] = 0.0;
gY_picking_camera->t.t.mat.m[1][1] = 0.0;
gY_picking_camera->t.t.mat.m[1][2] = -1.0;
gY_picking_camera->t.t.mat.m[2][0] = 0.0;
gY_picking_camera->t.t.mat.m[2][1] = 1.0;
gY_picking_camera->t.t.mat.m[2][2] = 0.0;
}
// IDA: int __cdecl BadDiv(br_scalar a, br_scalar b)
// Suffix added to avoid duplicate symbol
int BadDiv__raycast(br_scalar a, br_scalar b) {
//LOG_TRACE("(%f, %f)", a, b);
// LOG_TRACE("(%f, %f)", a, b);
return fabs(b) < 1.0 && fabs(a) > fabs(b) * BR_SCALAR_MAX;
}
//IDA: void __usercall DRVector2AccumulateScale(br_vector2 *a@<EAX>, br_vector2 *b@<EDX>, br_scalar s)
// Suffix added to avoid duplicate symbol
// IDA: void __usercall DRVector2AccumulateScale(br_vector2 *a@<EAX>, br_vector2 *b@<EDX>, br_scalar s)
// Suffix added to avoid duplicate symbol
void DRVector2AccumulateScale__raycast(br_vector2* a, br_vector2* b, br_scalar s) {
LOG_TRACE("(%p, %p, %f)", a, b, s);
@ -402,8 +400,8 @@ int DRModelPick2D__raycast(br_model* model, br_material* material, br_vector3* 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)
// Suffix added to avoid duplicate symbol
// 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)
// Suffix added to avoid duplicate symbol
int FindHighestPolyCallBack__raycast(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) {
br_scalar the_y;
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);
@ -422,8 +420,8 @@ int FindHighestPolyCallBack__raycast(br_model* pModel, br_material* pMaterial, b
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)
// Suffix added to avoid duplicate symbol
// 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)
// Suffix added to avoid duplicate symbol
int FindHighestCallBack__raycast(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);
@ -450,7 +448,7 @@ void FindBestY(br_vector3* pPosition, br_actor* gWorld, br_scalar pStarting_heig
*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);
// 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)

View File

@ -2387,10 +2387,9 @@ void LoadTrack(char* pFile_name, tTrack_spec* pTrack_spec, tRace_info* pRace_inf
}
PossibleService();
gSky_image_width = (360.0 / (double)BR_ANGLE_DEG(GetAnInt(f)));
gSky_image_height = BR_ANGLE_DEG(GetAScalar(f));
gSky_image_underground = (uint16_t)gSky_image_height * (sky_pixels_high - GetAnInt(f)) / sky_pixels_high;
gSky_image_width = (360.0 / BrDegreeToAngle(GetAnInt(f)));
gSky_image_height = BrDegreeToAngle(GetAScalar(f));
gSky_image_underground = gSky_image_height * (sky_pixels_high - GetAnInt(f)) / sky_pixels_high;
MungeRearviewSky();
PossibleService();