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
Left is positive, right is negative
number
type
The Y (forward/back) position in 3D space
Backward is positive, forward is negative
number
type
The Z (up/down) position in 3D space
Up is positive, down is negative

Optional arguments

number
type
options.nodeWeight
default
The weight of the node in kg
As of game version 0.31.3.0 the default weight of a node is 25 kg
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.
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
A different kind of group, related to powertrain simulation
Used by components such as the engine block, intake, exhaust, radiator, fuel tank, etc.
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.
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.

As of version 0.31.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

string
type
Overrides the node’s generic impact sound event

The default sound event is determined by the physics material. This property can override it, which is useful 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 metal impact sound event

The default sound event is determined by the physics material. This property can override it, which is useful 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 plastic impact sound event

The default sound event is determined by the physics material. This property can override it, which is useful 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.

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.

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
This is 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 XYZ axis.
This is almost never set explicitly in Nodes section but rather passed from the Slots section.
float
type
The friction coefficient modifier on zero load.

Used by tires.

This value should be higher than the “fullLoadCoef”.

float
type
The friction coefficient modifier on full load.

Used by tires.

This value should be lower than the “noLoadCoef”.

float
type
1.75
default
Allows finer control of the sliding friction curve.

Used by tires.

Smaller values will result in a more progressive transition.

float
type
Allows finer control of the sliding friction curve.

Used by tires.

Affects the velocity at which the sliding coefficient will apply.

float
type
0.6
default
Affects tire squeal

Used by tires.

Harder tires squeal more.

float
type
1
default
Multiplies ground roughness coefficient for this node.

Used by tires.

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

Used by tires.

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

Used by tires.

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.

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.31.3.0 contains 111916 entries in 8197 sections distributed over 15631 parts in 4059 jbeam files.
Last modified: 22/1/2024 08:56

Any further questions?

Join our discord