17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-11-03 15:30:21 +01:00
Commit Graph

97 Commits

Author SHA1 Message Date
1ad6d8b2bd Merge remote-tracking branch 'origin/feat/track-uneven' into feat/renderers-cleanup 2026-10-31 19:52:29 +01:00
154c42cb66 Merge remote-tracking branch 'origin/feat/track-uneven' into feat/renderers-cleanup 2026-10-31 19:13:23 +01:00
maj00r
2b8d7d7cf3 refactor(track): what goes with unevenness in one place, readable
The rules stay in TrackUneven.h with no dependence on the engine, as they can
be tested. Their use on the tracks moves out of Track.cpp to TrackUneven.cpp,
split into steps: the group of switches, the values of its paths, the meeting
of two ends. One set of helpers for the paths of a track takes the place of
the same conditions written out in several places, and the value at the ends
of a switch is worked out in one place. The clatter of an axle leaves the long
Update of a vehicle. The fields in the editor say themselves when they show.

No change in behaviour.
2026-10-31 19:05:56 +01:00
maj00r
371de52342 fix(track): what the review of unevenness found in the engine
- A path of no length gave a joint with a vector across of NaN to the path
  joined to it, on any scenery, with unevenness or not. It now has no
  vector across, and so makes no joint.
- Axles no longer stray along the track. It moved vehicles against each
  other, changing the distance their couplers go by.
- The bend under an axle goes straight on past the ends of a path: the
  polynomial ran off on a short curved one, with a kick in the cab shake.
- A track left out of its rail run, where tracks are joined one way only,
  no longer walks the whole run again on every call.
- The clatter of an axle goes by the outer axle on its side of the vehicle,
  and not always by the same one, as the two can be on different tracks.
- A vertex works out the amounts once, and the foot of the ballast not at all.
2026-10-31 19:02:55 +01:00
24b805b348 Merge remote-tracking branch 'origin/feat/track-uneven' into feat/renderers-cleanup 2026-10-31 18:53:48 +01:00
maj00r
7aff1ee9ff feat(vehicle): an uneven track shakes the cab by itself
On such a track the sway drawn from the lateral acceleration, that is
from the curve radius, and the jolts drawn at random are off. Tracks
with no unevenness shake the cab as before. Hunting stays: it goes by the
vehicle and its speed, not by the track.
2026-10-31 18:29:22 +01:00
maj00r
b2dcb8a42e fix(vehicle): wheel clatter on an uneven track doesn't loop into a buzz
The phase of the rails was wrapped to the rail length of the track the
vehicle is on, while an axle can be on a track with longer rails. From
then on every frame looked like a joint crossed.
2026-10-31 18:21:28 +01:00
maj00r
e5266e1e6b feat(track): track unevenness declared in the track entry
Usage, optional attributes of a track entry, before endtrack:

  uneven <mm>       peak deviation of a rail on a 10 m chord, 0-100; normal and switch
  unevenup <mm>     up and down alone, instead of uneven; normal and switch
  unevenside <mm>   sideways alone, instead of uneven; normal and switch
  unevencross <mm>  cross level alone, instead of uneven; normal only
  jointdip <mm>     depth of the dip at rail joints, every sound distance; normal only,
                    default 0.4 of the up and down component

Values of uneven follow PLK Id-14 appendix 1: 6 mm is the limit at 160 km/h, 10 at 120,
18 at 80, 35 at 40; half of it for a track in a good state. Example:

  uneven 18
  unevencross 25
  jointdip 6
  endtrack

The same fields are in the editor, track panel, section Ride and sound. See
track_uneven_doc.md.

The unevenness is a displacement field over the plan of the scenery, with no random
numbers: one place strays the same every time, and joined tracks, the paths of a switch,
sleepermodel and axles at one place move together. Tracks meet at a joint at the lower of
their values. Joined switches take the lowest of theirs, the tracks joined to them come to
it, and a track with none of a component keeps the switch to its design in it. The clatter
comes from the dipping joints. Curve radius and grade for the physics stay as designed.

