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
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.
0.33.3.0
the default weight of a node is 25 kg
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"]}],
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.
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.
Powertrain
These arguments are used by powertrain components of the car such as the engine.
Props only
These are only used on props, as they have no usability in a vehicle.
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.
Cargo
Used only on cargo loads.
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.
Advanced tire friction parameters
Used by the wheel and tire system, not set manually.
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.
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.