Nodes

Nodes are masspoints and the core of the BeamNG physics. Everything revolves around them. A node itself is a dimensionless (infinitely small) mass point in 3D space. Each node is defined by a unique name and a position in 3D space.

Nodes can have any string for their name, as long as the names do not conflict. A good naming scheme is some memorable/relevant letter, followed by a number, followed by a letter signifying which side of the vehicle it’s on. For example, the 1st rightmost frame node could be called f1rr while the 3rd left frame node would be called f3l. A node sitting in the middle (posX = 0) would have no letter suffix.

This is an example of a nodes section. Nodes also have many properties which can be set by placing dictionary lines above the nodes which are desired to be affected. Node weights are in kilograms, and coordinates are in meters. The “group” modifier is for assigning flexbodies. Node material only affects sound and particle properties, not physics.

Our game engine uses a z-up coordinate system and SI units for most parameters.


Collision system

In BeamNG, collision is handled by nodes alone. There are 3 types of node collision: dynamic (with vehicle triangles ), static (with collision mesh faces of map objects) and heightmap (with the ground). Additionally, the dynamic collision can be divided into self-collision (triangles of the same vehicle the node belongs to) and external collision (triangles of other vehicles). Heightmap collision differs from static collision by having several layers which helps vehicle tires rotate smoother. Collision types have priority, with dynamic being prioritized over static and heightmap collisions. Practically this means that with high enough force a node can be slightly pushed through a solid wall or the ground. It will pop back out once the triangle stops pushing it.

In Jbeam, these types are controlled by 3 properties. The “collision” argument affects all types of collision, and has the highest priority - enabling any other collision type will not work if this one is disabled. The “selfCollision” argument only affects the self-collision type of dynamic collision. The “staticCollision” argument affects static and heightmap collision.

On the triangles side, when a node approaches a triangle, it will be subject to forces of collision, which will attempt to stop the node, and anti-clip, which decide on which side of the triangle the node will end up. If a node approaches the triangle from the front (shown as green with the triangle debug visualization), the forces will start applying at around 2.5cm distance from the triangle in order to prevent clipping. You can controll these forces by setting some properties. When “triangleType” is set to “NONCOLLIDABLE”, it will not have collision but will still have the anti-clip system. The “externalCollisionBias” property will offset the distance where the forces start applying.

For optimization and design purposes, a node will not collide with triangles made of nodes with the same “group” argument even when selfCollision is set to true. If at least one of the nodes has multiple groups, then the first one defined in the list will be taken into account for each node. For example a node with the groups {“A”, “B”} will collide with triangles made of nodes with groups {“C”, “B”} but not with triangles made of nodes with groups {“A”, “C”}. This system may not work as intended if the group does not contain any flexbodies.

There is another special property of dynamic collision. When a triangle doesn’t have any collidable nodes in over 10cm distance from it, it becomes “inactive” in terms of collision detection. This helps improve performance, so it is advised to keep over 10cm space between collidable components by default.


Required arguments

string
type
Defines the node name. Need to be unique for the whole vehicle
number
type
The X (left/right) position in 3D space (m)
Left is positive, right is negative
number
type
The Y (forward/back) position in 3D space (m)
Backward is positive, forward is negative
number
type
The Z (up/down) position in 3D space (m)
Up is positive, down is negative

Optional arguments

The Nodes section has many optional arguments. We will divide them into categories, which will be sorted from most to least frequently used.

General

These are the most basic arguments, used everywhere in Jbeam files, necessary for correct simulation.

number
type
options.nodeWeight
default
The weight of the node in kg
As of game version 0.33.3.0 the default weight of a node is 25 kg
string
type
Groups a set of nodes into a group that can be used later in other sections

This is mostly used to map visible model parts to groups of nodes for deformation.

Nodes can also be assigned to multiple groups on an individual basis, as per the following example:

["f6ll", 0.76, -0.72, 0.83, {"group":["coupe_engine","coupe_windshield"]}],
string
type
options.nodeMaterial
default
Physics material of the node, rubber, metal, etc.

The node physics material affects the default sound events generated by the node, as well as the type of emited particles.

The name should be “NM_” + name of the physics material, for example “NM_METAL”. As of version 0.33.3.0 the following physics materials are available:
METAL, PLASTIC, RUBBER, GLASS, WOOD, FOLIAGE, CLOTH, WATER, ASPHALT, ASPHALT_WET, SLIPPERY, ROCK, DIRT_DUSTY, DIRT, SAND, SANDY_ROAD, MUD, GRAVEL, GRASS, ICE, SNOW, FIRESMALL, FIREMEDIUM, FIRELARGE, SMOKESMALLBLACK, SMOKEMEDIUMBLACK, STEAM, RUMBLE_STRIP, COBBLESTONE, FOLIAGE_THIN, SPIKE_STRIP

Collision

These define what the node will collide with. Also used in every Jbeam file. Usually, collision and selfCollision are used together, while staticCollision is rarely used.

boolean
type
true
default
If the node can collide with anything
This argument affects all types of collision, and has the highest priority - enabling any other collision type will not work if this one is disabled.
boolean
type
false
default
If the node can collide with the vehicle it belongs to
This argument only affects the self-collision type of dynamic collision. It is commonly set to false for nodes that would cause issues if they collided with the rest of the vehicle, but still need to collide with everything else, for example wheels and tires.
boolean
type
true
default
If the node can collide with map objects and terrain
This argument affects static and heightmap collision. It is set to false for wheel center nodes, which can’t collide with the world as that would make the collision offset from the rim edges, but still need to collide with other vehicles for correct crash deformation.

