Dynamic Head-Motion for ETS2/ATS
Overview β’
Features β’
Installation β’
Game Settings β’
Controls β’
Configuration
Building β’
Project Structure β’
Contributing β’
License
MotionCab is a plugin for Euro Truck Simulator 2 and American Truck Simulator that adds realistic dynamic head-motion camera effects for a next-level driving experience.
It's built on the SPF Framework, which handles telemetry, camera control, keybind rebinding, and the in-game settings UI.
- Head Motion β inertial head sway/tilt under acceleration, braking, and cornering
- Steering Camera β smoothed camera yaw following the steering wheel
- Idle Breathing β subtle breathing motion that fades out with speed
- Suspension β seat bounce and head tilt over bumps, plus grade follow
- Engine Vibration β RPM-scaled engine buzz
- Mirror Check β looks toward the mirror on turn signal
- Manual Look β smooth look-left/look-right and mirror glances
- Road Irregularity β ground chatter, plus rocking off-road
- Speed Shake β body sway growing with speed and rough ground
- Body Dynamics β head leans outward in corners and nods forward when braking
- Engine Start/Stop β mechanical shudder when the engine catches or dies
- Natural Head Movement β TrackIR-like head movement, without a tracker
- Manual Zoom β smooth zoom effect
- Blindspot Viewer β leans forward to see traffic lights hidden by the cab
- Cabin Walk β walks around the parked cabin and sits in the passenger seat or on the bunk
- Profiles β create, save, and switch between named presets
- Localized β available in 15 languages
Every effect above is independently customizable and toggleable, and only active while in the interior (cabin) camera view.
- Install SPF Framework in your game's
bin/win_x64/plugins/folder. - Install MotionCab in your game's
bin/win_x64/plugins/spfPlugins/folder. - Start your game and enable MotionCab in SPF's plugin manager.
For both ETS2 and ATS, disable the following camera options
in Options > Gameplay:
| Setting | Value |
|---|---|
| Uneven surfaces simulation | 0% |
| Steering camera rotation factor | 0% |
| Steering camera rotation on reverse | Off |
| Physical camera movement | Off |
| Physical camera factor | 0% |
| Interior camera horizon locking factor | Off |
Disabling these settings ensures that MotionCab has full control over the camera.
| Action | Default key | Behavior |
|---|---|---|
| Toggle Settings Window | F9 | Shows/hides the MotionCab Quick Settings window |
| Look Left | Numpad / | Manual Look β hold or toggle to look left |
| Look Right | Numpad * | Manual Look β hold or toggle to look right |
| Glance at Left Mirror | Numpad 7 | Manual Look β hold or toggle to glance at the left mirror |
| Glance at Right Mirror | Numpad 9 | Manual Look β hold or toggle to glance at the right mirror |
| Zoom | Numpad - | Manual Zoom β hold to zoom in, release to return to normal |
| Blindspot Viewer | F10 | Blindspot Viewer β Toggle or hold to lean forward and look up |
| Stand Up / Sit Down | Page Up | Cabin Walk β get up; tap to sit at the seat you look at, hold to go back to the wheel |
| Walk | W/S/A/D | Cabin Walk β walk forward, back and sideways while standing |
| Crouch | C | Cabin Walk β crouch while standing |
All parameters are tuned live in MotionCab's own Quick Settings window:
right-click any slider to reset it to default, and the Settings tab has a
button to reset every effect at once.
Values are persisted by the framework to plugins/spfPlugins/MotionCab/config/settings.json.
| Setting | Default | Description |
|---|---|---|
| Head Motion | ||
sway_strength |
0.2 | How much your head gets pushed around when you speed up, brake, or take a turn. |
tilt_strength |
0.15 | How much your head tilts when the cab leans or rocks. |
smoothing_time |
0.2 | How quickly your head settles into place. Higher = slower and smoother, lower = snappier. |
| Steering Camera | ||
rotation_left_deg |
30.0 | How far the camera turns when you crank the wheel all the way to the left. |
rotation_right_deg |
30.0 | How far the camera turns when you crank the wheel all the way to the right. |
center_zone_pct |
15.0 | How much of the wheel's turn keeps the camera turning alike both ways. Past it, each side turns at its own rotation amount. |
smoothing_time |
0.5 | How smooth the camera turn feels once it gets going. Higher = smoother and slower. |
delay_seconds |
0.2 | How long the camera waits after you turn the wheel before it starts moving. |
disable_in_reverse |
true | Keep the camera centered while the truck is in reverse gear. |
| Idle Breathing | ||
vertical_amplitude |
0.002 | How far the camera rises and falls with each breath. |
pitch_amplitude_deg |
0.15 | How much your head tips forward/back with each breath. |
breathing_rate_bpm |
15.0 | How fast the breathing happens. |
fade_start_kmh |
30.0 | The speed at which this effect starts fading away as you speed up. |
fade_end_kmh |
50.0 | The speed at which this effect has completely faded away. |
| Suspension | ||
vertical_strength |
1.0 | How much bumps in the road bounce and tilt the camera. |
reactivity |
0.25 | How quickly the seat settles after a bump. Lower = firmer and snappier. |
grade_strength |
0.5 | Raises your head on downhill stretches and lowers it on uphill ones. |
| Engine Vibration | ||
intensity |
1.0 | How strong the engine rumble feels. |
| Mirror Check | ||
left_angle_deg |
28.0 | How far your head turns to check the left mirror. |
left_pitch_deg |
0.0 | How much your head tilts while checking the left mirror. |
left_fov_deg |
0.0 | How much the field of view widens while checking the left mirror. |
right_angle_deg |
28.0 | How far your head turns to check the right mirror. |
right_pitch_deg |
0.0 | How much your head tilts while checking the right mirror. |
right_fov_deg |
0.0 | How much the field of view widens while checking the right mirror. |
smoothing_time |
0.35 | How smooth the look-and-return motion is. |
require_stationary |
true | Only check the mirror when the truck is stopped. |
ignore_after_moving_signal |
true | Don't check the mirror for a turn signal you switched on while already driving, even after you stop. |
| Manual Look | ||
look_left_deg |
45.0 | How far your head turns when you look left. |
look_right_deg |
45.0 | How far your head turns when you look right. |
glance_left_deg |
20.0 | How far your head turns when you glance at the left mirror. |
glance_left_pitch_deg |
0.0 | How much your head tilts while glancing at the left mirror. |
glance_left_fov_deg |
0.0 | How much the field of view widens while glancing at the left mirror. Negative = narrower (zoom in). |
glance_right_deg |
30.0 | How far your head turns when you glance at the right mirror. |
glance_right_pitch_deg |
0.0 | How much your head tilts while glancing at the right mirror. |
glance_right_fov_deg |
0.0 | How much the field of view widens while glancing at the right mirror. Negative = narrower (zoom in). |
smoothing_time |
0.35 | How smooth the look-and-return motion is. |
toggle_mode |
false | On: press once to look, press again to look back. Off: look while held, let go to look back. |
| Road Irregularity | ||
intensity |
1.0 | How strong the road-texture shake and off-road rocking feel. |
reactivity |
0.05 | How sharp and buzzy the road-texture shake feels. Lower = sharper. |
| Speed Shake | ||
intensity |
1.0 | Overall strength of the shake you feel from driving fast. |
smoothing_time |
0.3 | How the shake feels over time. Higher = slower and smoother, lower = jumpier and more nervous. |
rotation |
1.0 | How much your view tilts/turns as part of the shake, versus just moving side to side. Set to 0 to keep only the side-to-side motion. |
vertical |
1.0 | How much up-and-down bounce is mixed into the shake. |
roughness |
0.5 | How uneven the shake feels over time. 0 keeps it constant; higher gives bursts of calm and rough stretches. |
| Body Dynamics | ||
lean_strength |
1.0 | How much your head leans toward the outside of a turn. |
nod_strength |
1.0 | How much your head dips forward when braking and pulls back when accelerating. |
smoothing_time |
0.25 | How quickly the lean and nod settle. Lower = snappier. |
| Engine Start/Stop | ||
intensity |
0.1 | How strong the shudder feels when the engine starts or stops. |
duration |
1.0 | How long the start-up shudder lasts. The stop shudder is shorter and gentler than this. |
| Natural Head Movement | ||
tremor_intensity |
5.0 | How much your head trembles slightly, all the time. |
micro_intensity |
2.5 | How far your head moves when it makes a small adjustment. |
posture_intensity |
1.3 | How far your head shifts when it settles into a new position: tilted, leaning forward or to one side. |
posture_interval |
15.0 | About how long your head holds a position before settling into a new one. |
steering_tilt |
1.5 | How much your head tilts into the turn as you turn the steering wheel. |
| Manual Zoom | ||
zoom_fov_deg |
40.0 | How zoomed in the view gets while holding the zoom key. Lower = more zoomed in. |
smoothing_time |
0.25 | How smooth the zoom in/out feels. |
| Blindspot Viewer | ||
pos_x |
-0.06 | How far your head moves left or right while peeking. |
pos_y |
-0.1 | How far your head moves up or down while peeking. |
pos_z |
-0.88 | How far your head moves forward while peeking. Negative = forward. |
yaw_deg |
-1.7 | How far your head turns left or right while peeking. |
pitch_deg |
33.0 | How far your head tilts up or down while peeking. |
roll_deg |
3.0 | How far your head tilts to the side while peeking. |
fov_offset_deg |
10.0 | How much the field of view widens while peeking. Negative = narrower. |
smoothing_time |
0.6 | How smooth the lean-and-return motion is. |
toggle_mode |
true | On: press once to peek, press again to sit back. Off: peek while held, let go to sit back. |
| Cabin Walk | ||
require_parking_brake |
true | On: needs the parking brake, releasing it sends you back. Off: stopping is enough. |
Every effect also has its own enabled toggle, defaulting to on.
Requires CMake 4.4+, Ninja and MinGW-w64 (x86_64-w64-mingw32-g++/windres).
-
Rename
CMakeUserPresets.json.exampletoCMakeUserPresets.jsonand fill in yourETS2_PLUGINS_DIR/ATS_PLUGINS_DIRpaths. Make sure thepluginsfolder exists in your game directory. If it doesnβt, create it. -
Run the workflow preset:
cmake --workflow --preset user-mingw-release
This configures, builds, and deploys motioncab.dll straight into your
game's plugins/spfPlugins/MotionCab/.
βββ src/
β βββ Plugin.cpp Lifecycle callbacks, telemetry wiring, per-frame driver
β βββ core/
β β βββ Manifest.cpp / .hpp Plugin identity, settings defaults, keybinds, window
β β βββ CameraRig.cpp / .hpp Writes the effects' offset into the interior camera
β β βββ PluginContext.cpp / .hpp Shared plugin state
β β βββ Profiles.cpp / .hpp Create/save/switch named presets
β β βββ Settings.cpp / .hpp Every setting: key, default, slider range
β β βββ Conflicts.hpp Which effects pause which while enabled
β β βββ Loc.cpp / .hpp Translated string lookup (loc::Tr)
β β βββ Keybinds.hpp Keybind action names and key polling helpers
β β βββ Strings.hpp Case-insensitive string helpers
β β βββ Links.hpp Plugin URLs
β βββ math/
β β βββ SpringDamper.hpp Critically-damped spring, the core smoothing primitive
β β βββ Noise.hpp Deterministic gradient noise
β β βββ Oscillator.hpp Damped spring that can overshoot and ring
β β βββ Units.hpp Unit conversions, easing, Lerp, phase wrapping
β βββ effects/
β β βββ Effect.hpp Base effect interface + HeadOffset struct
β β βββ ConfigurableEffect.hpp Base for effects: enabled toggle + settings access
β β βββ EffectManager.cpp / .hpp Owns/drives all HeadOffset-based effects
β β βββ Telemetry.hpp Telemetry readings shared by effects
β β βββ driving/ HeadMotion, BodyDynamics, SteeringCamera
β β βββ road/ Suspension, RoadIrregularity, SpeedShake,
β β β Surface (ground classification)
β β βββ cabin/ IdleBreathing, EngineVibration, EngineStartStop,
β β β NaturalHeadMovement
β β βββ manual/ MirrorCheck, ManualLook, ManualZoom, BlindspotViewer
β β βββ cabin_walk/
β β βββ CabinWalkEffect.* The effect: standing up, walking, sitting down
β β βββ CabinLayouts.* Per-truck cabin layouts
β β βββ CabinPresets.* Shipped layouts, one per truck model
β β βββ CabinWalkSounds.* Footsteps (FMOD bank)
β β βββ InteriorCameraOverride.* Swaps the camera's limits while out of the seat
β βββ ui/
β βββ SettingsWindow.cpp / .hpp MotionCab Quick Settings window
β βββ EffectTabs.cpp / .hpp Driving/Road/Cabin/Manual tabs
β βββ CabinLayoutPanel.cpp/.hpp Cabin Walk's layout panel (Advanced)
β βββ SettingsTab.cpp / .hpp Settings tab: keybind, profiles, reset
β βββ AboutTab.cpp / .hpp About tab
β βββ Widgets.cpp / .hpp Shared look and widgets
β βββ OpenUrl.cpp / .hpp Opens a URL in the system browser
βββ data/
β βββ logo.png About tab logo
β βββ sounds/ Cabin Walk's FMOD bank
βββ localization/
β βββ <lang>.json UI text, one file per language
βββ SPF_API/ SPF Framework SDK headers
βββ cmake/
β βββ toolchain-mingw.cmake MinGW cross-compile toolchain
βββ .github/workflows/build.yaml CI/CD
βββ .github/scripts/
β βββ check-localization.py Checks every language file against en.json
βββ CMakeLists.txt Plugin sources, deploy steps
βββ CMakePresets.json Toolchain/build-type presets
βββ CMakeUserPresets.json.example Template for your game deploy paths
βββ version.rc.in Windows version resource
βββ LICENSE Project licenseBug reports, feature requests, pull requests and translation fixes are welcome β see CONTRIBUTING.md for build instructions, coding standards, how to improve a translation or add a language, and how to submit a change.
This project is licensed under the GPL-3.0.
