acron.interop¶
Godot(Y-up) <-> Acron(Z-up) conventions – the single source of truth.
Godot is Y-up, right-handed; Acron is Z-up, right-handed. acron-gltf
already converts loaded glTF geometry Y-up -> Z-up on load, so models arrive in
Acron space and must NOT be rotated again. What still needs converting is every
literal vector or transform copied straight out of the GDScript / .tscn
(spawn points, Vector3.UP, gravity, hand-typed directions).
Two conventions are supported, matching the two porting styles our ports used:
1. Direct swap (the TPS style). Godot (x, y, z) -> Acron (x, z, y).
The swap is an involution (its own inverse) – but it has determinant -1: it is a
REFLECTION, valid only for direction/position vectors (gravity, Vector3.UP,
velocities, offsets), never as a rotation-matrix basis. For full transforms use
acron.transform, which handles the basis correctly.
2. Y-up logic frame (the racing style). For dense ported math (vehicle
dynamics) keep the equations verbatim in a Godot-style Y-up frame: a child node
with set_hpr(0, 90, 0) so local +Y is world +Z (attach_logic_frame()),
converting only at the solver/render boundary. The frame mapping is the PROPER
ROTATION (x, y, z) -> (x, -z, y) (g2p_rot()). Chirality trap: for
world data (track collision, markers) shared with such a frame you must use the
rotation convention, not the reflection swap – mixing them mirrors the world
relative to the logic frame (the symptom is geometry that only matches through an
impossible mirror). Use the reflection swap only for symmetric vectors
(gravity, up).
For transforming vectors through a node’s frame (Godot xform/xform_inv)
call NodePath.get_relative_vector / get_relative_point directly.
Global Functions
- apply_vertical_fov(lens, vfov_degrees: float, eps: float = 0.01) bool¶
Set a lens’s field of view from the AUTHORED, VERTICAL angle.
Godot (and most engines’ camera authoring) states fov vertically; Acron’s
Lens.set_fov(x)sets the HORIZONTAL angle and derives the vertical from the aspect ratio. Handing it the vertical number renders the same scene through a much longer lens — which reads as a subtly wrong camera rather than a bug, and quietly changes how much world is on screen and what a frame costs.Converts through the lens’s own aspect ratio and sets only the horizontal angle, so a window resize re-derives the vertical — and calling this every frame is what brings it back round to correct after one. Returns True when the lens was actually written (skipped inside
epsdegrees, so a per-frame caller costs one comparison).
- attach_logic_frame(parent, name: str = 'logic_frame')¶
Attach a Godot-style Y-up child frame under
parent.Inside the returned node, ported math can treat +Y as up exactly as the GDScript does; the node’s
hpr(0, 90, 0)maps local +Y to the parent’s +Z. Verify empirically withrender.get_relative_vector(frame, (0, 1, 0)).
- g2p(v) LVector3f¶
Vector from the Godot Y-up frame to the Acron Z-up frame (axis swap).
Accepts anything indexable
[0]/[1]/[2]. The swap is an involution, sop2g()is the same operation under a name that documents direction.
- g2p_rot(v) LVector3f¶
Godot/logic-frame vector -> Acron world via the PROPER ROTATION.
(x, y, z) -> (x, -z, y)– the mapping performed by aattach_logic_frame()node (hpr 0,90,0). Unlikeg2p()this preserves chirality, so it is the correct convention for world data (collision meshes, markers) used alongside a logic frame.
- godot_to_acron_vec(x: float, y: float, z: float) LVector3f¶
Convert a literal Godot
Vector3(x, y, z)to a AcronLVector3.Godot Y (up) becomes Acron Z (up); Godot Z becomes Acron Y. Positions use the same swap (build an
LPoint3from the result).