@needle-tools/engine
Version:
Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.
227 lines (226 loc) • 8.89 kB
TypeScript
import type { Quaternion, Vector2, Vector3, Vector4 } from "three";
import type { Vec3 } from "./engine_types.js";
declare type Vector = Vector3 | Vector4 | Vector2 | Quaternion;
/**
* Math utility class providing common mathematical operations.
* Access via the exported `Mathf` constant.
*
* @example
* ```ts
* import { Mathf } from "@needle-tools/engine";
*
* // Random number between 0 and 10
* const rand = Mathf.random(0, 10);
*
* // Clamp a value
* const clamped = Mathf.clamp(value, 0, 100);
*
* // Smooth interpolation
* const smoothed = Mathf.lerp(start, end, t);
* ```
*/
declare class MathHelper {
/**
* Returns a random number or element.
* @param arr Array to pick a random element from
* @returns Random element from array, or null if array is empty
* @example `Mathf.random([1, 2, 3])` - returns random element
*/
random<T>(arr: Array<T>): T | null;
/**
* Returns a random number between min and max (inclusive).
* @param min Minimum value (inclusive)
* @param max Maximum value (inclusive)
* @returns Random number in range, or 0-1 if no args provided
* @example `Mathf.random(0, 10)` - returns 0 to 10
*/
random(min?: number, max?: number): number;
/**
* Fills a Vector3 with random values.
* @param target Vector3 to fill with random values
* @param min Minimum value for each component
* @param max Maximum value for each component
*/
randomVector3(target: Vector3, min?: number, max?: number): void;
/**
* Clamps a value between min and max.
* @param value Value to clamp
* @param min Minimum bound
* @param max Maximum bound
* @returns Clamped value
*/
clamp(value: number, min: number, max: number): number;
/**
* Clamps a value between 0 and 1.
* @param value Value to clamp
* @returns Value clamped to [0, 1]
*/
clamp01(value: number): number;
/**
* Linearly interpolates between two values.
* @param value1 Start value (returned when t=0)
* @param value2 End value (returned when t=1)
* @param t Interpolation factor, clamped to [0, 1]
* @returns Interpolated value
*/
lerp(value1: number, value2: number, t: number): number;
/**
* Calculates the linear interpolation parameter that produces the given value.
* Inverse of lerp: if `lerp(a, b, t) = v`, then `inverseLerp(a, b, v) = t`
* @param value1 Start value
* @param value2 End value
* @param t The value to find the parameter for
* @returns The interpolation parameter (may be outside [0,1] if t is outside [value1, value2])
*/
inverseLerp(value1: number, value2: number, t: number): number;
/**
* Remaps a value from one range to another.
* @param value The value to remap.
* @param min1 The minimum value of the current range.
* @param max1 The maximum value of the current range.
* @param min2 The minimum value of the target range.
* @param max2 The maximum value of the target range.
*/
remap(value: number, min1: number, max1: number, min2: number, max2: number): number;
/**
* Moves a value towards a target by a maximum step amount.
* Useful for smooth following or gradual value changes.
* @param value1 Current value
* @param value2 Target value
* @param amount Maximum step to move (positive moves toward target)
* @returns New value moved toward target, never overshooting
*/
moveTowards(value1: number, value2: number, amount: number): number;
readonly Rad2Deg: number;
readonly Deg2Rad: number;
readonly Epsilon = 0.00001;
/**
* Converts radians to degrees
*/
toDegrees(radians: number): number;
/**
* Converts degrees to radians
*/
toRadians(degrees: number): number;
tan(radians: number): number;
gammaToLinear(gamma: number): number;
linearToGamma(linear: number): number;
/**
* Checks if two vectors are approximately equal within epsilon tolerance.
* Works with Vector2, Vector3, Vector4, and Quaternion.
* @param v1 First vector
* @param v2 Second vector
* @param epsilon Tolerance for comparison (default: Number.EPSILON)
* @returns True if all components are within epsilon of each other
*/
approximately(v1: Vector, v2: Vector, epsilon?: number): boolean;
/**
* Easing function: slow start, fast middle, slow end (cubic).
* @param x Input value from 0 to 1
* @returns Eased value from 0 to 1
*/
easeInOutCubic(x: number): number;
}
export declare const Mathf: MathHelper;
declare class LowPassFilter {
y: number | null;
s: number | null;
alpha: number;
constructor(alpha: number);
setAlpha(alpha: number): void;
filter(value: number, alpha: number): number;
lastValue(): number | null;
reset(value: number): void;
}
/**
* [OneEuroFilter](https://engine.needle.tools/docs/api/OneEuroFilter) is a low-pass filter designed to reduce jitter in noisy signals while maintaining low latency.
* It's particularly useful for smoothing tracking data from XR controllers, hand tracking, or other input devices where the signal contains noise but responsiveness is important.
*
* The filter automatically adapts its smoothing strength based on the signal's velocity:
* - When the signal moves slowly, it applies strong smoothing to reduce jitter
* - When the signal moves quickly, it reduces smoothing to maintain responsiveness
*
* Based on the research paper: [1€ Filter: A Simple Speed-based Low-pass Filter for Noisy Input](http://cristal.univ-lille.fr/~casiez/1euro/)
*
* @example Basic usage with timestamp
* ```ts
* const filter = new OneEuroFilter(120, 1.0, 0.0);
*
* // In your update loop:
* const smoothedValue = filter.filter(noisyValue, this.context.time.time);
* ```
*
* @example Without timestamps (using frequency estimate)
* ```ts
* // Assuming 60 FPS update rate
* const filter = new OneEuroFilter(60, 1.0, 0.5);
*
* // Call without timestamp - uses the frequency estimate
* const smoothedValue = filter.filter(noisyValue);
* ```
*
* @example Smoothing 3D positions
* ```ts
* const posFilter = new OneEuroFilterXYZ(90, 0.5, 0.0);
*
* posFilter.filter(trackedPosition, smoothedPosition, this.context.time.time);
* ```
*
* @see {@link OneEuroFilterXYZ} for filtering 3D vectors
*/
export declare class OneEuroFilter {
/**
* An estimate of the frequency in Hz of the signal (> 0), if timestamps are not available.
*/
freq: number;
/**
* Min cutoff frequency in Hz (> 0). Lower values allow to remove more jitter.
*/
minCutOff: number;
/**
* Parameter to reduce latency (> 0). Higher values make the filter react faster to changes.
*/
beta: number;
/**
* Used to filter the derivates. 1 Hz by default. Change this parameter if you know what you are doing.
*/
dCutOff: number;
/**
* The low-pass filter for the signal.
*/
x: LowPassFilter;
/**
* The low-pass filter for the derivates.
*/
dx: LowPassFilter;
/**
* The last time the filter was called.
*/
lasttime: number | null;
/** Create a new OneEuroFilter
* @param freq - An estimate of the frequency in Hz of the signal (> 0), if timestamps are not available.
* @param minCutOff - Min cutoff frequency in Hz (> 0). Lower values allow to remove more jitter.
* @param beta - Parameter to reduce latency (> 0). Higher values make the filter react faster to changes.
* @param dCutOff - Used to filter the derivates. 1 Hz by default. Change this parameter if you know what you are doing.
*/
constructor(freq: number, minCutOff?: number, beta?: number, dCutOff?: number);
alpha(cutOff: number): number;
/** Filter your value: call with your value and the current timestamp (e.g. from this.context.time.time) */
filter(x: number, time?: number | null): number;
reset(x?: number): void;
}
export declare class OneEuroFilterXYZ {
readonly x: OneEuroFilter;
readonly y: OneEuroFilter;
readonly z: OneEuroFilter;
/** Create a new OneEuroFilter
* @param freq - An estimate of the frequency in Hz of the signal (> 0), if timestamps are not available.
* @param minCutOff - Min cutoff frequency in Hz (> 0). Lower values allow to remove more jitter.
* @param beta - Parameter to reduce latency (> 0). Higher values make the filter react faster to changes.
* @param dCutOff - Used to filter the derivates. 1 Hz by default. Change this parameter if you know what you are doing.
*/
constructor(freq: number, minCutOff?: number, beta?: number, dCutOff?: number);
filter(value: Vec3, target: Vec3, time?: number | null): void;
reset(value?: Vec3): void;
}
export {};