-
Notifications
You must be signed in to change notification settings - Fork 18
pyvec
The pyvec.* api functions provide vector, matrix and plane math for 3D plugin work.
PYTHA has no built-in math type system, so historically every plugin re-implemented its own vec3 / mat4 helpers. The pyvec namespace fills that gap with a small, dependency-free library.
A vec3 is a plain Lua array {x, y, z} carrying a metatable. Because PYTHA coordinate parameters are themselves {x, y, z} arrays (see Axes and Directions), a vec3 can be passed directly into any pytha.* function that expects a point or direction — no conversion needed. Conversely, the free functions (pyvec.dot, pyvec.cross, ...) also accept ordinary {x, y, z} tables returned by the API; only the arithmetic operators require a real vec3.
A mat4 is a 4×4 affine transform stored row-major as a flat array of 16 numbers (the element at row r, column c is index (r-1)*4 + c). The bottom row is assumed to be {0, 0, 0, 1}.
A plane is stored as {normal, d} with a unit normal satisfying normal · p + d = 0.
All angles are in degrees, consistent with PYTHA's global math helpers.
| Function | Description |
|---|---|
pyvec.vec3(x, y, z) |
Creates a vec3 from three numbers. Missing components default to 0. |
pyvec.vec3{x, y, z} |
Creates a vec3 from (clones) an existing point table — handy to wrap an API return value. |
These are free functions and are also available as methods, e.g. a:dot(b) is the same as pyvec.dot(a, b).
| Function | Description |
|---|---|
pyvec.dot(a, b) |
Dot product (number). |
pyvec.cross(a, b) |
Cross product (vec3). |
pyvec.length(v) |
Euclidean length (number). |
pyvec.length_sq(v) |
Squared length (number); avoids the square root. |
pyvec.normalize(v) |
Returns the unit vector and, as a second value, the original length. A zero vector returns (0, 0, 0) and length 0. |
pyvec.distance(a, b) |
Distance between two points. |
pyvec.distance_sq(a, b) |
Squared distance between two points. |
pyvec.scale(v, s) |
v scaled by the scalar s (vec3). |
pyvec.lerp(a, b, t) |
Linear interpolation; t = 0 → a, t = 1 → b. |
pyvec.angle_between(a, b) |
Angle between the two vectors in degrees (0..180). |
pyvec.approx_equal(a, b [, eps]) |
Component comparison with tolerance eps (default 1e-9). |
| Operator | Result |
|---|---|
a + b, a - b
|
Component-wise addition / subtraction (vec3). |
-a |
Negation (vec3). |
a * s, s * a
|
Scalar multiplication (vec3). |
a / s |
Scalar division (vec3). |
a == b |
Exact component equality. Use pyvec.approx_equal for a tolerant compare. |
tostring(a) |
"vec3(x, y, z)". |
a * bbetween two vec3 raises an error on purpose — the intent is ambiguous. Usepyvec.dotorpyvec.crossexplicitly.
| Function | Description |
|---|---|
pyvec.mat4(...) |
Builds a matrix from 16 numbers or a 16-element table. With no arguments it returns the identity. |
pyvec.identity() |
Identity matrix. |
pyvec.translation(t) |
Translation by the point/vec3 t. |
pyvec.scaling(s) |
Uniform scale (number) or per-axis scale (point/vec3). |
pyvec.rotation(axis, angle) |
Rotation about axis through the origin by angle degrees. Right-handed: a positive angle turns counter-clockwise looking down the axis. |
pyvec.from_axes(origin, u, v, w) |
Transform whose columns are the given axes and origin; maps local coordinates to world. The axes are used verbatim and are not orthonormalized. |
pyvec.frame(origin, u_dir, w_dir) |
Builds an orthonormal right-handed frame (u × v = w) from a primary direction u_dir and an approximate up direction w_dir. Mirrors PYTHA's own axis correction (see Axes and Directions). |
pyvec.mat_multiply(a, b) |
Matrix product a · b (mat4). |
pyvec.transform_point(mat, p) |
Transforms point p, applying translation (vec3). |
pyvec.transform_vector(mat, d) |
Transforms direction d, ignoring translation (vec3). |
pyvec.transpose(mat) |
Transposed matrix. |
pyvec.inverse(mat) |
Matrix inverse via Gauss-Jordan elimination. Raises an error if mat is singular. Useful for world → local conversion. |
Operators and methods:
| Operator / method | Result |
|---|---|
mat * other |
Matrix product, when both operands are mat4. |
mat * p |
Transforms the point p, when p is a point/vec3 — same as transform_point. |
mat:transform_point(p), mat:transform_vector(d), mat:multiply(other), mat:transpose(), mat:inverse()
|
Method forms of the functions above. |
tostring(mat) |
Formatted 4×4 layout. |
| Function | Description |
|---|---|
pyvec.plane(point, normal) |
Plane through point with the given normal (normalized internally). |
pyvec.plane_from_points(a, b, c) |
Plane through three points; the normal follows the right-hand rule for the order a → b → c. |
pyvec.signed_distance(pl, p) |
Signed distance from p to the plane; positive on the side the normal points to. |
pyvec.project_point(pl, p) |
Orthogonal projection of p onto the plane (vec3). |
Methods: pl:signed_distance(p), pl:project_point(p).
| Function | Description |
|---|---|
pyvec.is_vec3(v) |
true if v is a pyvec vec3. |
pyvec.is_mat4(m) |
true if m is a pyvec mat4. |
pyvec.is_plane(p) |
true if p is a pyvec plane. |
-- Build an orthonormal frame from a wall direction and world up.
local origin = pyvec.vec3(1.0, 0.5, 0.0)
local frame = pyvec.frame(origin, pyvec.vec3(1, 1, 0), pyvec.vec3(0, 0, 1))
-- A point given in the frame's local coordinates, expressed in world space.
local world_pt = frame:transform_point(pyvec.vec3(0.2, 0.0, 0.8))
-- world_pt is a {x, y, z} array and can be passed straight to pytha.*:
pytha.create_block(world_pt, 0.1, 0.1, 0.1)
-- Go the other way: world -> local.
local local_pt = frame:inverse():transform_point(world_pt)
-- Distance of a point from a plane through three corners.
local pl = pyvec.plane_from_points(
pyvec.vec3(0, 0, 0), pyvec.vec3(1, 0, 0), pyvec.vec3(0, 1, 0))
local d = pl:signed_distance(pyvec.vec3(0, 0, 2)) -- 2.0Minimum PYTHA Version: V27
Math functions, Axes and Directions, pytha.push_local_coordinates, pytha.rotate_element, pygeo