Friction

Define the node’s static and sliding friction. FrictionCoef is used in every Jbeam file and most of the time set to 0.5, slidingFrictionCoef much less, usually just in tires, as its default value is the same as the value set in frictionCoef.

number
type
1
default
Static friction of the node
By default, this affects both static and dynamic friction, which for most vehicle parts are the same for optimization purposes.
number
type
frictionCoef
default
Sliding friction of the node
When this argument is not set, the sliding friction will default to the same value as static friction.

Powertrain

These arguments are used by powertrain components of the car such as the engine.

string
type
A different kind of group, related to powertrain simulation
Used by components such as the engine block, intake, exhaust, radiator, fuel tank, etc.

Props only

These are only used on props, as they have no usability in a vehicle.

boolean
type
false
default
If the node is fixed in 3D space (Can’t move at all)

The top node is fixed:

Fixed nodes will have disabled collision even if the collision argument is set to true.

Sound override

Override the node’s default impact sounds defined by the material. Used for uncommon vehicle parts, i.e. a porta potty bed load. The list of all usable event paths can be found in the World Editor: Window > Audio > SFX Previewer.

string
type
Overrides the node’s generic impact sound event
string
type
Overrides the node’s metal impact sound event
string
type
Overrides the node’s plastic impact sound event

Cargo

Used only on cargo loads.

string
type
Function that defines the change of the node’s weight based on the cargoGroup load in career mode delivery gameplay

Most basic example usage:

["rbc6", 0.0, 0.0, 0.5{"nodeWeightFunction":"=1+$load","cargoGroup":"roofBarCargoBoxA"}],

Offsets

These arguments are almost never set explicitly in Nodes section but rather passed from the Slots section.

dictionary
type
{“x”:0, “y”:0, “z”:0}
default
Offsets the node on the YZ axis, and offsets it in a mirrored fashion on the X axis (m)
dictionary
type
{“x”:0, “y”:0, “z”:0}
default
Offsets the node on the XYZ axis (m)

Advanced tire friction parameters

Used by the wheel and tire system, not set manually.

float
type
The friction coefficient modifier on zero load.
This value should be higher than the “fullLoadCoef”.
float
type
The friction coefficient modifier on full load.
This value should be lower than the “noLoadCoef”.
float
type
1.75
default
Allows finer control of the sliding friction curve.
Smaller values will result in a more progressive transition.
float
type
Allows finer control of the sliding friction curve.
Affects the velocity at which the sliding coefficient will apply.
float
type
0.6
default
Affects tire squeal
Harder tires squeal more.
float
type
1
default
Multiplies ground roughness coefficient for this node.
A slick tire will be 0, an offroad tire about 0.9 and a standard tire 0.7.
float
type
The loss of coef per newton of normal force
The friction coefficient will keep going down from the “noLoadCoef” until it reaches the “fullLoadCoef”, at which point it will stay stable.
string
type
Groups the inner and outer tire nodes into pairs

This argument is used to generate tire marks. The middle point between 2 paired nodes that are touching the ground is set as the tire mark location, and the distance between them dictates its width.

This argument is set automatically by the wheel generator. You should not use it manually as it might lead to issues with vehicle tires.

Debug

These are for short term debug purposes and should be removed in the final version of the structure.

dictionary
type
{“radius”:0,“col”:"#00000000"}
default
Highlights the node with the provided radius and color when the node visualization debug mode is turned on.

The table consists of 2 elements: “radius” is a number that sets the highlight radius in meters and “col” is either a string with the hex value of the color, or a table with RGB values. Example usage:

["a", -0.90, -0.93, 0.23, {
    "highlight":{
        "radius":0.005,
        "col":"#ff0000ff"
    }
}],

This will produce the same effect:

["a", -0.90, -0.93, 0.23, {
    "highlight":{
        "radius":0.005,
        "col":{
            "r":255,
            "g":0,
            "b":0,
            "a":255
        }
    }
}],

Simple Example

Node a sits somewhere in 3D space:

"nodes" :[
  ["id", "posX", "posY", "posZ"],
  ["a", -0.90, -0.93, 0.23],
],

Node a sits somewhere in 3D space and has the mass of 3 kg.

"nodes" :[
  ["id", "posX", "posY", "posZ"],
  ["a", -0.90, -0.93, 0.23, {"nodeWeight": 3}],
],

Advanced Example

Example of a typical node section, which begins by initializing all the properties that will be used for the following nodes.

{
   "nodes" :[
     ["id", "posX", "posY", "posZ"],
     {"group":"body"},
     {"selfCollision":false}
     {"collision" :true}
     {"nodeMaterial":"|NM_METAL"},
     {"frictionCoef":0.7},
     {"nodeWeight":12.5},
     // a comment
     ["n1rr", -0.90, -0.93, 0.23],
     ["n1r", -0.33, -0.95, 0.23],
     ["n1l", 0.33, -0.95, 0.23],
     ["n1ll", 0.90, -0.93, 0.23],
     {"group":""},

  ],
}
0.33.3.0 contains 122648 entries in 9066 sections distributed over 17428 parts in 4472 jbeam files.
Last modified: September 18, 2024

Any further questions?

Join our discord
Our documentation is currently incomplete and undergoing active development. If you have any questions or feedback, please visit this forum thread.