Docs

Math & Utilities

Doriax includes a complete set of math and utility types that are shared across rendering, physics, animation, input, and gameplay code. Understanding these types helps you write efficient, readable Doriax scripts.

Vector types

Type Dimensions Typical uses
Vector2 2D (x, y) Positions, sizes, velocities, UV coordinates
Vector3 3D (x, y, z) Positions, directions, scales, normals
Vector4 4D (x, y, z, w) Colors (RGBA), homogeneous coordinates, packed data
-- Create vectors
local pos = Vector3(10, 5, 0)
local dir = Vector3(0, 1, 0)
local target = Vector3(0, 5, 0)

-- Arithmetic
local newPos = pos + dir * 3.0   -- 3.0 * dir works too
local dist   = pos:length()
local unit   = dir:normalized()
local dot    = pos:dotProduct(dir)

-- Step toward a point without passing it, or blend toward it
local stepped = pos:moveTowards(target, 4 * Engine.deltatime)
local halfway = pos:lerp(target, 0.5)

All three vector types have moveTowards and lerp. moveTowards moves at a fixed speed and stops exactly on the target, which suits movement driven by deltatime. lerp covers a fraction of the remaining distance, so it slows down near the target.

Common static constants

Constant Value
Vector3.ZERO (0, 0, 0)
Vector3.UNIT_SCALE (1, 1, 1)
Vector3.UNIT_X (1, 0, 0)
Vector3.UNIT_Y (0, 1, 0)
Vector3.UNIT_Z (0, 0, 1)

Changing one component of a property

Properties such as position, scale, rotation, color or linearVelocity return a copy of the value. Changing a component of that copy does not reach the object, so self.object.position.y = 2 runs without error but leaves the object where it was. Assign the whole value instead:

local pos = self.object.position
pos.y = 2                    -- only the copy changes
self.object.position = pos   -- now the object moves

-- the same, building a new vector
self.object.position = Vector3(pos.x, 2, pos.z)

-- or with a setter that takes the components
self.object:setPosition(pos.x, 2, pos.z)

Not every property has such a setter: setScale takes one uniform factor, and bodies have none for position or linearVelocity.

The same holds for methods that change a vector in place, such as normalize(), for values returned by methods like object:getWorldPosition(), and for list properties such as scene.postProcessPasses: they act on a copy. Code Editor completion marks properties that return a copy, e.g. Object.position -> Vector3 (copy).

Component fields are the exception: Lua gets the field itself, not a copy, so image:getUIComponent().color.x = 1 changes the component. Some fields also need their needUpdate… flag set; see Writing components directly.

Quaternion

Quaternion represents 3D rotation. Prefer quaternions over Euler angles for rotation interpolation and composition.

-- Create from Euler angles (ZYX order; degrees if useDegrees is enabled)
local q = Quaternion(0, 90, 0)

-- Interpolate (interpolation factor comes first)
local result = Quaternion.slerp(0.5, q1, q2)

-- Rotate a direction
local rotated = q * Vector3(1, 0, 0)  -- same as q:xAxis()

-- Face a target with the local +Z axis
obj.rotation = Quaternion.lookRotation(target - obj.position)

Matrix types

Type Use
Matrix3 3×3 transforms, normal matrix
Matrix4 4×4 transforms, projection, view matrix

Matrices are used internally by the renderer and physics, but you can construct them for custom transforms or pass them to shader uniforms.

Rect

Rect stores a 2D rectangle as (x, y, width, height). Use it for UI bounds, sprite atlas frames, and screen-space regions.

local frame = Rect(64, 0, 32, 32)   -- x=64, y=0, w=32, h=32
local contains = frame:contains(Vector2(70, 10))

Bounds and spatial queries

Class Use
AABB Axis-aligned bounding box — fast broad-phase tests, frustum culling
OBB Oriented bounding box — rotated objects that AABB over-approximates
Sphere Sphere bounds — broad-phase tests, shadow radius, audio range
Ray Ray from origin in a direction — picking, raycasts, line-of-sight
Plane Infinite plane defined by normal and distance — frustum planes, clip tests
-- Cast a ray through the cursor and test it against the scene's 3D physics bodies
local pos = Input.getMousePosition()
local ray = camera:screenToRay(pos.x, pos.y)
local result = ray:intersects(scene, RayFilter.BODY_3D)
if result.hit then
    print("Hit entity:", result.body, "at distance", result.distance)
end

intersects also accepts individual AABB, OBB, Plane, Body2D, and Body3D targets, and RayFilter.BOUNDS tests every mesh's bounding box without any physics. Pass an entity or a list of entities to skip those bodies so the ray continues through them (ray:intersects(scene, RayFilter.BODY_3D, self.entity)). The returned RayReturn carries hit, distance, point, normal, body (the entity), and shapeIndex.

Angles

The Angle utility class provides explicit degree/radian conversions. The engine can be configured to use degrees everywhere with Engine::setUseDegrees(true).

-- Convert explicitly regardless of engine setting
local rad = Angle.degToRad(90)
local deg = Angle.radToDeg(math.pi / 2)

Color utilities

The static Color class provides sRGB ↔ linear conversions. Rendering expects linear color space internally.

-- Convert from sRGB to linear for the renderer
local linearRed = Color.sRGBToLinear(Vector3(1, 0, 0))

-- And back for display values
local srgb = Color.linearTosRGB(linearRed)

Logging

Log provides formatted console output at different severity levels.

-- The Lua functions take a single string; use .. for formatting
Log.print("Scene loaded")
Log.debug("Player position: " .. tostring(obj.position))
Log.warn("Optional resource missing: " .. path)
Log.error("Physics body creation failed")
// The C++ functions accept printf-style format arguments
Log::print("Scene loaded");
Log::debug("Player position: %s", position.toString().c_str());
Log::warn("Optional resource missing: %s", path.c_str());
Log::error("Physics body creation failed");

Use Log::debug for development-only output. Release builds can strip debug logs by setting the appropriate log level.

Object utility

The Object class wraps an entity handle and provides transform, visibility, parenting, and basic physics convenience APIs. Use it when you need to access transform data from a script without knowing the specific object type.

local Mover = {
    properties = {
        { name = "speed", displayName = "Speed", type = "float", default = 50.0 }
    }
}

function Mover:init()
    RegisterEngineEvent(self, "onUpdate")
end

function Mover:onUpdate()
    local obj = Object(self.scene, self.entity)
    local dt = Engine.deltatime
    obj.position = obj.position + Vector3(0, self.speed * dt, 0)
end

return Mover

Base64

The Base64 utility class encodes and decodes binary data as base64 strings. Useful for embedding small binary data in JSON or YAML, or for network/save serialization. C++ only — encode / decode are not exposed to Lua yet.

See also