summaryrefslogtreecommitdiff
path: root/src/overlay.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/overlay.cpp')
-rw-r--r--src/overlay.cpp269
1 files changed, 269 insertions, 0 deletions
diff --git a/src/overlay.cpp b/src/overlay.cpp
new file mode 100644
index 0000000..75a9194
--- /dev/null
+++ b/src/overlay.cpp
@@ -0,0 +1,269 @@
+#include "overlay.h"
+#include "gauges.h"
+
+const F32 TRAIL_TACH_MAX = 0.14f;
+const F32 TRAIL_BOOST_MAX = 0.16f;
+
+OVERLAY_DATA* overlay_inst() {
+ static OVERLAY_DATA d;
+ return &d;
+}
+
+void overlay_handle_teleport( OVERLAY_DATA* d ) {
+ TELEMETRY *t = &d->telem;
+
+ U8 iszero = fabsf( t->pos_x ) < 0.01f && fabsf( t->pos_y ) < 0.01f && fabsf( t->pos_z ) < 0.01f;
+ U8 iszero_last = fabsf( d->last_pos_x ) < 0.01f && fabsf( d->last_pos_y ) < 0.01f && fabsf( d->last_pos_z ) < 0.01f;
+ F32 dist = vec_dist( t->pos_x, t->pos_y, t->pos_z, d->last_pos_x, d->last_pos_y, d->last_pos_z );
+ U8 unteleported = 0;
+
+ if( d->teleported && !iszero ) {
+ F32 tdist = vec_dist( t->pos_x, t->pos_y, t->pos_z, d->tele_pos_x, d->tele_pos_y, d->tele_pos_z );
+ if( tdist > 1.f ) {
+ d->teleported = 0;
+ unteleported = 1;
+ }
+ }
+
+ U8 iszero_vel = fabsf( t->vel_z ) < 3.f;
+ if( !iszero_vel ) {
+ if( d->teleported )
+ unteleported = 1;
+ d->teleported = 0;
+ }
+
+ // teleported
+ if( !unteleported && !d->teleported && !iszero && !iszero_last && dist > 10.f ) {
+ d->teleported = 1;
+ d->tele_pos_x = t->pos_x;
+ d->tele_pos_y = t->pos_y;
+ d->tele_pos_z = t->pos_z;
+ }
+
+ d->last_brake = t->brake;
+ d->last_hb = t->handbrake;
+ d->last_pos_x = t->pos_x;
+ d->last_pos_y = t->pos_y;
+ d->last_pos_z = t->pos_z;
+
+ if( !d->was_race_on && t->race_on ) {
+ d->teleported = 0;
+ }
+}
+
+void overlay_handle_redline( OVERLAY_DATA* d ) {
+ TELEMETRY* t = &d->telem;
+
+ if( !d->cfg.autoscale_rpm || d->valid_redline < 0.86f ) {
+ d->valid_redline = 0.86f;
+ return;
+ }
+
+ if( t->gear != d->last_gear ) {
+ if( t->gear != 0 && t->gear != 11 && t->gear > d->last_valid_gear )
+ d->valid_shift = 1;
+ else
+ d->valid_shift = 0;
+ }
+
+ if( d->valid_shift ) {
+ F64 rpmr = (F64)(t->rpm) / t->rpm_max;
+ if( rpmr >= 0.99f )
+ d->valid_redline = 0.86f;
+ rpmr = (F64)(t->rpm - (I32)d->cfg.rpm_off) / t->rpm_max;
+ if( rpmr > d->valid_redline ) {
+ d->valid_redline = rpmr;
+ }
+ }
+
+ d->last_gear = t->gear;
+ if( t->gear != 11 )
+ d->last_valid_gear = t->gear;
+}
+
+void overlay_handle_car_changed( OVERLAY_DATA* d ) {
+ TELEMETRY* t = &d->telem;
+ if( !t->extended )
+ return;
+
+ U8 car_changed = ( t->car_ordinal != d->car_ordinal || fabsf( t->rpm_max - d->car_rpm_max ) > 1.0f );
+ if( car_changed ) {
+ d->car_ordinal = t->car_ordinal;
+ d->car_rpm_max = t->rpm_max;
+ d->peak_boost_bar = 0.0;
+ d->boost_since = 0.0;
+ d->valid_redline = 0.86;
+ }
+}
+
+void overlay_update_rpm_boost( OVERLAY_DATA* d, U8 live, F64 dt, F64 now ) {
+ TELEMETRY* t = &d->telem;
+
+ F64 k = dt * 20.0;
+ if( k > 1.0 )
+ k = 1.0;
+ d->disp_rpm += ( (F64)t->rpm - d->disp_rpm ) * k;
+ if( d->disp_rpm > d->peak_rpm )
+ d->peak_rpm = d->disp_rpm;
+ else
+ d->peak_rpm -= 2500.0 * dt;
+ if( d->peak_rpm < 0.0 )
+ d->peak_rpm = 0.0;
+
+ F64 bar = (F64)t->boost_psi * PSI_TO_BAR;
+ F64 kb = dt * 25.0;
+ if( kb > 1.0 )
+ kb = 1.0;
+ d->disp_boost_bar += ( bar - d->disp_boost_bar ) * kb;
+ if( live && bar > d->peak_boost_bar )
+ d->peak_boost_bar = bar;
+
+ d->was_race_on = t->race_on;
+ F32 kmh = t->speed_ms * 3.6f;
+ d->lc_armed = 0;
+ if( t->handbrake > 30 && t->accel > 30 && kmh < 1.0f )
+ d->lc_armed = 1;
+
+ F64 idt = dt > 1e-4 ? 1.0 / dt : 0.0;
+ F64 sm = dt * 15.0;
+ if( sm > 1.0 )
+ sm = 1.0;
+ d->rpm_vel += ( ( d->disp_rpm - d->prev_disp_rpm ) * idt - d->rpm_vel ) * sm;
+ d->bar_vel += ( ( d->disp_boost_bar - d->prev_disp_bar ) * idt - d->bar_vel ) * sm;
+ d->prev_disp_rpm = d->disp_rpm;
+ d->prev_disp_bar = d->disp_boost_bar;
+
+ if( d->peak_boost_bar > 0.10 && d->boost_since <= 0.0 )
+ d->boost_since = now;
+}
+
+void overlay_handle_assists( OVERLAY_DATA* d, F64 now ) {
+ TELEMETRY* t = &d->telem;
+
+ I32 w0 = 0, w1 = 3; // AWD
+ if( t->drivetrain == 0 ) { w0 = 0; w1 = 1; } // FWD
+ else if( t->drivetrain == 1 ) { w0 = 2; w1 = 3; } // RWD
+
+ if( t->gear == 11 )
+ d->tcs_until = 0;
+ else if( t->accel > 30 && t->rpm < t->rpm_max - t->rpm_max * 0.1f && t->rpm > d->last_rpm ) {
+ for( I32 i = w0; i <= w1; i++ ) {
+ if( t->combined_slip[i] > 1.35f && t->power * 1.02f < d->last_power && t->accel >= d->last_acc )
+ d->tcs_until = now + 0.05;
+ }
+ }
+
+ if( t->brake > 30 ) {
+ for( I32 i = 0; i < 4; i++ ) {
+ if( t->slip_ratio[i] < -1.f )
+ d->abs_until = now + 0.02;
+ }
+ }
+}
+
+void overlay_update( OVERLAY_DATA* d, F64 now, F64 dt ) {
+ TELEMETRY* t = &d->telem;
+
+ overlay_handle_teleport( d );
+
+ U8 live = overlay_live( d, now );
+ if( live && !d->was_live )
+ d->live_since = now;
+ d->was_live = live;
+
+ overlay_handle_car_changed( d );
+ overlay_handle_redline( d );
+ overlay_update_rpm_boost( d, live, dt, now );
+
+ if( !t->extended )
+ return;
+
+ overlay_handle_assists( d, now );
+
+ d->prev_race_on = t->race_on;
+ d->last_power = t->power;
+ d->last_acc = t->accel;
+ d->last_rpm = t->rpm;
+}
+
+U8 overlay_visible( OVERLAY_DATA* d, F64 now ) {
+ return overlay_live( d, now ) && fade_alpha( d->live_since, now ) > 0.0f;
+}
+
+U8 overlay_live( OVERLAY_DATA* d, F64 now ) {
+ U8 live = d->telem.race_on && !d->teleported;
+ return now - d->telem.stamp < 3.0 && ( live || d->cfg.keep );
+}
+
+void overlay_build_cluster( OVERLAY_DATA* d, GAUGE_RENDERER* gauge, F32 w, F32 h, F64 now ) {
+ TELEMETRY* t = &d->telem;
+ CONFIG* c = &d->cfg;
+
+ F32 sc = (F32)c->scale;
+ if( sc < 0.2f || sc > 4.0f )
+ sc = 1.0f;
+ F32 a_main = fade_alpha( d->live_since, now );
+
+ gauge->clear();
+ gauge->set_fade( a_main );
+
+ F32 blur = (F32)c->blur;
+ if( blur < 0.0f || blur > 0.5f )
+ blur = 0.0f;
+ F32 rpm_max_safe = t->rpm_max < 100.0f ? 8000.0f : t->rpm_max;
+ F32 trail_tach = blur > 0.0f ? (F32)( d->rpm_vel * blur ) / rpm_max_safe : 0.0f;
+ if( trail_tach > TRAIL_TACH_MAX ) trail_tach = TRAIL_TACH_MAX;
+ if( trail_tach < -TRAIL_TACH_MAX ) trail_tach = -TRAIL_TACH_MAX;
+
+ F32 speed = t->speed_ms * ( c->units ? 2.23694f : 3.6f );
+ F32 kmh = t->speed_ms * 3.6f;
+ F32 rpmoff = c->autoscale_rpm ? (F32)(c->rpm_off - 100.f) / rpm_max_safe : 0.f;
+ gauge->build_tach(
+ (F32)( c->tach_x * w ), (F32)( c->tach_y * h ), (F32)( c->tach_r * h ) * sc, trail_tach,
+ (F32)d->disp_rpm, t->rpm_max, d->valid_redline, rpmoff, (F32)d->peak_rpm,
+ t->gear, speed, t->extended, c->flash_needle
+ );
+
+ F32 a_boost = a_main * fade_alpha( d->boost_since, now );
+ if( c->show_boost && t->extended && a_boost > 0.0f ) {
+ F32 need = (F32)d->peak_boost_bar + 0.25f;
+ F32 range = ceilf( need / 0.25f ) * 0.25f;
+ if( range < 0.5f ) range = 0.5f;
+
+ F32 shown = (F32)d->disp_boost_bar;
+ if( shown < -1.0f ) shown = -1.0f;
+ if( shown > range ) shown = range;
+
+ F32 span = range + 1.0f;
+ F32 trail_boost = blur > 0.0f ? (F32)( d->bar_vel * blur ) / span : 0.0f;
+ if( trail_boost > TRAIL_BOOST_MAX ) trail_boost = TRAIL_BOOST_MAX;
+ if( trail_boost < -TRAIL_BOOST_MAX ) trail_boost = -TRAIL_BOOST_MAX;
+ gauge->set_fade( a_boost );
+ gauge->build_boost(
+ (F32)( c->boost_x * w ), (F32)( c->boost_y * h ), (F32)( c->boost_r * h ) * sc,
+ shown, range, trail_boost
+ );
+ gauge->set_fade( a_main );
+ }
+
+ if( t->extended && ( c->show_abs || c->show_tcs || c->show_lc ) ) {
+ U8 abs_show = c->show_abs;
+ U8 tcs_show = c->show_tcs;
+ U8 lc_show = c->show_lc;
+ U8 abs_lit = abs_show && now < d->abs_until;
+ U8 tcs_lit = ( tcs_show && now < d->tcs_until );
+ U8 lc_lit = (now < d->tcs_until && kmh < 50);
+ U8 lc_flash = c->show_lc && ( ( d->lc_armed && fmod( now, 0.30 ) < 0.20 ) || lc_lit );
+ gauge->build_lamps(
+ (F32)( c->tach_x * w ), (F32)( c->tach_y * h ),
+ (F32)( c->tach_r * h * sc ), (F32)( c->tach_r * h * sc * 0.1f ),
+ t->handbrake > 0,
+ abs_show, tcs_show || lc_show, abs_lit, tcs_lit || lc_flash
+ );
+ }
+
+ if( t->extended && c->show_tires ) {
+ gauge->build_tires( (F32)( c->tire_x * w ), (F32)( c->tire_y * h ), (F32)( c->tire_sc * h ),
+ d->telem.tire_temp[0], d->telem.tire_temp[1], d->telem.tire_temp[2], d->telem.tire_temp[3] );
+ }
+}