Godot 3D Vector/Physics Cheat-Sheet:
This is supposed to be a reference for use with 3D Vector/Transform/Physics operations.
It won't contain much explanations but some examples. And it is supposed to never be complete.
There is already some information about 3D Vectors and Transforms:
I also did two little godot demo projects which should be attached to this post:
Just some Basics:
Godot has values but no units. If you work with physics you might want some units sooner or later to have a scale or for output purposes.
I assume that the value 1 in Godots coordinate space is one metre. The phyics engine also seems to implicitly use 1 second as time scale.
I also assume that the mass value of 1 equals 1kg. Weight (better ignore it) depends on the gravity and is 1N(ewton) at 1g = 9.81m/sec².
So a velocity of 1 is 1 m/sec = 3.6 km/h.
So a gravity value 9.8 equals 9.8m/sec².
A force of 1 probably is 1N*m (Newton metre or 1 Joule)
contains 2 members:
Vector3 with the 3 coordinates of the position. So
transform.origin equals the property
A matrix of 3 x
Vector3. It contains the normalized direction vectors of X/Y/Z-Axis.
B.t.w.: "normalized" means a vector is scaled to length 1
transform.basis.z therefore is a
Vector3 that contains the direction of the Z-Axis
This basically defines the rotation of a
Transform. A single component (i.e.
transform.basis.x) will give you the direction but not the orientation (where's the upside of the object/transform?).
Spatial you can either use the property
transform specifies the local rotation and position of a Spatial inside its parent.
transform.basis.x|y|z will return the axis-vectors rotated by the local rotation.
transform.origin will return the local offset of a Spatial inside its parent.
Rotation/position in the games 3D-Space.
A turret on a tank. The
transform of the turret won't change when the tank moves and turns. But the
If the turret turns, the values of the turrets
transform.basis will change to represet its rotation relative to the tank.
looking_at / look_at / look_at_from_position
These methods basically all do the same:
Spatial (and descendants) offers
void look_at ( Vector3 target, Vector3 up ) and
void look_at_from_position ( Vector3 position, Vector3 target, Vector3 up )
Transform looking_at ( Vector3 target, Vector3 up )
This methods calculates the
transform.basis (rotation) matrix which is needed to let the forward vector (Vector3(0,0,-1)) point from Transform.origin to the target coordinates. The "up" Vector defines the orientation of the resulting Transform.basis.
You have a node with a "head" mesh. When you let that head "look_at" another node and you pass a down-vector (Vector3(0,-1,0)) then the hair will be below the head. If you pass an up-vector (Vector3(0,1,0)) then the hair will be on the upside of the head. In any way the head will always point in the right direction, only the orientation is different.
Limiting the look_at to a plane:
You might often want to limit the rotation of your "head" to one axis. This can be achieved by setting the coord outside the plane to the same value. For example: If you want to limit the rotation to the y-axis (x/z-plane) then use the same y-coordinate for source and target.
head.look_at_from_pos(Vector3(get_translation().x,target.get_translation().y,get_translation().z), \ target.get_translation(),Vector3(0,1,0))
Avoid whereever possible. Try to reduce coords to 2D when working with angles or you might enter the "gimbal lock" hell.
That is: Angles tend to "suddenly" switch "upside down" at one point in rotation which can mess up angle based calculation.
Spatials heading in X/Z space should be something like this:
Since godot 3.x (yes it changed from godot 2.x) the coordinate system turns counter clock-wise. So if you want a compass heading you'd need to calc a bit:
compass_heading = 360-rad2deg(angle) (untested)
Rotating a local offset by Spatials rotation:
Another way to rotate a local offset:
var relOffset = (0,0,-1)
var relRotPos = transform.basis.xform(relOffset)
Velocities: (and some 3D Vector math)
Vector3 of a Body (i.e. RigidBody)
linear_velocity delivers always the global velocity.
If you want to know how to convert this to a local/rotated velocity, see below.
This should calculate the speed of a point on a rotating Body:
var relativePosition = Vector3(0,0,-1) #sample value, 1m to "front"
var tangVelo = angular_velocity.cross(relativePosition)
How much km/h are this?
var kph = tangVelo.length() * 3.6
Note: this velocity is relative to the parent and the objects velocity.
The absolute/global speed of the rotating point should be
Which (local) "forward" speed has a Body?
Rotate global velocity by rotation basis in Bodies
global_transform and use only the z-component of the relative velocity.
var kph = global_transform.basis.xform_inv(linear_velocity).z*-3.6
global_transform is used because the
linear_velocity is also global.
Absolute velocity of a child node which is on a rotating and moving parent body:
#1: Get the position of a person on a rotating platform (in parent coords):
The person is at relative coordinate x=-2, z=-3 on that platform. (before rotation)
Now rotate this:
var relRotPos = transform.basis.x * -2 + transform.basis.z*-3
(see also "rotating a local offset" above)
#2: Now calculate the tangential velocity (rotation speed) and add it to the current velocity (moving speed):
There are file attachments with the demo projects:
3d_vectors_demo_v3.zip: Is for use with Godot 3.x (tested in Godot 3.1 beta 3)
3d_vectors_demo.zip: Is for use with Godot 2.x (!)
(As download link because of technical difficulties in forum)
spaceship.zip: Simple space game about forces, rigidbodies with a following camera.