Tracks with it get geometry every 2 m on straights: 4x the vertices on Baltyk with all
tracks flagged, 0.2 ms more per frame on td.scn.
2026-10-31 15:47:10 +01:00
55372571b3 Merge branch 'master' into feat/renderers-cleanup 2026-10-29 20:42:39 +01:00
1447dcf075 Walk the shadow passes and the culled model groups on worker threads in the Vulkan renderer 2026-10-27 20:56:11 +01:00
550d47e97c Merge remote-tracking branch 'jano211/siec-radio' into feat/renderers-cleanup 2026-10-26 16:36:36 +01:00
3e2d292709 perf(gpucull): keep the walks of the submodel trees of the instances from frame to frame and make them again only when the model changes (gfx.gpucull.walkcache) 2026-10-24 01:01:43 +02:00
1a42009dc2 perf(physics): performance.multithreading switches the work over many threads, which each job sizes by how much it has: the physics steps a thread per 128 vehicle steps, up to all logical cores 2026-10-23 21:07:05 +02:00
9f7217256b fix(physics): the external program messages (multiplayer) no longer keep the physics steps in one thread, only network sessions do; the debug panel tells what keeps them in one 2026-10-23 20:12:02 +02:00
60667588b5 perf(physics): the steps of the vehicle physics on many threads, in groups of vehicles which act on one another (performance.cpucores, 0: all cores) 2026-10-23 19:56:36 +02:00
f17462b186 perf(physics): road vehicles farther than 1 km from the camera go by one step of the physics in a frame (physics.roadlod); count what resets the switching time of the vehicles (compressor, mains, diesel, physics woken) in the debug panel 2026-10-23 18:47:01 +02:00
a04efbf968 perf(physics): vehicles standing still and held by their brakes let their physics sleep (physics.sleepheld) 2026-10-23 18:20:49 +02:00
e054fe900d perf(debug): count what keeps the physics on in rail vehicles standing still (active cab, speed, acceleration, switching, ezt/dmu, moving neighbour), for the debug panel 2026-10-23 18:06:12 +02:00
0aa1e2d4b6 perf(debug): forces and update of the vehicles by kind in the debug panel: rail and road, within 1 km of the camera and farther, with the counts of vehicles and of the ones standing still 2026-10-23 17:54:05 +02:00
5a53c32b0a perf(debug): forces and update of the vehicles by kind in the debug panel: rail and road, within 1 km of the camera and farther, with the counts of vehicles and of the ones standing still 2026-10-23 17:51:15 +02:00
52df707f30 perf(debug): parts of the vehicle update in the debug panel: scenery animations, power grid, roads, preparation, forces, vehicle update and ai, with the counts of vehicles and physics steps; input and the start of the ui frame timed apart 2026-10-23 17:26:44 +02:00
8fbf056749 fix(ai): a road order holding the vehicle keeps the road orders past it from telling the vehicle to drive on 2026-10-22 18:01:04 +02:00
f4f8c75e49 fix(ai): orders of road junctions and level crossings measured along the lane they lie on, so they aren't misplaced on short lanes 2026-10-22 17:16:33 +02:00
40a4267bd3 Merge pull request #189 from pwarszawski/fix/ai-ready-released-brakes
AI: don't cut the power for a brake already released below 0.4 bar
2026-10-21 09:00:34 +02:00
918c056b83 Merge branch 'master' into feat/gl46-migration 2026-10-17 20:57:15 +02:00
IwanXXI
b4b1e6c32f Broadcast radio receiver in the cab
Plays internet radio streams (http, mp3) through a positional emitter in the cab, with analog tuning, inter-station noise and two speaker profiles. Stations are listed in fmradio.txt, cab controls are defined with fmradio entries in the .mmd file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 00:14:32 +02:00
jerrrrycho
c7f9796387 fix(ai): release horn when human driver takes over from AI (#210)
* fix(ai): release what the AI was holding when the player takes over

* fix(ai): keep the light selector lookup within its table, Sonar findings of the handover

- the light selector size comes from the vehicle definition (LightsList Size)
  and isn't limited, while the table holds 18 positions; a bigger selector
  read past the table, and so did a table index other than the front or
  rear one. Only the positions the table holds are looked at now, and the
  selector stays where it is for a bad table index (cpp:S2259),
- the lambdas of the handover capture what they use explicitly (cpp:S3608),
- the chained assignments resetting the headlight state on the AI taking
  over are split (cpp:S1121).
2026-10-16 14:44:30 +02:00
61bfc6eb1a Move modern OpenGL renderer to rendering/opengl46 and rename classes 2026-10-15 01:12:05 +02:00
3d3eef2e1c Remove legacy OpenGL 2.1 renderer 2026-10-15 00:06:31 +02:00
pwarszawski
71a19f32fb Compare the brake force with 10 kN directly 2026-10-12 06:54:17 +02:00
jerrrrycho
6263fe539b Fix/sonar maintainability rebased (#209)
* refactor(sonar): use override instead of redundant virtual (cpp:S3471)

* refactor(sonar): remove empty statements, one declaration per statement (cpp:S1116, cpp:S1659)

* refactor(sonar): drop redundant lambda return types (cpp:S3574)

* refactor(sonar): prefer using over typedef (cpp:S5416)

* refactor(sonar): use =default for trivial special members (cpp:S3490)

* refactor(sonar): use nullptr literal (cpp:S4962)

* refactor(sonar): remove redundant access specifiers (cpp:S3539)

* refactor(sonar): remove redundant casts (cpp:S1905)

* refactor(sonar): use std::scoped_lock instead of std::lock_guard (cpp:S5997)

* refactor(sonar): construct elements in place with emplace_back (cpp:S6003)

* refactor(sonar): make narrowing conversions explicit (cpp:S5276)

* refactor(sonar): mark unused parameters (cpp:S1172)

Unused names are commented out; parameters used only on some platforms
are marked [[maybe_unused]].

* refactor(sonar): declare non-mutating member functions const (cpp:S5817)

Virtual functions are left untouched so overrides keep matching.

* refactor(sonar): merge collapsible nested if statements (cpp:S1066)

Comments that preceded the inner if are kept above the merged statement.

* refactor(sonar): scope single-use variables in if init-statements (cpp:S6004)

* fix(sonar): give polymorphic base classes virtual destructors (cpp:S1235)

* refactor(sonar): use try_emplace for map insertion (cpp:S6030)

* refactor(sonar): use auto where the type is spelled out on the right (cpp:S5827)

* refactor(sonar): remove redundant parentheses (cpp:S1110)

* refactor(sonar): document intentionally empty functions (cpp:S1186)

* refactor(sonar): remove dead stores (cpp:S1854)

Side effects (e.g. LISTLINE++) are kept.

* refactor(sonar): remove unused variables, captures and private fields (cpp:S1481, cpp:S1068)

* refactor(sonar): use structured bindings for pair access (cpp:S6005)

* refactor(sonar): use range-based loops and ranges algorithms (cpp:S5566)

* refactor(sonar): split chained assignments (cpp:S1121)

* refactor(sonar): add default cases to switch statements (cpp:S3562)

* refactor(sonar): use std::size for array lengths (cpp:S7127)

* refactor(sonar): use std::ranges algorithms and std::erase(_if) (cpp:S6197)

* refactor(sonar): access static members through the class (cpp:S2209)

* refactor(sonar): add braces around nested if-else (cpp:S5261)

* refactor(sonar): avoid side effects inside typeid operands (cpp:S5279)

* refactor(sonar): drop top-level const from by-value return types (cpp:S5951)

* refactor(sonar): declare variables separately from their type definitions (cpp:S3646)

* refactor(sonar): declare loop counters in the for statement (cpp:S5955)

* refactor(sonar): rely on class template argument deduction (cpp:S6012)

* refactor(sonar): inherit base constructors instead of forwarding them (cpp:S5952)

* refactor(sonar): rename locals that shadow outer declarations (cpp:S1117)

Only local variables and definition parameters are renamed; shadowing
struct fields and enumerators in headers are left for a separate change.

* refactor(sonar): reduce enum qualification with using enum (cpp:S6177)

Applied only where no unqualified name in the block could be captured by
the introduced enumerators.

* refactor(sonar): mark converting constructors explicit (cpp:S1709)

sound_source and the gl::object conversion operators stay implicit; they
are relied upon by copy-list-initialisation and GL calls.

* refactor(sonar): initialise members in initialiser lists or declarations (cpp:S3230)

* refactor(sonar): make read-only local references and pointers const (cpp:S5350)

* refactor(sonar): take read-only pointer and reference parameters as const (cpp:S995)

TTrain command handlers keep their signature, it is fixed by the handler table.

* refactor(sonar): pass expensive-to-copy parameters by const reference (cpp:S1238)

Signatures declared in files touched by PR 206 (Driver.h, EU07.cpp) and
virtual overrides are left unchanged.

* refactor(sonar): use transparent comparators for string-keyed maps (cpp:S6045)

std::unordered_map instances and map types exposed in headers used by
other modules are left as they are.

* fix(sonar): do not use UI text as a printf format string (cpp:S5281)

Text lines containing '%' would otherwise be interpreted as format
specifiers by ImGui::TextColored.

* refactor(sonar): use std::bind_front for callbacks (cpp:S5995)

* refactor(sonar): drop const_cast on string literals passed to the Python C API (cpp:S859)

* refactor(sonar): take read-only string parameters as std::string_view (cpp:S6009)

The Windows messaging helpers keep std::string, they need c_str().

* refactor(sonar): make read-only global tables const (cpp:S5421)

Mutable global state (flags, timers, singletons) is left as is.

* refactor(sonar): replace single-case switch statements with if (cpp:S1301)

* refactor(sonar): format UUIDs and log timestamps with std::format (cpp:S6494, cpp:S5945)

* refactor(sonar): use std::array for local fixed-size arrays (cpp:S5945)

Arrays that are class members or part of headers are left unchanged.

* fix(sonar): test the bearing damage bit, not bit 0 (cpp:S872)

'DamageFlag & dtrain_bearing > 0' parsed as 'DamageFlag & (dtrain_bearing > 0)',
i.e. DamageFlag & 1, so bearing friction reacted to the wrong damage flag.

* refactor(sonar): assorted small fixes

- empty() instead of size() comparisons (cpp:S1155)
- member initialisers in declaration order (cpp:S3229)
- no redundant c_str() when a std::string is accepted (cpp:S7121)
- contains() on associative containers (cpp:S6171)
- const reference instead of a copying range-for (cpp:S6032)
- starts_with() for prefix checks (cpp:S6178)
- no std::move on temporaries (cpp:S5274)
- has_value() on std::optional (cpp:S7172)
- bool literals for bool members (cpp:S5820)
- inline only on the definition (cpp:S3548)
- explicit base access specifier (cpp:S5965)
- explicit element access instead of dereferencing an array (cpp:S7116)
- rely on the C++20 rewritten operator!= (cpp:S6186)

* refactor(sonar): more small fixes

- std::format instead of iostream manipulators in to_string/to_hex_str (cpp:S6495);
  output verified identical, negative hex values keep the unsigned form
- remove an empty compound statement (cpp:S108)
- drop an always-false unsigned < 0 branch (cpp:S1768)
- explicit lambda capture (cpp:S3608)
- std::make_unique (cpp:S5950)

* chore: strip stray carriage returns left in TTrain constructor comments

* fix: keep quantize() in its own value type

The S5276 change cast the result of the generic quantize<Type_>() to
unsigned int, which truncated float/double callers (shadow angle slider,
editor rotation snapping, AI speed control steps) and broke negative values.

* fix(sonar): use integer loop counters in segment sampling (cpp:S2193)

* refactor(sonar): clean up issues reported on PR 209

- remove locals left unused after the dead-store cleanup (cpp:S1481, cpp:S1854)
- unnamed unused parameter (cpp:S1172)
- single-use declarations moved into if init-statements (cpp:S6004)
- auto for casted initialisers (cpp:S5827)
- const references and pointers where nothing is modified (cpp:S5350)
- rename structured bindings shadowed by inner declarations (cpp:S1117)
2026-10-11 13:22:33 +02:00
c26041f2e7 Merge pull request #199 from MaSzyna-EU07/brake-diag
AI - prevent overcharge when pipe pressure of car is too high for too long
2026-10-10 20:37:12 +02:00
9935257783 Add nosonar tags 2026-10-09 18:40:31 +02:00
917c8f7285 Merge branch 'master' into feat/modern-editor 2026-10-08 17:44:58 +02:00
maj00r
4e406fdd86 fix(ai): end brake charging on control reservoir overcharge, charge on blocked departures
- end the charging position when the control reservoir of any vehicle, the
  locomotive included, rises 0.05 bar above the nominal pipe pressure
- standing and unable to depart for 10 s: allow the charging position
  regardless of the equivalent pipe pressure and the train type
2026-10-07 18:17:59 +02:00
maj00r
084a705452 fix(vehicles): vehicle placed with a switch as its first path no longer reads the direction of a previous path it doesn't have; vehicle put back on the track keeps the direction of its axles 2026-10-06 22:19:12 +02:00
jerrrrycho
79bd0c8e91 fix(sonar): addressing reliability/security issues (#202) 2026-10-04 20:00:13 +02:00
27a94509c4 feat(roads): right of way and lane turns at junctions, road weights, kerbs, medians and forking roads, banks to the ground, roundabouts, pedestrian crossings, spawn sets by count; fix(editor): model skin export, placement on the ground under the orthophoto 2026-10-04 01:55:35 +02:00
2f417fddcc feat(roads): road node with generated lanes, surface and markings 2026-10-03 17:35:08 +02:00
pwarszawski
b71ad90c93 Declare isbraking in the init-statement of the if 2026-10-03 14:32:09 +02:00
pwarszawski
c38ec7faa8 Merge master into fix/ai-ready-released-brakes 2026-10-03 14:31:56 +02:00
maj00r
affa7cdaa9 AI - prevent overcharge when pipe pressure of car is too high for too long 2026-10-02 19:55:23 +02:00
maj00r
314e7df294 braking diagnostics 2026-10-01 21:57:18 +02:00
jerrrrycho
1474d2b773 fix: merge nested ifs in Driver.cpp cpp:s1066 (#194) 2026-10-01 13:30:36 +02:00
jakubg1
99c5a0090b Remove brake position check from TController::PrepareEngine()
The function would flag the consist as not ready (`iEngineActive` set to `false`) when the brake handle was at a cutoff position. Since this is what the brake lever is exactly starting at in the EW58 train, the train when asked to move the brake lever to operating position would not listen since the `control_tractive_and_braking_force()` function which is supposed to do that is gated behind the readiness flag in the `TController::Update()` function.

This makes sure EW58 trains can be driven by AI once again instead of being stuck.

I don't really know why the brake position check was there, since it would fail only if:
- There is a brake handle
- The brake handle is in the cutoff position
- The brake handle is NOT in the operating position

The third check seems redundant but curiously there is one case where this matters and it's... MHZ_EN57. Its operating and cutoff positions are both defined as `0`, which might be a hack, since the actual cutoff position in the MHZ_EN57 handle is meant to be `6`.
2026-10-01 02:10:21 +02:00
pwarszawski
f2f152e5d3 AI: don't cut the power for a brake already released below 0.4 bar
When the AI takes power after a brake release, determine_consist_state()
marks the consist not Ready if any vehicle's distributor reports the lap
or application state (b_hld | b_on), whatever the speed, and the sanity
check in control_handles() then puts the master controller back to zero.
A distributor stays in the lap position until the brake pipe has fully
recharged, so a few seconds after a release, with 0.2-0.3 bar left in a
cylinder, one wagon of a train is enough to throw an EU07 or EP09 that
has just reached the 2nd-5th position back to zero; it starts again
moments later.

The check in motion was meant to be lenient (brake force over 10 kN),
but the distributor state was applied at any speed. In motion it now
counts only when the cylinder holds more than 0.4 bar, the UIC figure
already used a few lines below for a released brake. At a stand the
check is unchanged.

Measured in real time against master, two runs of each scenery (a 20 per
mille descent, flat and a 10 per mille climb with 32 consists each, and a
descent with 15 freight trains of other wagon types), with a 20 km/h
restriction one coach long: throttle-downs to zero in motion caused by
readiness drop from 13 to 1, 7 to 2, 0 to 0 and 13 to 6. Each of those
left has a wagon over 0.4 bar that is applying or lapped, or one still
releasing with more than 10 kN at walking pace. No coupler broke; signal
overruns, speeds in the restriction and rolling back on the climb
are the same as on master within run-to-run spread.
2026-09-28 23:21:19 +02:00
b67bbb19e6 Merge pull request #188 from MaSzyna-EU07/feat/dynobj-seasonal-models
seasonal model variants for vehicle exterior model
2026-09-28 21:21:49 +02:00
jerrrrycho
176427f96b refactor: sonar c++20 changes (#185) 2026-09-28 21:08:15 +02:00
jerrrrycho
4137f5504a fix: sonar sast fixes - sonar.yml, nosonar, linux chmod modification 2026-09-28 21:07:53 +02:00
551f6dbc3b seasonal model variants for vehicle exterior model 2026-09-28 20:49:18 +02:00