diff --git a/src/BRSRC13/include/brender/brender.h b/src/BRSRC13/include/brender/brender.h index 91ad596b..c268d57d 100644 --- a/src/BRSRC13/include/brender/brender.h +++ b/src/BRSRC13/include/brender/brender.h @@ -43,7 +43,7 @@ br_pixelmap* BrMapAdd(br_pixelmap* pixelmap); br_pixelmap* BrMapRemove(br_pixelmap* pixelmap); br_pixelmap* BrMapFind(char* pattern); br_uint_32 BrMapAddMany(br_pixelmap** items, int n); -br_map_find_cbfn* BrMapFindHook(br_map_find_cbfn* hook) ; +br_map_find_cbfn* BrMapFindHook(br_map_find_cbfn* hook); // BrMaterial br_material* BrMaterialAllocate(char* name); @@ -90,6 +90,10 @@ void BrMatrix34PostShearZ(br_matrix34* mat, br_scalar sx, br_scalar sy); void BrMatrix4Copy(br_matrix4* A, br_matrix4* B); br_scalar BrMatrix4Inverse(br_matrix4* A, br_matrix4* B); void BrMatrix4TApply(br_vector4* A, br_vector4* B, br_matrix4* C); +void BrMatrix4ApplyP(br_vector4* A, br_vector3* B, br_matrix4* C); +void BrMatrix4Perspective(br_matrix4* mat, br_angle field_of_view, br_scalar aspect, br_scalar hither, br_scalar yon); +void BrMatrix4Scale(br_matrix4* mat, br_scalar sx, br_scalar sy, br_scalar sz); +void BrMatrix4Mul(br_matrix4* A, br_matrix4* B, br_matrix4* C); // BrMem void BrMemFree(void* block); @@ -133,7 +137,6 @@ void* BrResRemove(void* vres); void BrResFree(void* vres); char* BrResStrDup(void* vparent, char* str); - // BrTable br_pixelmap* BrTableAdd(br_pixelmap* pixelmap); br_pixelmap* BrTableFind(char* pattern); diff --git a/src/DETHRACE/common/car.c b/src/DETHRACE/common/car.c index 4b3bb2db..67ba6606 100644 --- a/src/DETHRACE/common/car.c +++ b/src/DETHRACE/common/car.c @@ -50,11 +50,19 @@ int gFace_num__car = 1; // suffix added to avoid duplicate symbol br_angle gOld_yaw__car; // suffix added to avoid duplicate symbol br_angle gOld_zoom; br_vector3 gCamera_pos_before_collide; -int gMetal_crunch_sound_id__car[5] = { // suffix added to avoid duplicate symbol - 5000, 5001, 5002, 5003, 5004, +int gMetal_crunch_sound_id__car[5] = { + // suffix added to avoid duplicate symbol + 5000, + 5001, + 5002, + 5003, + 5004, }; -int gMetal_scrape_sound_id__car[3] = { // suffix added to avoid duplicate symbol - 5010, 5011, 5012, +int gMetal_scrape_sound_id__car[3] = { + // suffix added to avoid duplicate symbol + 5010, + 5011, + 5012, }; int gCar_car_collisions; int gFreeze_mechanics; @@ -116,7 +124,7 @@ void DamageUnit(tCar_spec* pCar, int pUnit_type, int pDamage_amount) { the_damage = &pCar->damage_units[pUnit_type]; the_damage->damage_level += pDamage_amount; if (the_damage->damage_level >= 100) { - the_damage->damage_level = 99; + the_damage->damage_level = 99; } } } @@ -804,14 +812,11 @@ void CalcEngineForce(tCar_spec* c, br_scalar dt) { c->acc_force = 0.0; if (c->revs == 0.0) { - //LOG_DEBUG("changedown1"); c->gear = 0; } sign = c->gear < 0 || (!c->gear && c->velocity_car_space.v[2] > 0.5); if (c->keys.backwards != sign) { c->keys.backwards = !c->keys.backwards; - //LOG_PANIC("not expected"); - temp_for_swap = c->keys.acc; c->keys.acc = c->keys.dec; c->keys.dec = temp_for_swap; @@ -2209,7 +2214,7 @@ void CalcForce(tCar_spec* c, br_scalar dt) { AddDrag(c, dt); if (c->driver >= eDriver_net_human) { c->acc_force = -(v136.v[2] * force[0]) - v136.v[2] * force[1]; - //LOG_DEBUG("old %f new %f", old, c->acc_force); + // LOG_DEBUG("old %f new %f", old, c->acc_force); } } @@ -2224,7 +2229,6 @@ void DoRevs(tCar_spec* c, br_scalar dt) { + c->car_master_actor->t.t.mat.m[2][1] * c->v.v[1] + c->car_master_actor->t.t.mat.m[2][0] * c->v.v[0]); - //LOG_DEBUG("ts %f, acc %f", ts, c->acc_force); if (c->gear) { c->target_revs = ts / c->speed_revs_ratio / (double)c->gear; } else { @@ -2820,14 +2824,57 @@ void SkidNoise(tCar_spec* pC, int pWheel_num, br_scalar pV, int material) { int i; LOG_TRACE("(%p, %d, %f, %d)", pC, pWheel_num, pV, material); - STUB_ONCE(); + i = IRandomBetween(0, 1); + if (gCurrent_race.material_modifiers[material].tyre_noise_index == -1) { + return; + } + if (IRandomBetween(0, 4) != 0) { + return; + } + + last_skid_vol[i] = pV * 10.0; + if ((pWheel_num & 1) != 0) { + pos.v[0] = pC->bounds[1].max.v[0]; + } else { + pos.v[0] = pC->bounds[1].min.v[0]; + } + pos.v[1] = pC->wpos[pWheel_num].v[1] - pC->oldd[pWheel_num]; + pos.v[2] = pC->wpos[pWheel_num].v[2]; + BrMatrix34ApplyP(&world_pos, &pos, &pC->car_master_actor->t.t.mat); + BrVector3InvScale(&world_pos, &world_pos, WORLD_SCALE); + if (!DRS3SoundStillPlaying(gSkid_tag[i]) || (pC->driver == eDriver_local_human && gLast_car_to_skid[i] != pC)) { + gSkid_tag[i] = DRS3StartSound3D( + gIndexed_outlets[1], + IRandomBetween(0, 4) + 9000, + &world_pos, + &pC->velocity_bu_per_sec, + 1, + last_skid_vol[i], + IRandomBetween(49152, 81920), + 0x10000); + gLast_car_to_skid[i] = pC; + } + if (gCurrent_race.material_modifiers[material].smoke_type == 1) { + BrVector3Cross(&wv, &pC->omega, &pos); + BrVector3Add(&wv, &wv, &pC->velocity_car_space); + ts = -(BrVector3Dot(&wv, &pC->road_normal)); + BrVector3Scale(&wvw, &pC->road_normal, ts); + BrVector3Add(&wv, &wv, &wvw); + BrMatrix34ApplyV(&wvw, &wv, &pC->car_master_actor->t.t.mat); + CreatePuffOfSmoke(&world_pos, &wvw, pV / 25.0, 1.0, 4, pC); + } } // IDA: void __usercall StopSkid(tCar_spec *pC@) void StopSkid(tCar_spec* pC) { LOG_TRACE("(%p)", pC); - STUB_ONCE(); + if (gLast_car_to_skid[0] == pC) { + DRS3StopSound(gSkid_tag[0]); + } + if (gLast_car_to_skid[1] == pC) { + DRS3StopSound(gSkid_tag[1]); + } } // IDA: void __usercall CrashNoise(br_vector3 *pForce@, br_vector3 *position@, int material@) @@ -2844,7 +2891,8 @@ void CrashNoise(br_vector3* pForce, br_vector3* position, int material) { vol = 255; } if (crunch_tag == 0 || (!DRS3SoundStillPlaying(crunch_tag) && vol > 30)) { - last_crunch_vol = vol; (void)last_crunch_vol; + last_crunch_vol = vol; + (void)last_crunch_vol; BrVector3Set(&velocity, 0.f, 0.f, 0.f); crunch_tag = DRS3StartSound3D(gIndexed_outlets[1], gMetal_crunch_sound_id__car[IRandomBetween(0, COUNT_OF(gMetal_crunch_sound_id__car) - 1)], @@ -4835,7 +4883,7 @@ int CollideCamera2(br_vector3* car_pos, br_vector3* cam_pos, br_vector3* old_cam 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; + // 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]; diff --git a/src/DETHRACE/common/graphics.c b/src/DETHRACE/common/graphics.c index a276b20f..0ebf4ba5 100644 --- a/src/DETHRACE/common/graphics.c +++ b/src/DETHRACE/common/graphics.c @@ -97,6 +97,7 @@ br_matrix34 gIdentity34 = { tShadow_level gShadow_level = eShadow_us_only; br_scalar gShadow_hither_z_move; br_scalar gShadow_hither_min_move; +/* clang-format off */ // arrows pointing to 180, 202, 224, 246 degrees (step = 90 / 4 = 22(.5) degrees) int gArrows[2][4][60] = { @@ -119,8 +120,10 @@ int gArrows[2][4][60] = 0, 3, -1, 3, -2, 3, -2, 2, -2, 1, -2, 0, -3, 0, -3, -1, }, }, }; +/* clang-format on */ + float gMap_render_x = 80.f; -float gMap_render_y = 6.f; +float gMap_render_y = 6.f; float gMap_render_width = 64.f; float gMap_render_height = 40.f; int gMouse_started; @@ -782,16 +785,16 @@ void DrawMapBlip(tCar_spec* pCar, tU32 pTime, br_matrix34* pTrans, br_vector3* p time_diff = pTime - gMap_mode; BrMatrix34ApplyP(&map_pos, pPos, &gCurrent_race.map_transformation); switch (gReal_graf_data_index) { - case 0: - break; - case 1: - map_pos.v[0] = map_pos.v[0] * 2.f; - map_pos.v[1] = map_pos.v[1] * 2.f + 40.f; - break; - default: - TELL_ME_IF_WE_PASS_THIS_WAY(); + case 0: + break; + case 1: + map_pos.v[0] = map_pos.v[0] * 2.f; + map_pos.v[1] = map_pos.v[1] * 2.f + 40.f; + break; + default: + TELL_ME_IF_WE_PASS_THIS_WAY(); } - period = 256; // Must be power of 2 + period = 256; // Must be power of 2 colours[0] = pColour; colours[1] = OppositeColour(pColour); BrMatrix34Mul(&car_in_map_space, pTrans, &gCurrent_race.map_transformation); @@ -829,24 +832,24 @@ void DrawMapBlip(tCar_spec* pCar, tU32 pTime, br_matrix34* pTrans, br_vector3* p if (gNet_mode != eNet_mode_none && gCurrent_net_game->type == eNet_game_type_foxy && gNet_players[gIt_or_fox].car == pCar) { from_x = map_pos.v[0] - 8.f; from_y = map_pos.v[1] - 8.f; - to_x = map_pos.v[0] + 8.f; - to_y = map_pos.v[1] + 8.f; - BrPixelmapLine(gBack_screen, from_x, from_y, to_x, from_y, colour); - BrPixelmapLine(gBack_screen, from_x, to_y, to_x, to_y, colour); + to_x = map_pos.v[0] + 8.f; + to_y = map_pos.v[1] + 8.f; + BrPixelmapLine(gBack_screen, from_x, from_y, to_x, from_y, colour); + BrPixelmapLine(gBack_screen, from_x, to_y, to_x, to_y, colour); BrPixelmapLine(gBack_screen, from_x, from_y, from_x, to_y, colour); - BrPixelmapLine(gBack_screen, to_x, from_y, to_x, to_y, colour); + BrPixelmapLine(gBack_screen, to_x, from_y, to_x, to_y, colour); } - // To attract the player's attention, draw a rectangle around the player's position that decreases in size, + // To attract the player's attention, draw a rectangle around the player's position that decreases in size, if (time_diff <= 500 && pCar->driver == eDriver_local_human) { offset = ((500 - time_diff) * 70) / 500; from_x = map_pos.v[0] - offset - .5f; from_y = map_pos.v[1] - offset - .5f; - to_x = map_pos.v[0] + offset + .5f; - to_y = map_pos.v[1] + offset + .5f; - BrPixelmapLine(gBack_screen, from_x, from_y, to_x, from_y, colour); - BrPixelmapLine(gBack_screen, from_x, to_y, to_x, to_y, colour); - BrPixelmapLine(gBack_screen, from_x, from_y, from_x, to_y, colour); - BrPixelmapLine(gBack_screen, to_x, from_y, to_x, to_y, colour); + to_x = map_pos.v[0] + offset + .5f; + to_y = map_pos.v[1] + offset + .5f; + BrPixelmapLine(gBack_screen, from_x, from_y, to_x, from_y, colour); + BrPixelmapLine(gBack_screen, from_x, to_y, to_x, to_y, colour); + BrPixelmapLine(gBack_screen, from_x, from_y, from_x, to_y, colour); + BrPixelmapLine(gBack_screen, to_x, from_y, to_x, to_y, colour); } } @@ -2635,28 +2638,28 @@ void DRPixelmapDoubledCopy(br_pixelmap* pDestn, br_pixelmap* pSource, int pSourc dst_row_skip = 2 * pDestn->row_bytes - 2 * pSource_width; src_row_skip = (pSource->row_bytes - pSource_width) / 2; - sptr = (tU16*)((tU8*)pSource->pixels - 2 * src_row_skip + (pSource->row_bytes * pSource_height / 2) * 2); - dptr = (tU8*)pDestn->pixels + pSource_width * 2 + (2 * pSource_height + pY_offset) * pDestn->row_bytes - pDestn->row_bytes; + sptr = (tU16*)((tU8*)pSource->pixels - 2 * src_row_skip + (pSource->row_bytes * pSource_height / 2) * 2); + dptr = (tU8*)pDestn->pixels + pSource_width * 2 + (2 * pSource_height + pY_offset) * pDestn->row_bytes - pDestn->row_bytes; dptr2 = dptr - pDestn->row_bytes; width_over_2 = pSource_width / 2; for (i = 0; i < pSource_height; i++) { for (j = 0; j < width_over_2; j++) { --sptr; - pixels = *sptr; + pixels = *sptr; pixel_1 = pixels >> 8; pixel_2 = pixels >> 0; - dptr [-1] = pixel_1; + dptr[-1] = pixel_1; dptr2[-1] = pixel_1; - dptr [-2] = pixel_1; + dptr[-2] = pixel_1; dptr2[-2] = pixel_1; - dptr [-3] = pixel_2; + dptr[-3] = pixel_2; dptr2[-3] = pixel_2; - dptr [-4] = pixel_2; + dptr[-4] = pixel_2; dptr2[-4] = pixel_2; dptr -= 4; dptr2 -= 4; } - dptr -= dst_row_skip; + dptr -= dst_row_skip; dptr2 -= dst_row_skip; sptr -= src_row_skip; } diff --git a/src/DETHRACE/common/input.c b/src/DETHRACE/common/input.c index ced26e52..0dda8a64 100644 --- a/src/DETHRACE/common/input.c +++ b/src/DETHRACE/common/input.c @@ -207,7 +207,7 @@ tU32* KevKeyService() { tU32 keys; keys = gKeys_pressed; - //printf("key: %d, %lx, %lx\n", sizeof(long), keys, code2); + // printf("key: %d, %lx, %lx\n", sizeof(long), keys, code2); return_val[0] = 0; return_val[1] = 0; @@ -240,12 +240,12 @@ tU32* KevKeyService() { code += keys << 11; code = (code >> 17) + (code << 4); code2 = (code2 >> 29) + keys * keys + (code2 << 3); - //printf("accumulate: keys=%lx, sum=%lx, code=%lx, code2=%lx\n", keys, sum, code, code2); + // printf("accumulate: keys=%lx, sum=%lx, code=%lx, code2=%lx\n", keys, sum, code, code2); last_time = PDGetTotalTime(); } else if (PDGetTotalTime() > (last_time + 1000)) { return_val[0] = ((code >> 11) + (sum << 21)); return_val[1] = code2; - //printf("final value: code=%lx, code2=%lx\n", return_val[0], return_val[1]); + // printf("final value: code=%lx, code2=%lx\n", return_val[0], return_val[1]); code = 0; code2 = 0; sum = 0; @@ -692,7 +692,7 @@ void DoRLTypeLetter(int pChar, int pSlot_index) { int new_len; LOG_TRACE("(%d, %d)", pChar, pSlot_index); - //v2 = pSlot_index; + // v2 = pSlot_index; if (pChar >= 32) { if (gInsert_mode) { new_len = strlen(gCurrent_typing) + 1; @@ -782,7 +782,7 @@ void TypeKey(int pSlot_index, char pKey) { case KEY_RIGHT: DoRLCursorRight(pSlot_index); break; - default: + default: DoRLTypeLetter(PDGetASCIIFromKey(pKey), pSlot_index); break; } diff --git a/src/DETHRACE/common/spark.c b/src/DETHRACE/common/spark.c index f181597d..0d1a3d37 100644 --- a/src/DETHRACE/common/spark.c +++ b/src/DETHRACE/common/spark.c @@ -8,6 +8,7 @@ #include "graphics.h" #include "harness/trace.h" #include "loading.h" +#include "piping.h" #include "utility.h" #include "world.h" @@ -64,7 +65,10 @@ void SetWorldToScreen(br_pixelmap* pScreen) { br_matrix4 mat; br_matrix4 mat2; LOG_TRACE("(%p)", pScreen); - NOT_IMPLEMENTED(); + + BrMatrix4Perspective(&mat, gSpark_cam->field_of_view, gSpark_cam->aspect, -gSpark_cam->hither_z, -gSpark_cam->yon_z); + BrMatrix4Scale(&mat2, pScreen->width / 2, pScreen->height / 2, 1.0); + BrMatrix4Mul(&gCameraToScreen, &mat, &mat2); } // IDA: void __usercall DrawLine3DThroughBRender(br_vector3 *pStart@, br_vector3 *pEnd@) @@ -140,6 +144,10 @@ void RenderSparks(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_ac br_vector3 new_pos; br_scalar ts; LOG_TRACE("(%p, %p, %p, %p, %d)", pRender_screen, pDepth_buffer, pCamera, pCamera_to_world, pTime); + + gSpark_cam = pCamera->type_data; + SetWorldToScreen(pRender_screen); + STUB_ONCE(); } @@ -494,7 +502,23 @@ void SmokeLine(int l, int x, br_scalar zbuff, int r_squared, tU8* scr_ptr, tU16* int shade_offset_int; tU16 z; LOG_TRACE("(%d, %d, %f, %d, %p, %p, %p, %f, %f, %f)", l, x, zbuff, r_squared, scr_ptr, depth_ptr, shade_ptr, r_multiplier, z_multiplier, shade_offset); - NOT_IMPLEMENTED(); + + scr_ptr += gOffset; + if (gProgram_state.cockpit_on) { + depth_ptr += gOffset; + } + z = (int)(uint16_t)(int)((1.0 - zbuff) * 32768.0); + for (i = 0; i < l; i++) { + if (*depth_ptr > z) { + shade_offset_int = (((int)((int)(shade_offset * 65536.0) - r_squared * (int)(r_multiplier * 65536.0)) >> 8) & 0xFFFFFF00); + *scr_ptr = shade_ptr[*scr_ptr + shade_offset_int]; + } + r_multiplier_int = x + r_squared; + scr_ptr++; + x++; + depth_ptr++; + r_squared = x + r_multiplier_int; + } } // IDA: void __usercall SmokeCircle(br_vector3 *o@, br_scalar r, br_scalar extra_z, br_scalar strength, br_scalar pAspect, br_pixelmap *pRender_screen, br_pixelmap *pDepth_buffer, br_pixelmap *pShade_table) @@ -527,7 +551,153 @@ void SmokeCircle(br_vector3* o, br_scalar r, br_scalar extra_z, br_scalar streng br_scalar aspect_squared; void (*line)(int, int, br_scalar, int, tU8*, tU16*, tU8*, br_scalar, br_scalar, br_scalar); LOG_TRACE("(%p, %f, %f, %f, %f, %p, %p, %p)", o, r, extra_z, strength, pAspect, pRender_screen, pDepth_buffer, pShade_table); - NOT_IMPLEMENTED(); + + line = SmokeLine; + ox = pRender_screen->width / 2 + o->v[0]; + oy = pRender_screen->height / 2 + o->v[1]; + max_r_squared = r * r; + zbuff = o->v[2]; + aspect_squared = pAspect * pAspect; + if (pRender_screen->width / 4 <= r + || pRender_screen->width <= ox - r + || ox + r < 0.0f) { + return; + } + shade_ptr = (tU8*)pShade_table->pixels + pShade_table->row_bytes * (pShade_table->base_y + 1); + shade_offset = strength * 14.99; + r_multiplier = shade_offset / (double)max_r_squared; + z_multiplier = extra_z / (double)max_r_squared; + max_x = pRender_screen->width - ox - 1; + min_x = -ox; + ry = r / pAspect; + l = pRender_screen->height - oy - 1; + scr_ptr = pRender_screen->pixels; + scr_ptr += pRender_screen->base_x + pRender_screen->base_y * pRender_screen->row_bytes + ox + l * pRender_screen->row_bytes; + depth_ptr = (tU16*)((char*)pDepth_buffer->pixels + 2 * ox + 2 * l * (pDepth_buffer->row_bytes / 2)); + osp = scr_ptr; + odp = depth_ptr; + if (pRender_screen->height > oy && oy + ry >= 0.0) { + r_squared = (r * r); + inc = -r; + y = 0; + y_limit = ry; + if (oy < 0) { + y = -oy; + r_squared = (-oy * -oy) * aspect_squared; + scr_ptr += oy * pRender_screen->row_bytes; + depth_ptr += oy * (pDepth_buffer->row_bytes / 2); + inc = -sqrtf(max_r_squared - r_squared); + r_squared += inc * inc; + } + if (pRender_screen->height < oy + ry) { + y_limit = pRender_screen->height - oy - 1; + } + l = -2 * inc; + scr_ptr += inc; + depth_ptr += inc; + gOffset = 0; + while (1) { + x = inc + gOffset; + if (min_x <= inc + gOffset && l + x - 1 <= max_x) { + line(l, inc, zbuff, r_squared, scr_ptr, depth_ptr, shade_ptr, r_multiplier, z_multiplier, shade_offset); + } else { + if (max_x < x || l + x < min_x) { + break; + } + x2 = l; + if (l + x - 1 - max_x > 0) { + x2 = max_x - (x - 1); + } + if (min_x - x <= 0) { + line(x2, inc, zbuff, r_squared, scr_ptr, depth_ptr, shade_ptr, r_multiplier, z_multiplier, shade_offset); + } else { + line(x2 - (min_x - x), min_x - x + inc, zbuff, y * y + (min_x - x + inc) * (min_x - x + inc), &scr_ptr[min_x - x], &depth_ptr[min_x - x], shade_ptr, r_multiplier, z_multiplier, shade_offset); + } + } + if (y_limit <= y) { + break; + } + ++y; + scr_ptr -= pRender_screen->row_bytes; + depth_ptr -= pDepth_buffer->row_bytes / 2; + for (r_squared += (2 * y - 1) * aspect_squared; max_r_squared < r_squared && inc < 0; r_squared += 2 * inc - 1) { + inc++; + scr_ptr++; + depth_ptr++; + l -= 2; + } + gOffset += IRandomBetween(-1, 1); + if (gOffset > r / 5.0) { + gOffset = r / 5.0; + } + if (gOffset < -(r / 5.0)) { + gOffset = -(r / 5.0); + } + } + } + if (pAspect < 1.0) { + aspect_squared = 9.0; + ry = r / 3.0; + } + if (oy > 0 && oy <= pRender_screen->height + ry - 2.0) { + r_squared = (r * r); + inc = -r; + y = 0; + scr_ptr = osp; + depth_ptr = odp; + y_limit = ry; + if (pRender_screen->height < oy) { + l2 = oy - pRender_screen->height; + y = pRender_screen->height - oy; + r_squared = y * y * aspect_squared; + scr_ptr = &osp[l2 * pRender_screen->row_bytes]; + depth_ptr = &odp[l2 * (pDepth_buffer->row_bytes / 2)]; + inc = -sqrtf(max_r_squared - r_squared); + r_squared += inc * inc; + } + if (oy - ry < 0.0) { + y_limit = oy; + } + l = -2 * inc; + scr_ptr += inc; + depth_ptr += inc; + gOffset = 0; + do { + y--; + scr_ptr += pRender_screen->row_bytes; + depth_ptr += pDepth_buffer->row_bytes / 2; + for (r_squared -= (2 * y - 1) * aspect_squared; max_r_squared < r_squared && inc < 0; r_squared += 2 * inc - 1) { + inc++; + scr_ptr++; + depth_ptr++; + l -= 2; + } + x = inc + gOffset; + if (min_x <= inc + gOffset && l + x - 1 <= max_x) { + line(l, inc, zbuff, r_squared, scr_ptr, depth_ptr, shade_ptr, r_multiplier, z_multiplier, shade_offset); + } else { + if (max_x < x || l + x < min_x) { + return; + } + x2 = l; + if (l + x - 1 - max_x > 0) { + x2 = max_x - (x - 1); + } + if (min_x - x <= 0) { + line(x2, inc, zbuff, r_squared, scr_ptr, depth_ptr, shade_ptr, r_multiplier, z_multiplier, shade_offset); + } else { + line(x2 - (min_x - x), min_x - x + inc, zbuff, y * y + (min_x - x + inc) * (min_x - x + inc), &scr_ptr[min_x - x], &depth_ptr[min_x - x], shade_ptr, r_multiplier, z_multiplier, shade_offset); + } + } + gOffset += IRandomBetween(-1, 1); + if (gOffset > r / 5.0) { + gOffset = r / 5.0; + } + if (gOffset < -(r / 5.0)) { + gOffset = -r / 5.0; + } + } while (-y < y_limit); + } } // IDA: int __cdecl CmpSmokeZ(void *p1, void *p2) @@ -566,7 +736,21 @@ void SmokeCircle3D(br_vector3* o, br_scalar r, br_scalar strength, br_scalar pAs int scaled_r; br_scalar extra_z; LOG_TRACE("(%p, %f, %f, %f, %p, %p, %p, %p)", o, r, strength, pAspect, pRender_screen, pDepth_buffer, pShade_table, pCam); - NOT_IMPLEMENTED(); + + cam = pCam->type_data; + srand(o->v[2] * 16777216.0 + o->v[1] * 65536.0 + o->v[0] * 256.0 + r); + BrVector3Sub(&tv, o, (br_vector3*)gCamera_to_world.m[3]); + BrMatrix34TApplyV(&p, &tv, &gCamera_to_world); + + if (-p.v[2] >= cam->hither_z && -p.v[2] <= cam->yon_z) { + scaled_r = gCameraToScreen.m[0][0] * r / -p.v[2]; + extra_z = gCameraToScreen.m[3][2] * r / (p.v[2] * p.v[2]); + BrMatrix4ApplyP(&o2, &p, &gCameraToScreen); + p.v[0] = o2.v[0] / o2.v[3]; + p.v[1] = o2.v[1] / o2.v[3]; + p.v[2] = o2.v[2] / o2.v[3]; + SmokeCircle(&p, (br_scalar)scaled_r, extra_z, strength, pAspect, pRender_screen, pDepth_buffer, pShade_table); + } } // IDA: void __usercall ReplaySmoke(br_pixelmap *pRender_screen@, br_pixelmap *pDepth_buffer@, br_actor *pCamera@) @@ -609,7 +793,93 @@ void RenderSmoke(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_act tU32 seed; tU32 not_lonely; LOG_TRACE("(%p, %p, %p, %p, %d)", pRender_screen, pDepth_buffer, pCamera, pCamera_to_world, pTime); - STUB_ONCE(); + + not_lonely = 0; + DrawTheGlow(pRender_screen, pDepth_buffer, pCamera); + + if (gSmoke_flags) { + seed = rand(); + if (gAction_replay_mode) { + ReplaySmoke(pRender_screen, pDepth_buffer, pCamera); + srand(seed); + } else { + StartPipingSession(ePipe_chunk_smoke); + for (i = 0; i < COUNT_OF(gSmoke); i++) { + if ((gSmoke_flags & (1 << i)) != 0) { + if (gSmoke[i].strength > 0.0) { + if (gSmoke[i].time_sync) { + BrVector3Scale(&tv, &gSmoke[i].v, gSmoke[i].time_sync / 1000.0); + // tv.v[0] = gSmoke[i].time_sync / 1000.0 * gSmoke[i].v.v[0]; + // tv.v[1] = gSmoke[i].time_sync / 1000.0 * gSmoke[i].v.v[1]; + // tv.v[2] = gSmoke[i].time_sync / 1000.0 * gSmoke[i].v.v[2]; + gSmoke[i].time_sync = 0; + } else { + BrVector3Scale(&tv, &gSmoke[i].v, pTime / 1000.0); + // tv.v[0] = pTime / 1000.0 * gSmoke[i].v.v[0]; + // tv.v[1] = pTime / 1000.0 * gSmoke[i].v.v[1]; + // tv.v[2] = pTime / 1000.0 * gSmoke[i].v.v[2]; + } + BrVector3Add(&gSmoke[i].pos, &gSmoke[i].pos, &tv); + } else { + gSmoke_flags &= ~(1 << i); + } + } + } + for (i = 0; i < COUNT_OF(gSmoke); i++) { + if ((gSmoke_flags & (1 << i)) != 0) { + if ((gSmoke[i].type & 0xF) == 7) { + not_lonely |= 1 << i; + } else if ((not_lonely & (1 << i)) == 0) { + for (j = i + 1; j < COUNT_OF(gSmoke); j++) { + if ((gSmoke_flags & (1 << j)) != 0) { + BrVector3Sub(&tv, &gSmoke[i].pos, &gSmoke[i].pos); + ts = BrVector3LengthSquared(&tv); + if ((gSmoke[i].radius + gSmoke[j].radius) * (gSmoke[i].radius + gSmoke[j].radius) > ts) { + not_lonely |= (1 << j) | (1 << i); + break; + } + } + } + } + if (((1 << i) & not_lonely) == 0) { + gSmoke[i].strength = gSmoke[i].strength / 2.0; + } + aspect = (gSmoke[i].radius - 0.05) / 0.25 * 0.5 + 1.0; + if ((gSmoke[i].type & 0x10) != 0) { + SmokeCircle3D(&gSmoke[i].pos, gSmoke[i].radius / aspect, gSmoke[i].strength, 1.0, pRender_screen, pDepth_buffer, gShade_list[gSmoke[i].type & 0xF], pCamera); + } else { + SmokeCircle3D(&gSmoke[i].pos, gSmoke[i].radius, gSmoke[i].strength, aspect, pRender_screen, pDepth_buffer, gShade_list[gSmoke[i].type & 0xF], pCamera); + } + if (gSmoke[i].pipe_me) { + AddSmokeToPipingSession(i, gSmoke[i].type, &gSmoke[i].pos, gSmoke[i].radius, gSmoke[i].strength); + } + gSmoke[i].radius = (double)pTime / 1000.0 * gSmoke[i].strength * 0.5 + gSmoke[i].radius; + gSmoke[i].strength = gSmoke[i].strength - (double)pTime * gSmoke[i].decay_factor / 1000.0; + if (gSmoke[i].radius > 0.3) { + gSmoke[i].radius = 0.3; + } + if (gSmoke[i].strength > 0.0) { + ts = 1.0 - (double)pTime * 0.002; + if (ts < 0.5) { + ts = 0.5; + } + BrVector3Scale(&gSmoke[i].v, &gSmoke[i].v, ts); + if (fabs(gSmoke[i].v.v[1]) < 0.43478259 && (gSmoke[i].type & 0xFu) < 7) { + if (gSmoke[i].v.v[1] >= 0.0) { + gSmoke[i].v.v[1] = 0.43478259; + } else { + gSmoke[i].v.v[1] = gSmoke[i].v.v[1] + 0.43478259; + } + } + } else { + gSmoke_flags &= ~(1 << i); + } + } + } + EndPipingSession(); + srand(seed); + } + } } // IDA: void __usercall CreatePuffOfSmoke(br_vector3 *pos@, br_vector3 *v@, br_scalar strength, br_scalar pDecay_factor, int pType, tCar_spec *pC) @@ -617,7 +887,43 @@ void CreatePuffOfSmoke(br_vector3* pos, br_vector3* v, br_scalar strength, br_sc br_vector3 tv; int pipe_me; LOG_TRACE("(%p, %p, %f, %f, %d, %p)", pos, v, strength, pDecay_factor, pType, pC); - NOT_IMPLEMENTED(); + + if (!gSmoke_on) { + return; + } + // if we are too far away from the current car... + BrVector3Sub(&tv, pos, &gProgram_state.current_car.pos); + if (BrVector3LengthSquared(&tv) > 625.0) { + // check the distance from the car we are viewing and if it is too far away also, just return + BrVector3Sub(&tv, pos, &gCar_to_view->pos); + if (&gProgram_state.current_car != gCar_to_view && BrVector3LengthSquared(&tv) > 625.0) { + return; + } + } + + BrVector3InvScale(&gSmoke[gSmoke_num].v, v, WORLD_SCALE); + gSmoke[gSmoke_num].v.v[1] = gSmoke[gSmoke_num].v.v[1] + 0.1449275362318841; + gSmoke[gSmoke_num].pos = *pos; + gSmoke[gSmoke_num].radius = 0.05; + if ((pType & 0xF) == 7) { + gSmoke[gSmoke_num].radius *= 2.0f; + } else { + gSmoke[gSmoke_num].pos.v[1] += 0.04; + } + gSmoke[gSmoke_num].pos.v[1] += 0.04; + if (strength > 1.0) { + strength = 1.0; + } + gSmoke[gSmoke_num].strength = strength; + gSmoke_flags |= 1 << gSmoke_num; + gSmoke[gSmoke_num].time_sync = gMechanics_time_sync; + gSmoke[gSmoke_num].type = pType; + gSmoke[gSmoke_num].decay_factor = pDecay_factor; + gSmoke[gSmoke_num].pipe_me = 1; + gSmoke_num++; + if (gSmoke_num >= 25) { + gSmoke_num = 0; + } } // IDA: void __cdecl ResetSmoke() @@ -668,13 +974,9 @@ void GenerateSmokeShades() { static int bg = 0x80; LOG_TRACE("()"); - STUB(); - return; - - // FIXME: use this once the car can be shaded correctly gBlack_smoke_shade_table = GenerateShadeTable(16, gRender_palette, rb, gb, bb, .25f, .6f, .9f); - gDark_smoke_shade_table = GenerateShadeTable(16, gRender_palette, rd, gd, bd, .25f, .6f, .9f); - gGrey_smoke_shade_table = GenerateShadeTable(16, gRender_palette, rg, gg, bg, .25f, .6f, .9f); + gDark_smoke_shade_table = GenerateShadeTable(16, gRender_palette, rd, gd, bd, .25f, .6f, .9f); + gGrey_smoke_shade_table = GenerateShadeTable(16, gRender_palette, rg, gg, bg, .25f, .6f, .9f); gIt_shade_table = GenerateDarkenedShadeTable(16, gRender_palette, 0, 255, 254, .25f, .5f, .75f, .6f); gShade_list[0] = gBlack_smoke_shade_table; @@ -770,7 +1072,7 @@ void DisposeFlame() { } for (i = 0; i < 5; i++) { - if ((gSplash_flags & (1 << i)) && (gSmoke_column[i].colour == 0)) { + if ((gColumn_flags & (1 << i)) && (gSmoke_column[i].colour == 0)) { BrActorRemove(gSmoke_column[i].flame_actor); } actor = gSmoke_column[i].flame_actor->children; @@ -795,7 +1097,7 @@ void InitFlame() { br_material* material; LOG_TRACE("()"); - gSplash_flags = 0; + gColumn_flags = 0; gLollipop_model = BrModelAllocate("Lollipop", 4, 2); PathCat(the_path, gApplication_path, "PIXELMAP"); PathCat(the_path, the_path, "FLAMES.PIX"); @@ -821,8 +1123,8 @@ void InitFlame() { } gLollipop_model->nvertices = 4; BrVector3SetFloat(&gLollipop_model->vertices[0].p, -.5f, 0.f, .0f); - BrVector3SetFloat(&gLollipop_model->vertices[1].p, .5f, 0.f, .0f); - BrVector3SetFloat(&gLollipop_model->vertices[2].p, .5f, 1.f, .0f); + BrVector3SetFloat(&gLollipop_model->vertices[1].p, .5f, 0.f, .0f); + BrVector3SetFloat(&gLollipop_model->vertices[2].p, .5f, 1.f, .0f); BrVector3SetFloat(&gLollipop_model->vertices[3].p, -.5f, 1.f, .0f); gLollipop_model->vertices[0].map.v[0] = 0.f; gLollipop_model->vertices[0].map.v[1] = 1.f; @@ -879,7 +1181,7 @@ void InitSplash(FILE* pF) { BrMapAddMany(splash_maps, gNum_splash_types); for (i = 0; i < gNum_splash_types; ++i) { gSplash_material[i] = BrMaterialAllocate(0); - gSplash_material[i]->flags &= ~ (BR_MATF_LIGHT | BR_MATF_PRELIT); + gSplash_material[i]->flags &= ~(BR_MATF_LIGHT | BR_MATF_PRELIT); gSplash_material[i]->flags |= BR_MATF_ALWAYS_VISIBLE | BR_MATF_PERSPECTIVE; gSplash_material[i]->index_blend = LoadSingleShadeTable(&gTrack_storage_space, "BLEND50.TAB"); gSplash_material[i]->colour_map = splash_maps[i]; @@ -887,8 +1189,8 @@ void InitSplash(FILE* pF) { } gSplash_model->nvertices = 4; BrVector3SetFloat(&gSplash_model->vertices[0].p, -0.5f, 0.0f, 0.0f); - BrVector3SetFloat(&gSplash_model->vertices[1].p, 0.5f, 0.0f, 0.0f); - BrVector3SetFloat(&gSplash_model->vertices[2].p, 0.5f, 1.0f, 0.0f); + BrVector3SetFloat(&gSplash_model->vertices[1].p, 0.5f, 0.0f, 0.0f); + BrVector3SetFloat(&gSplash_model->vertices[2].p, 0.5f, 1.0f, 0.0f); BrVector3SetFloat(&gSplash_model->vertices[3].p, -0.5f, 1.0f, 0.0f); gSplash_model->vertices[0].map.v[0] = 0.0f; gSplash_model->vertices[0].map.v[1] = 1.0f; @@ -949,7 +1251,22 @@ void DrawTheGlow(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_act br_vector3 tv; tU32 seed; LOG_TRACE("(%p, %p, %p)", pRender_screen, pDepth_buffer, pCamera); - NOT_IMPLEMENTED(); + + if (gColumn_flags) { + seed = rand(); + srand(GetTotalTime()); + for (i = 0; i < 5; i++) { + if (((1 << i) & gColumn_flags) != 0 && gSmoke_column[i].colour <= 1) { + strength = 0.5; + if (gSmoke_column[i].lifetime < 4000) { + strength = gSmoke_column[i].lifetime * 0.5 / 4000.0; + } + BrVector3Set(&tv, gSmoke_column[i].pos.v[0], gSmoke_column[i].pos.v[1] + 0.02, gSmoke_column[i].pos.v[2]); + SmokeCircle3D(&tv, 0.07, strength, SRandomBetween(0.5, 0.99000001), pRender_screen, pDepth_buffer, gAcid_shade_table, pCamera); + } + } + srand(seed); + } } // IDA: void __usercall PipeInstantUnSmudge(tCar_spec *pCar@) @@ -997,7 +1314,7 @@ void ResetSmokeColumns() { // IDA: void __usercall SetSmokeOn(int pSmoke_on@) void SetSmokeOn(int pSmoke_on) { LOG_TRACE("(%d)", pSmoke_on); - + gSmoke_on = pSmoke_on; } diff --git a/src/harness/sdl/gl_renderer.c b/src/harness/sdl/gl_renderer.c index 794dbfd6..ab28cce5 100644 --- a/src/harness/sdl/gl_renderer.c +++ b/src/harness/sdl/gl_renderer.c @@ -497,7 +497,7 @@ void setActiveMaterial(tStored_material* material) { if (material->shade_table) { GLRenderer_SetShadeTable(material->shade_table); } - if ((material->flags & BR_MATF_LIGHT) && material->shade_table) { + if ((material->flags & BR_MATF_LIGHT) && !(material->flags & BR_MATF_PRELIT) && material->shade_table) { // TODO: light value shouldn't always be 0? Works for shadows, not sure about other things. glUniform1i(uniforms_3d.light_value, 0); } else { @@ -566,7 +566,7 @@ void GLRenderer_RenderModel(br_actor* actor, br_model* model, br_matrix34 model_ glDrawElements(GL_TRIANGLES, group->nfaces * 3, GL_UNSIGNED_INT, (void*)(element_index * sizeof(int))); element_index += group->nfaces * 3; } - //glUniform1i(uniforms_3d.palette_index_override, 0);//material->index_base); + glBindVertexArray(0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); dirty_buffers = 1;