Vehicles Bundle Architecture
This is an introduction to the design idea behind the Vehicles bundle in a generic way.
The important point is that the bundle is not a library of fixed machines. It is a
set of reusable vehicle-domain building blocks that let you turn low-level physics
assets into configurable machine models.
%%{init: {"flowchart": {"curve": "basis", "nodeSpacing": 38, "rankSpacing": 56, "htmlLabels": true}}}%%
flowchart TB
title["openplx Vehicles Bundle Overview<br/>From low-level physics assets to configurable vehicle models"]
subgraph assets_layer["Layer 1: Low-Level Assets"]
direction TB
physics3d["Physics3D<br/>Bodies, geometries,<br/>constraints"]
assets["Assets<br/>Exported rigid bodies,<br/>meshes, transforms,<br/>mate connectors"]
asset_traits["Asset Traits<br/>FrameBody, AxleBody,<br/>WheelBody"]
end
subgraph machine_layer["Layer 2: Machine-Level Components"]
direction TB
primitive["Primitive Components<br/>Wrap bodies as reusable<br/>machine parts"]
interfaces["Vehicle Interfaces<br/>Expected connectors<br/>and outputs"]
upgraded_parts["Upgraded Parts<br/>Front frame, rear frame,<br/>axle, cargo bed,<br/>track wheel, link"]
end
subgraph domain_layer["Layer 3: Vehicle-Domain Building Blocks"]
direction LR
chassis["Vehicles.Chassis.*<br/>Rigid, articulated,<br/>dual-pivot, intermediate-link"]
running_gear["Vehicles.Wheels.*<br/>Vehicles.TrackSystem.*<br/>Rims, tires, sprockets,<br/>idlers, rollers, links"]
supporting_systems["Suspensions,<br/>DriveTrain,<br/>Connections,<br/>Attachments"]
steering["Vehicles.Steering.*<br/>DualCylinder,<br/>DualDistance,<br/>Ackermann variants"]
end
subgraph family_layer["Layer 4: Machine Archetype Composition"]
direction TB
families["Archetype Modules<br/>Vehicles.DumpTruck.*<br/>Vehicles.Bulldozer.*<br/>Other machine bundles"]
assembly["Reusable Vehicle Assembly<br/>Choose topology and connect<br/>subsystems without hard-coding<br/>one fixed machine"]
end
subgraph variants_layer["Layer 5: Traits and Variants"]
direction LR
traits["Traits<br/>Suspension, hydraulic tuning,<br/>connector conventions,<br/>motors, optional equipment"]
variants["Variant Choices<br/>Wheeled or tracked<br/>Simple or detailed steering<br/>Optional bed, blade, ripper"]
end
result["Final openplx Vehicle Model<br/>A configurable machine assembled from reusable layers"]
scene["Scene Setup<br/>Terrain, controls, ranges,<br/>springs, contact properties"]
title --> physics3d
physics3d --> assets --> asset_traits
asset_traits --> primitive
primitive --> upgraded_parts
interfaces --> upgraded_parts
asset_traits -.-> interfaces
upgraded_parts --> chassis
upgraded_parts --> running_gear
upgraded_parts --> supporting_systems
upgraded_parts --> steering
chassis --> families
running_gear --> families
supporting_systems --> families
steering --> families
families --> assembly --> result --> scene
traits --> assembly
variants --> assembly
classDef titleClass fill:#243746,stroke:#243746,color:#ffffff,stroke-width:2px;
classDef assetsClass fill:#fff8dc,stroke:#d7c7a3,color:#222222,stroke-width:1.5px;
classDef machineClass fill:#edf7fc,stroke:#9eb7c8,color:#222222,stroke-width:1.5px;
classDef domainClass fill:#f4fae8,stroke:#9fb88b,color:#222222,stroke-width:1.5px;
classDef familyClass fill:#f9ebe5,stroke:#c79076,color:#222222,stroke-width:1.5px;
classDef variantClass fill:#f4ecfa,stroke:#a58ab5,color:#222222,stroke-width:1.5px;
classDef resultClass fill:#d5efe1,stroke:#4f7b68,color:#222222,stroke-width:2px;
classDef sceneClass fill:#fff6ea,stroke:#b98b42,color:#222222,stroke-width:1.5px;
style assets_layer fill:#fffef8,stroke:#d7c7a3,stroke-width:1.5px,color:#222222;
style machine_layer fill:#f8fcfe,stroke:#9eb7c8,stroke-width:1.5px,color:#222222;
style domain_layer fill:#fbfdf7,stroke:#9fb88b,stroke-width:1.5px,color:#222222;
style family_layer fill:#fdf8f5,stroke:#c79076,stroke-width:1.5px,color:#222222;
style variants_layer fill:#faf8fd,stroke:#a58ab5,stroke-width:1.5px,color:#222222;
class title titleClass;
class physics3d,assets,asset_traits assetsClass;
class primitive,interfaces,upgraded_parts machineClass;
class chassis,running_gear,supporting_systems,steering domainClass;
class families,assembly familyClass;
class traits,variants variantClass;
class result resultClass;
class scene sceneClass;
Core idea
The workflow is layered:
Assetsdefine low-level physical parts.MachineModelingcomponents give those parts structure and meaning.Vehiclescomponents add domain-specific behavior such as chassis layouts, wheel systems, tracks, steering, suspensions, and attachments.- Traits specialize the model for a machine family or a concrete variant.
This separation makes it possible to reuse the same physical parts in several vehicle configurations without duplicating the full assembly.
Layer 1: Assets are raw physics building blocks
The lowest layer usually comes from exported geometry and connector data. At this level, a part is mostly a rigid body plus the information needed to attach it to other parts:
- geometry
- visual mesh
- mass and inertia inputs
- mate connectors
- local transforms
In practice, an asset trait often looks like this:
trait FrameBody:
axle_c is Physics3D.Interactions.MateConnector:
position: {...}
main_axis: {...}
normal: {...}
visual is Visuals.Geometries.ExternalTriMeshGeometry:
path: @"frame.obj"
geometry is Physics3D.Geometries.ExternalTriMeshGeometry:
path: visual.path
At this stage the part does not yet "know" that it belongs to a dump truck, bulldozer, wheel loader, or any other machine class. It is only a physical part with geometry and attachment points.
Layer 2: Primitive components are upgraded into vehicle parts
The next step is to wrap exported bodies in higher-level component definitions. This is where low-level assets are promoted into domain-aware machine parts.
For example, a rigid body can become a front frame, rear frame, axle, wheel carrier, track wheel, cargo bed, or equalizer bar by combining:
- a primitive component
- a body created from the asset trait
- vehicle interfaces that define expected connectors or outputs
Typical pattern:
FrontFrame is MachineModeling.Components.Primitive.Base
with Vehicles.Chassis.Articulated.Interfaces.DualJoint
with Vehicles.DumpTruck.Interfaces.Chassis.AFrame:
body becomes Physics3D.Bodies.RigidBody with FrameBody
upper_joint_connector: body.upper_joint_c
lower_joint_connector: body.lower_joint_c
center_a_frame_connector: body.axle_c
This is the key "upgrade" step:
Physics3Dprovides the body and constraints.- exported assets provide geometry and connector locations.
Vehicles.*.Interfaces.*define the role the part plays in a vehicle.
After this step the model is no longer just a mesh with connectors. It has become a reusable vehicle subsystem component.
Layer 3: Vehicles bundle modules encode vehicle-domain structure
The Vehicles bundle adds machine-specific abstractions on top of the primitive
parts. These abstractions describe how a vehicle is organized rather than how each
triangle mesh was authored.
Examples of domain modules in the bundle:
Vehicles.Chassis.*for rigid and articulated chassis topologiesVehicles.Steering.*for steering mechanisms and fidelity levelsVehicles.Wheels.*for rims, tires, wheel connectors, and wheel behaviorVehicles.TrackSystem.*for sprockets, idlers, rollers, links, and track supportVehicles.Suspensions.*for wheel and axle suspension behaviorVehicles.DriveTrain.*for drive distributionVehicles.DumpTruck.*,Vehicles.Bulldozer.*, and similar folders for machine-family-specific composition
These modules define reusable patterns such as:
- articulated vs rigid chassis
- dual-pivot vs intermediate-link articulation
- wheeled vs tracked undercarriage
- simple vs detailed steering
- optional cargo beds, blades, rippers, or other machine equipment
Layer 4: Traits define reusable variation
Traits are what keep the system composable. They allow variation to be expressed orthogonally instead of forcing every variant into a separate monolithic class.
Common uses for traits in the vehicle stack:
- physical tuning such as suspension stiffness or damping
- hydraulic dimensions such as cylinder stroke and barrel diameter
- optional equipment packages
- connector conventions
- visual or geometry additions
- actuation models such as velocity motors or simpler kinematic substitutes
This makes it possible to mix and match behavior:
MyVehicle is Vehicles.DumpTruck.ArticulatedWithLink:
with Suspension
with Hydraulic
with IndividualWheelMotors
The machine variant is then defined by composition rather than by copying an entire machine model and editing it in place.
Why this is useful
This architecture solves a common modeling problem: the same machine family often needs several variants with different fidelity, hardware layouts, or optional equipment.
With the bundle approach, you can change one concern at a time:
- keep the same exported bodies, but switch chassis topology
- keep the same chassis, but swap steering model
- keep the same vehicle family, but move from wheels to tracks
- keep the same base vehicle, but add or remove attachments
- keep the same assembly, but retune suspension, damping, or actuation traits
That is much more maintainable than building every machine as an isolated, fully-specialized model.
A generic assembly flow
A typical workflow for building a custom vehicle from the bundle is:
- Export or author the physical parts in
Assets. - Define body traits with geometry, visuals, and mate connectors.
- Wrap those bodies in primitive components and attach the relevant
Vehicles.*.Interfaces.*. - Choose a vehicle topology from the bundle, such as rigid, articulated, wheeled, or tracked.
- Add connection modules for axles, suspensions, cargo beds, blades, or tools.
- Apply reusable traits for tuning, hydraulics, drivetrain behavior, and options.
- Place the assembled vehicle in a scene and add ranges, springs, contact properties, terrain, and controls.
This means a packaged machine model is usually split into at least three concerns:
- asset definitions
- reusable vehicle assembly
- scene or scenario setup
How to think about a machine package
A machine package should be read as a composition of layers, not as one flat file. Even when a final model looks specific, the structure is usually generic:
- asset files describe bodies and connectors
- bundle-based assembly files turn those bodies into vehicle components
- scene files add environment, terrain, limits, controls, and runtime settings
That is why a concrete machine can still be a good example of the general design, without the design being tied to that one machine.
Practical rule of thumb
When adding a new machine, ask these questions in order:
- Which parts are just physical assets?
- Which parts are reusable vehicle-domain components?
- Which decisions belong to the chosen machine family?
- Which differences should be expressed as traits instead of new classes?
If those responsibilities stay separate, the result is usually easy to extend, retune, and recombine into new vehicle variants.