Realistic braking: Cache offset of centre of mass of train
This commit is contained in:
@@ -102,16 +102,25 @@ void GroundVehicle<T, Type>::CargoChanged()
|
|||||||
{
|
{
|
||||||
assert(this->First() == this);
|
assert(this->First() == this);
|
||||||
uint32 weight = 0;
|
uint32 weight = 0;
|
||||||
|
uint64 mass_offset = 0;
|
||||||
|
uint32 veh_offset = 0;
|
||||||
|
|
||||||
for (T *u = T::From(this); u != nullptr; u = u->Next()) {
|
for (T *u = T::From(this); u != nullptr; u = u->Next()) {
|
||||||
uint32 current_weight = u->GetWeight();
|
uint32 current_weight = u->GetWeight();
|
||||||
if (Type == VEH_TRAIN) Train::From(u)->tcache.cached_veh_weight = current_weight;
|
if (Type == VEH_TRAIN) {
|
||||||
|
Train::From(u)->tcache.cached_veh_weight = current_weight;
|
||||||
|
mass_offset += current_weight * (veh_offset + (Train::From(u)->gcache.cached_veh_length / 2));
|
||||||
|
veh_offset += Train::From(u)->gcache.cached_veh_length;
|
||||||
|
}
|
||||||
weight += current_weight;
|
weight += current_weight;
|
||||||
/* Slope steepness is in percent, result in N. */
|
/* Slope steepness is in percent, result in N. */
|
||||||
u->gcache.cached_slope_resistance = current_weight * u->GetSlopeSteepness() * 100;
|
u->gcache.cached_slope_resistance = current_weight * u->GetSlopeSteepness() * 100;
|
||||||
u->InvalidateImageCache();
|
u->InvalidateImageCache();
|
||||||
}
|
}
|
||||||
ClrBit(this->vcache.cached_veh_flags, VCF_GV_ZERO_SLOPE_RESIST);
|
ClrBit(this->vcache.cached_veh_flags, VCF_GV_ZERO_SLOPE_RESIST);
|
||||||
|
if (Type == VEH_TRAIN) {
|
||||||
|
Train::From(this)->tcache.cached_centre_mass = (weight != 0) ? (mass_offset / weight) : (this->gcache.cached_total_length / 2);
|
||||||
|
}
|
||||||
|
|
||||||
/* Store consist weight in cache. */
|
/* Store consist weight in cache. */
|
||||||
this->gcache.cached_weight = std::max(1u, weight);
|
this->gcache.cached_weight = std::max(1u, weight);
|
||||||
|
@@ -1646,10 +1646,11 @@ void CheckCaches(bool force_check, std::function<void(const char *)> log)
|
|||||||
print_gv_cache_diff("train", gro_cache[length], Train::From(u)->gcache);
|
print_gv_cache_diff("train", gro_cache[length], Train::From(u)->gcache);
|
||||||
}
|
}
|
||||||
if (memcmp(&tra_cache[length], &Train::From(u)->tcache, sizeof(TrainCache)) != 0) {
|
if (memcmp(&tra_cache[length], &Train::From(u)->tcache, sizeof(TrainCache)) != 0) {
|
||||||
CCLOGV("train cache mismatch: %c%c%c%c%c%c%c%c",
|
CCLOGV("train cache mismatch: %c%c%c%c%c%c%c%c%c",
|
||||||
tra_cache[length].cached_override != Train::From(u)->tcache.cached_override ? 'o' : '-',
|
tra_cache[length].cached_override != Train::From(u)->tcache.cached_override ? 'o' : '-',
|
||||||
tra_cache[length].cached_tilt != Train::From(u)->tcache.cached_tilt ? 't' : '-',
|
tra_cache[length].cached_tilt != Train::From(u)->tcache.cached_tilt ? 't' : '-',
|
||||||
tra_cache[length].cached_num_engines != Train::From(u)->tcache.cached_num_engines ? 'e' : '-',
|
tra_cache[length].cached_num_engines != Train::From(u)->tcache.cached_num_engines ? 'e' : '-',
|
||||||
|
tra_cache[length].cached_centre_mass != Train::From(u)->tcache.cached_centre_mass ? 'm' : '-',
|
||||||
tra_cache[length].cached_veh_weight != Train::From(u)->tcache.cached_veh_weight ? 'w' : '-',
|
tra_cache[length].cached_veh_weight != Train::From(u)->tcache.cached_veh_weight ? 'w' : '-',
|
||||||
tra_cache[length].cached_uncapped_decel != Train::From(u)->tcache.cached_uncapped_decel ? 'D' : '-',
|
tra_cache[length].cached_uncapped_decel != Train::From(u)->tcache.cached_uncapped_decel ? 'D' : '-',
|
||||||
tra_cache[length].cached_deceleration != Train::From(u)->tcache.cached_deceleration ? 'd' : '-',
|
tra_cache[length].cached_deceleration != Train::From(u)->tcache.cached_deceleration ? 'd' : '-',
|
||||||
|
@@ -1148,6 +1148,7 @@ struct train_venc {
|
|||||||
GroundVehicleCache gvcache;
|
GroundVehicleCache gvcache;
|
||||||
bool cached_tilt;
|
bool cached_tilt;
|
||||||
uint8 cached_num_engines;
|
uint8 cached_num_engines;
|
||||||
|
uint16 cached_centre_mass;
|
||||||
uint16 cached_veh_weight;
|
uint16 cached_veh_weight;
|
||||||
uint16 cached_uncapped_decel;
|
uint16 cached_uncapped_decel;
|
||||||
uint8 cached_deceleration;
|
uint8 cached_deceleration;
|
||||||
@@ -1215,6 +1216,7 @@ void Save_VENC()
|
|||||||
write_gv_cache(t->gcache);
|
write_gv_cache(t->gcache);
|
||||||
SlWriteByte(t->tcache.cached_tilt);
|
SlWriteByte(t->tcache.cached_tilt);
|
||||||
SlWriteByte(t->tcache.cached_num_engines);
|
SlWriteByte(t->tcache.cached_num_engines);
|
||||||
|
SlWriteByte(t->tcache.cached_centre_mass);
|
||||||
SlWriteUint16(t->tcache.cached_veh_weight);
|
SlWriteUint16(t->tcache.cached_veh_weight);
|
||||||
SlWriteUint16(t->tcache.cached_uncapped_decel);
|
SlWriteUint16(t->tcache.cached_uncapped_decel);
|
||||||
SlWriteByte(t->tcache.cached_deceleration);
|
SlWriteByte(t->tcache.cached_deceleration);
|
||||||
@@ -1275,6 +1277,7 @@ void Load_VENC()
|
|||||||
read_gv_cache(venc.gvcache);
|
read_gv_cache(venc.gvcache);
|
||||||
venc.cached_tilt = SlReadByte();
|
venc.cached_tilt = SlReadByte();
|
||||||
venc.cached_num_engines = SlReadByte();
|
venc.cached_num_engines = SlReadByte();
|
||||||
|
venc.cached_centre_mass = SlReadUint16();
|
||||||
venc.cached_veh_weight = SlReadUint16();
|
venc.cached_veh_weight = SlReadUint16();
|
||||||
venc.cached_uncapped_decel = SlReadUint16();
|
venc.cached_uncapped_decel = SlReadUint16();
|
||||||
venc.cached_deceleration = SlReadByte();
|
venc.cached_deceleration = SlReadByte();
|
||||||
@@ -1361,6 +1364,7 @@ void SlProcessVENC()
|
|||||||
check_gv_cache(t->gcache, venc.gvcache, t);
|
check_gv_cache(t->gcache, venc.gvcache, t);
|
||||||
CheckVehicleVENCProp(t->tcache.cached_tilt, venc.cached_tilt, t, "cached_tilt");
|
CheckVehicleVENCProp(t->tcache.cached_tilt, venc.cached_tilt, t, "cached_tilt");
|
||||||
CheckVehicleVENCProp(t->tcache.cached_num_engines, venc.cached_num_engines, t, "cached_num_engines");
|
CheckVehicleVENCProp(t->tcache.cached_num_engines, venc.cached_num_engines, t, "cached_num_engines");
|
||||||
|
CheckVehicleVENCProp(t->tcache.cached_centre_mass, venc.cached_centre_mass, t, "cached_centre_mass");
|
||||||
CheckVehicleVENCProp(t->tcache.cached_veh_weight, venc.cached_veh_weight, t, "cached_veh_weight");
|
CheckVehicleVENCProp(t->tcache.cached_veh_weight, venc.cached_veh_weight, t, "cached_veh_weight");
|
||||||
CheckVehicleVENCProp(t->tcache.cached_uncapped_decel, venc.cached_uncapped_decel, t, "cached_uncapped_decel");
|
CheckVehicleVENCProp(t->tcache.cached_uncapped_decel, venc.cached_uncapped_decel, t, "cached_uncapped_decel");
|
||||||
CheckVehicleVENCProp(t->tcache.cached_deceleration, venc.cached_deceleration, t, "cached_deceleration");
|
CheckVehicleVENCProp(t->tcache.cached_deceleration, venc.cached_deceleration, t, "cached_deceleration");
|
||||||
|
@@ -151,8 +151,8 @@ class NIHVehicle : public NIHelper {
|
|||||||
}
|
}
|
||||||
if (v->type == VEH_TRAIN) {
|
if (v->type == VEH_TRAIN) {
|
||||||
const Train *t = Train::From(v);
|
const Train *t = Train::From(v);
|
||||||
seprintf(buffer, lastof(buffer), " T cache: tilt: %u, engines: %u, decel: %u, uncapped decel: %u",
|
seprintf(buffer, lastof(buffer), " T cache: tilt: %u, engines: %u, decel: %u, uncapped decel: %u, centre mass: %u",
|
||||||
t->tcache.cached_tilt, t->tcache.cached_num_engines, t->tcache.cached_deceleration, t->tcache.cached_uncapped_decel);
|
t->tcache.cached_tilt, t->tcache.cached_num_engines, t->tcache.cached_deceleration, t->tcache.cached_uncapped_decel, t->tcache.cached_centre_mass);
|
||||||
print(buffer);
|
print(buffer);
|
||||||
seprintf(buffer, lastof(buffer), " T cache: veh weight: %u, user data: %u, curve speed: %u",
|
seprintf(buffer, lastof(buffer), " T cache: veh weight: %u, user data: %u, curve speed: %u",
|
||||||
t->tcache.cached_veh_weight, t->tcache.user_def_data, t->tcache.cached_max_curve_speed);
|
t->tcache.cached_veh_weight, t->tcache.user_def_data, t->tcache.cached_max_curve_speed);
|
||||||
|
@@ -99,6 +99,7 @@ struct TrainCache {
|
|||||||
/* cached values, recalculated on load and each time a vehicle is added to/removed from the consist. */
|
/* cached values, recalculated on load and each time a vehicle is added to/removed from the consist. */
|
||||||
bool cached_tilt; ///< train can tilt; feature provides a bonus in curves
|
bool cached_tilt; ///< train can tilt; feature provides a bonus in curves
|
||||||
uint8 cached_num_engines; ///< total number of engines, including rear ends of multiheaded engines
|
uint8 cached_num_engines; ///< total number of engines, including rear ends of multiheaded engines
|
||||||
|
uint16 cached_centre_mass; ///< Cached position of the centre of mass, from the front
|
||||||
uint16 cached_veh_weight; ///< Cached individual vehicle weight
|
uint16 cached_veh_weight; ///< Cached individual vehicle weight
|
||||||
uint16 cached_uncapped_decel; ///< Uncapped cached deceleration for realistic braking lookahead purposes
|
uint16 cached_uncapped_decel; ///< Uncapped cached deceleration for realistic braking lookahead purposes
|
||||||
uint8 cached_deceleration; ///< Cached deceleration for realistic braking lookahead purposes
|
uint8 cached_deceleration; ///< Cached deceleration for realistic braking lookahead purposes
|
||||||
|
@@ -364,6 +364,7 @@ void Train::ConsistChanged(ConsistChangeFlags allowed_changes)
|
|||||||
u->gcache.cached_air_drag = 0;
|
u->gcache.cached_air_drag = 0;
|
||||||
u->gcache.cached_total_length = 0;
|
u->gcache.cached_total_length = 0;
|
||||||
u->tcache.cached_num_engines = 0;
|
u->tcache.cached_num_engines = 0;
|
||||||
|
u->tcache.cached_centre_mass = 0;
|
||||||
u->tcache.cached_deceleration = 0;
|
u->tcache.cached_deceleration = 0;
|
||||||
u->tcache.cached_uncapped_decel = 0;
|
u->tcache.cached_uncapped_decel = 0;
|
||||||
u->tcache.cached_tilt = false;
|
u->tcache.cached_tilt = false;
|
||||||
@@ -847,8 +848,11 @@ static void LimitSpeedFromLookAhead(int &max_speed, const TrainDecelerationStats
|
|||||||
if (distance + current_position > position) {
|
if (distance + current_position > position) {
|
||||||
/* Speed is too fast, we would overshoot */
|
/* Speed is too fast, we would overshoot */
|
||||||
if (z_delta < 0 && (position - current_position) < stats.t->gcache.cached_total_length) {
|
if (z_delta < 0 && (position - current_position) < stats.t->gcache.cached_total_length) {
|
||||||
/* Reduce z delta near target to compensate for target z not taking into account that z varies across the whole train */
|
int effective_length = std::min<int>(stats.t->gcache.cached_total_length, stats.t->tcache.cached_centre_mass * 2);
|
||||||
z_delta = (z_delta * (position - current_position)) / stats.t->gcache.cached_total_length;
|
if ((position - current_position) < effective_length) {
|
||||||
|
/* Reduce z delta near target to compensate for target z not taking into account that z varies across the whole train */
|
||||||
|
z_delta = (z_delta * (position - current_position)) / effective_length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
max_speed = std::min(max_speed, GetRealisticBrakingSpeedForDistance(stats, position - current_position, end_speed, z_delta));
|
max_speed = std::min(max_speed, GetRealisticBrakingSpeedForDistance(stats, position - current_position, end_speed, z_delta));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user