lecodes-sdk 0.20.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/global.d.ts +35 -9
- package/dist/types/animate/tween/Animation.d.ts +69 -0
- package/dist/types/animate/tween/Timeline.d.ts +55 -0
- package/dist/types/animate/tween/animateValue.d.ts +27 -0
- package/dist/types/animate/tween/easing.d.ts +29 -0
- package/dist/types/animate/tween/spec.d.ts +178 -0
- package/dist/types/canvas/Canvas.d.ts +2 -0
- package/dist/types/g2/Node2D.d.ts +16 -0
- package/dist/types/g2/Sprite.d.ts +11 -1
- package/dist/types/gl/Camera.d.ts +15 -1
- package/dist/types/gl/DecalSet.d.ts +48 -3
- package/dist/types/gl/Foliage.d.ts +47 -0
- package/dist/types/gl/Geometry.d.ts +36 -0
- package/dist/types/gl/Light.d.ts +25 -7
- package/dist/types/gl/Lightmap.d.ts +90 -51
- package/dist/types/gl/Material.d.ts +32 -20
- package/dist/types/gl/Mesh.d.ts +7 -1
- package/dist/types/gl/Model.d.ts +41 -5
- package/dist/types/gl/Node.d.ts +18 -0
- package/dist/types/gl/Particles.d.ts +53 -1
- package/dist/types/gl/Scene.d.ts +21 -1
- package/dist/types/gl/animation/AnimationClip.d.ts +19 -0
- package/dist/types/gl/animation/Animator.d.ts +27 -0
- package/dist/types/gl/animation/DynamicBone.d.ts +184 -0
- package/dist/types/gl/animation/IK.d.ts +109 -0
- package/dist/types/gl/{Locomotion.d.ts → animation/Locomotion.d.ts} +6 -6
- package/dist/types/gl/animation/Warp.d.ts +2 -1
- package/dist/types/gl/animation/core.d.ts +35 -4
- package/dist/types/gl/{AudioSource.d.ts → audio/AudioSource.d.ts} +6 -6
- package/dist/types/gl/{AudioZone.d.ts → audio/AudioZone.d.ts} +4 -4
- package/dist/types/gl/{SceneAudio.d.ts → audio/SceneAudio.d.ts} +1 -1
- package/dist/types/gl/{NavAgent.d.ts → nav/NavAgent.d.ts} +4 -4
- package/dist/types/gl/{NavMesh.d.ts → nav/NavMesh.d.ts} +4 -4
- package/dist/types/gl/{CharacterController.d.ts → physics/CharacterController.d.ts} +5 -5
- package/dist/types/gl/{Physics.d.ts → physics/Physics.d.ts} +6 -5
- package/dist/types/gl/physics/Ragdoll.d.ts +161 -0
- package/dist/types/gl/{Shape.d.ts → physics/Shape.d.ts} +3 -3
- package/dist/types/gl/{Trigger.d.ts → physics/Trigger.d.ts} +2 -2
- package/dist/types/gl/{Terrain.d.ts → terrain/Terrain.d.ts} +10 -8
- package/dist/types/gl/{terrainMesh.d.ts → terrain/terrainMesh.d.ts} +1 -1
- package/dist/types/gl/vehicle/Vehicle.d.ts +300 -0
- package/dist/types/gl/vehicle/Wheel.d.ts +147 -0
- package/dist/types/inject.d.ts +35 -27
- package/dist/types/runtime/files.d.ts +24 -1
- package/dist/types/scene/defineScene.d.ts +50 -31
- package/dist/types/ui/UIButton.d.ts +3 -1
- package/dist/types/ui/UIInput.d.ts +5 -1
- package/dist/types/ui/UINode.d.ts +24 -24
- package/dist/types.json +1 -1
- package/package.json +1 -1
- package/prompts/README.md +142 -142
- package/prompts/core-design.md +27 -4
- package/prompts/core.md +35 -6
- package/prompts/select.ts +19 -4
- package/src/animate/tween/Animation.ts +378 -0
- package/src/animate/tween/Timeline.ts +175 -0
- package/src/animate/tween/animateValue.ts +100 -0
- package/src/animate/tween/easing.ts +172 -0
- package/src/animate/tween/spec.ts +479 -0
- package/src/bridges.d.ts +1760 -1481
- package/src/canvas/Canvas.ts +21 -0
- package/src/compile/__tests__/assetMacro.test.ts +26 -0
- package/src/compile/__tests__/compile.test.ts +11 -0
- package/src/compile/__tests__/detectEntry.test.ts +19 -0
- package/src/compile/__tests__/serverSplit.test.ts +27 -0
- package/src/compile/bundler.ts +34 -4
- package/src/compile/compileProject.ts +31 -1
- package/src/compile/detectEntry.ts +8 -3
- package/src/compile/header.ts +6 -3
- package/src/compile/index.ts +3 -0
- package/src/compile/sceneEditor.ts +42 -1
- package/src/compile/serverSplit.ts +9 -3
- package/src/g2/Node2D.ts +38 -0
- package/src/g2/Sprite.ts +20 -1
- package/src/gl/Camera.ts +34 -1
- package/src/gl/DecalSet.ts +132 -5
- package/src/gl/Foliage.ts +102 -0
- package/src/gl/Geometry.ts +109 -0
- package/src/gl/Light.ts +46 -16
- package/src/gl/Lightmap.ts +440 -249
- package/src/gl/Material.ts +69 -36
- package/src/gl/Mesh.ts +120 -102
- package/src/gl/Model.ts +167 -124
- package/src/gl/Node.ts +40 -1
- package/src/gl/Particles.ts +82 -5
- package/src/gl/Scene.ts +35 -2
- package/src/gl/animation/AnimationClip.ts +52 -0
- package/src/gl/animation/Animator.ts +42 -2
- package/src/gl/animation/DynamicBone.ts +482 -0
- package/src/gl/animation/IK.ts +214 -0
- package/src/gl/{Locomotion.ts → animation/Locomotion.ts} +7 -7
- package/src/gl/animation/Playback.ts +5 -4
- package/src/gl/animation/Warp.ts +5 -2
- package/src/gl/animation/core.ts +65 -4
- package/src/gl/{AudioSource.ts → audio/AudioSource.ts} +7 -7
- package/src/gl/{AudioZone.ts → audio/AudioZone.ts} +75 -75
- package/src/gl/{SceneAudio.ts → audio/SceneAudio.ts} +2 -2
- package/src/gl/{NavAgent.ts → nav/NavAgent.ts} +5 -5
- package/src/gl/{NavMesh.ts → nav/NavMesh.ts} +8 -8
- package/src/gl/{CharacterController.ts → physics/CharacterController.ts} +5 -5
- package/src/gl/{Physics.ts → physics/Physics.ts} +12 -5
- package/src/gl/physics/Ragdoll.ts +451 -0
- package/src/gl/{Shape.ts → physics/Shape.ts} +3 -3
- package/src/gl/{Trigger.ts → physics/Trigger.ts} +45 -45
- package/src/gl/{physicsEvents.ts → physics/physicsEvents.ts} +1 -1
- package/src/gl/{Terrain.ts → terrain/Terrain.ts} +14 -12
- package/src/gl/{terrainMesh.ts → terrain/terrainMesh.ts} +1 -1
- package/src/gl/vehicle/Vehicle.ts +666 -0
- package/src/gl/vehicle/Wheel.ts +290 -0
- package/src/inject.ts +236 -224
- package/src/runtime/files.ts +32 -2
- package/src/scene/defineScene.ts +92 -66
- package/src/scene/level.ts +2 -2
- package/src/ui/UIButton.ts +2 -2
- package/src/ui/UIInput.ts +3 -3
- package/src/ui/UINode.ts +61 -36
- package/dist/types/animate/animate.d.ts +0 -20
- package/dist/types/gl/Gearbox.d.ts +0 -86
- package/dist/types/gl/IK.d.ts +0 -53
- package/dist/types/gl/Ragdoll.d.ts +0 -86
- package/dist/types/gl/Vehicle.d.ts +0 -191
- package/dist/types/gl/Wheel.d.ts +0 -95
- package/src/animate/animate.ts +0 -238
- package/src/gl/Gearbox.ts +0 -212
- package/src/gl/IK.ts +0 -193
- package/src/gl/Ragdoll.ts +0 -270
- package/src/gl/Vehicle.ts +0 -473
- package/src/gl/Wheel.ts +0 -240
- /package/dist/types/gl/{physicsEvents.d.ts → physics/physicsEvents.d.ts} +0 -0
package/dist/types/gl/IK.d.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { Aspect } from "../core/Aspect";
|
|
2
|
-
import { type Vec3Like } from "../math/vec";
|
|
3
|
-
import { Quat } from "../math/quat";
|
|
4
|
-
import type { Node } from "./Node";
|
|
5
|
-
type Target = Node | Vec3Like;
|
|
6
|
-
/** Two-bone analytic IK (limbs). Attach to the END bone: `foot.aspect(IK.TwoBone, { target })`
|
|
7
|
-
* solves upper (grandparent) + mid (parent) so the end reaches `target`; `pole` steers the bend
|
|
8
|
-
* (knee/elbow) — a Node or world point. */
|
|
9
|
-
declare class TwoBone extends Aspect<"ik", Node> {
|
|
10
|
-
static readonly aspect = "ik";
|
|
11
|
-
/** Where the end bone should be (Node or world position). */
|
|
12
|
-
target?: Target;
|
|
13
|
-
/** Bend hint — the mid joint is pulled toward it (Node or world position). */
|
|
14
|
-
pole?: Target;
|
|
15
|
-
/** World rotation the END bone takes after the solve — a Node (its world rotation) or a Quat.
|
|
16
|
-
* Unset = the end bone keeps its animated local rotation (a hand on a grip, a foot on a slope
|
|
17
|
-
* want it set). Blended by `weight · rotationWeight`. */
|
|
18
|
-
rotation?: Node | Quat;
|
|
19
|
-
/** 0–1 contribution of `rotation` (on top of `weight`). */
|
|
20
|
-
rotationWeight: number;
|
|
21
|
-
/** 0–1 contribution (blend in/out, e.g. foot planting only while grounded). */
|
|
22
|
-
weight: number;
|
|
23
|
-
/** Solve every frame (default). Set false to drive `solve()` yourself. */
|
|
24
|
-
enabled: boolean;
|
|
25
|
-
update(): void;
|
|
26
|
-
/** One solve at the current pose. Safe to call manually (e.g. from a later-ordered aspect). */
|
|
27
|
-
solve(): void;
|
|
28
|
-
}
|
|
29
|
-
/** Aim a bone at a target (head / eyes / turret). Attach to the bone itself:
|
|
30
|
-
* `head.aspect(IK.LookAt, { target: camera, limit: 70 })`. `axis` is the bone's LOCAL forward
|
|
31
|
-
* (the direction that should point at the target) — rigs differ; default −Z, Mixamo heads look
|
|
32
|
-
* along +Z of the head bone in most exports, so pass `axis: [0, 0, 1]` there if it faces backwards. */
|
|
33
|
-
declare class LookAt extends Aspect<"lookAt", Node> {
|
|
34
|
-
static readonly aspect = "lookAt";
|
|
35
|
-
target?: Target;
|
|
36
|
-
/** The bone's local axis that should point at the target. */
|
|
37
|
-
axis: Vec3Like;
|
|
38
|
-
/** Max deflection from the animated direction, in degrees (default 80). */
|
|
39
|
-
limit: number;
|
|
40
|
-
/** 0–1 contribution. */
|
|
41
|
-
weight: number;
|
|
42
|
-
enabled: boolean;
|
|
43
|
-
update(): void;
|
|
44
|
-
solve(): void;
|
|
45
|
-
}
|
|
46
|
-
/** Inverse kinematics aspects — attach to bones (see file header). */
|
|
47
|
-
export declare const IK: {
|
|
48
|
-
TwoBone: typeof TwoBone;
|
|
49
|
-
LookAt: typeof LookAt;
|
|
50
|
-
};
|
|
51
|
-
export type IKTwoBone = TwoBone;
|
|
52
|
-
export type IKLookAt = LookAt;
|
|
53
|
-
export {};
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { Aspect } from "../core/Aspect";
|
|
2
|
-
import type { FieldMeta } from "../core/fields";
|
|
3
|
-
import { type Vec3Like } from "../math/vec";
|
|
4
|
-
import { Node } from "./Node";
|
|
5
|
-
export interface RagdollHinge {
|
|
6
|
-
/** The hinge axis in the MODEL's space (its rest pose: +Z forward, +Y up, +X the model's left in
|
|
7
|
-
* glTF). Perpendicular to the bone; the engine drops any component along it. */
|
|
8
|
-
axis: Vec3Like;
|
|
9
|
-
/** The bend range about `axis` in degrees, relative to the pose the ragdoll was built in — a knee
|
|
10
|
-
* is `{ axis: [1, 0, 0], min: 0, max: 140 }`: it folds one way only. */
|
|
11
|
-
min: number;
|
|
12
|
-
max: number;
|
|
13
|
-
}
|
|
14
|
-
export interface RagdollPart {
|
|
15
|
-
/** The bone the body sits on — its origin is the joint. */
|
|
16
|
-
bone: string;
|
|
17
|
-
/** The bone the capsule points at (the next joint down). Omitted = a leaf: `length` along the line
|
|
18
|
-
* from the parent part's origin (a head, a hand, a foot without toes). */
|
|
19
|
-
to?: string;
|
|
20
|
-
/** The bone of the part this one hangs from (default: the previous part in the list). The root
|
|
21
|
-
* has none. */
|
|
22
|
-
parent?: string;
|
|
23
|
-
/** Capsule radius in metres (default 0.05). */
|
|
24
|
-
radius?: number;
|
|
25
|
-
/** Length in metres: a leaf's, or an override of the distance to `to`. */
|
|
26
|
-
length?: number;
|
|
27
|
-
/** This part's share of the ragdoll's `mass` (relative weight, default 1). */
|
|
28
|
-
mass?: number;
|
|
29
|
-
/** Cone half-angle in degrees the part may swing off its parent (default 30). Ignored with `hinge`. */
|
|
30
|
-
swing?: number;
|
|
31
|
-
/** Twist half-angle in degrees about its own axis (default 20). */
|
|
32
|
-
twist?: number;
|
|
33
|
-
/** A one-way joint instead of the cone. */
|
|
34
|
-
hinge?: RagdollHinge;
|
|
35
|
-
}
|
|
36
|
-
export declare class Ragdoll extends Aspect<"ragdoll", Node> {
|
|
37
|
-
static readonly aspect = "ragdoll";
|
|
38
|
-
/** The parts: `'humanoid'` (default) finds the standard bones by name; a list places bodies on any
|
|
39
|
-
* bones — parents before children. */
|
|
40
|
-
parts: RagdollPart[] | "humanoid";
|
|
41
|
-
/** Total mass in kg (default 70), split between the parts by their `mass` shares. */
|
|
42
|
-
mass: number;
|
|
43
|
-
/** Friction of every part (default 0.6 — the physics default). */
|
|
44
|
-
friction: number;
|
|
45
|
-
/** Linear / angular damping of every part; 0 = Jolt's own 0.05. More angular damping settles a
|
|
46
|
-
* flailing body sooner. */
|
|
47
|
-
linearDamping: number;
|
|
48
|
-
angularDamping: number;
|
|
49
|
-
/** What the parts collide with. `'static'` (default): the static geometry and other such ragdolls
|
|
50
|
-
* only — dynamic bodies, character controllers and vehicles pass through a fallen body, which then
|
|
51
|
-
* never shoves or blocks anything and costs nothing when they meet. `'all'`: a regular dynamic
|
|
52
|
-
* body that bumps into everything (and gets kicked awake by everything). */
|
|
53
|
-
collide: "static" | "all";
|
|
54
|
-
/** Once every part has come to rest the parts turn static where they lie (default true): the pose
|
|
55
|
-
* holds, nothing can wake a settled body and it costs the solver nothing — `deactivate()` /
|
|
56
|
-
* `activate()` still work (activate makes it dynamic again). */
|
|
57
|
-
freeze: boolean;
|
|
58
|
-
/** Seconds after `activate()` at which the body freezes whatever it is doing — a twitch on a slope
|
|
59
|
-
* or a pile never sleeps on its own. 0 (default) = no cap. */
|
|
60
|
-
freezeAfter: number;
|
|
61
|
-
static fields: FieldMeta<Ragdoll>;
|
|
62
|
-
private _id;
|
|
63
|
-
private _active;
|
|
64
|
-
private _bones;
|
|
65
|
-
onAttach(): void;
|
|
66
|
-
onDetach(): void;
|
|
67
|
-
/** Hand the bones to physics from the pose they are in right now. `velocity` (world m/s) is given
|
|
68
|
-
* to every part — pass the character's, so a running body keeps travelling. */
|
|
69
|
-
activate(opts?: {
|
|
70
|
-
velocity?: Vec3Like;
|
|
71
|
-
}): boolean;
|
|
72
|
-
/** Take the bones back: the animator's pose shows again from the next frame. */
|
|
73
|
-
deactivate(): void;
|
|
74
|
-
/** Physics owns the bones right now. */
|
|
75
|
-
get active(): boolean;
|
|
76
|
-
/** Active and every part asleep (or frozen) — the body has come to rest. */
|
|
77
|
-
get settled(): boolean;
|
|
78
|
-
/** The root part's bone (the hips): where the body is. */
|
|
79
|
-
get root(): Node | null;
|
|
80
|
-
/** The bones that carry a part, in order. */
|
|
81
|
-
get bones(): string[];
|
|
82
|
-
/** The rigid-body id of a part (0 if none) — for the plain body calls. */
|
|
83
|
-
bodyOf(bone: string): number;
|
|
84
|
-
/** Push one part: an impulse in N·s, at a world point (a hit) or through its centre. Wakes the body. */
|
|
85
|
-
impulse(bone: string, v: Vec3Like, at?: Vec3Like): boolean;
|
|
86
|
-
}
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { Aspect } from "../core/Aspect";
|
|
2
|
-
import type { FieldMeta } from "../core/fields";
|
|
3
|
-
import { Vec3, type Vec3Like } from "../math/vec";
|
|
4
|
-
import { type QuatLike } from "../math/quat";
|
|
5
|
-
import { Node } from "./Node";
|
|
6
|
-
import { Wheel } from "./Wheel";
|
|
7
|
-
/** Which axle the engine drives. A wheel's own `drive` overrides it. */
|
|
8
|
-
export type DriveLayout = "rear" | "front" | "all";
|
|
9
|
-
/**
|
|
10
|
-
* How an axle's two wheels share torque.
|
|
11
|
-
* - `lsd` — limited slip (Jolt's 1.4 ratio), the sane default.
|
|
12
|
-
* - `open` — fully open: a lifted or spinning wheel takes ALL the torque.
|
|
13
|
-
* - `locked` — both wheels forced to the same speed. Breaks traction predictably: the drift diff.
|
|
14
|
-
* A number is the raw max/min wheel-speed ratio (> 1; smaller is more locked).
|
|
15
|
-
*/
|
|
16
|
-
export type DifferentialMode = "lsd" | "open" | "locked";
|
|
17
|
-
export interface EngineConfig {
|
|
18
|
-
/** Peak torque in N·m (default 500). The single biggest "how fast is it" knob. */
|
|
19
|
-
torque?: number;
|
|
20
|
-
/** Redline in RPM (default 6000). */
|
|
21
|
-
maxRpm?: number;
|
|
22
|
-
/** Idle RPM (default 1000) — the engine never falls below it. */
|
|
23
|
-
idleRpm?: number;
|
|
24
|
-
/**
|
|
25
|
-
* The engine's CHARACTER: a flat list `[rpm, torque, rpm, torque, …]` in NORMALISED units — x is
|
|
26
|
-
* a fraction of the redline, y a fraction of `torque`. Left out, Jolt's own broad curve is used.
|
|
27
|
-
*
|
|
28
|
-
* `[0, 0.8, 0.66, 1, 1, 0.8]` is an ordinary petrol engine (peak two thirds up, falling to the
|
|
29
|
-
* redline); `[0, 1, 1, 1]` is flat, which is what an electric motor feels like.
|
|
30
|
-
*/
|
|
31
|
-
curve?: number[];
|
|
32
|
-
/** Moment of inertia in kg·m² (default 0.5) — how eagerly it revs when the clutch is out. */
|
|
33
|
-
inertia?: number;
|
|
34
|
-
/** Engine braking: angular damping of the engine itself (default 0.2). */
|
|
35
|
-
braking?: number;
|
|
36
|
-
}
|
|
37
|
-
export interface SteeringConfig {
|
|
38
|
-
/** Steering lock in degrees at a standstill (default 35). */
|
|
39
|
-
lock?: number;
|
|
40
|
-
/**
|
|
41
|
-
* The lock still available, in degrees, once the car reaches `speed` (default 10) — what stops a
|
|
42
|
-
* car over-driving its own front tires.
|
|
43
|
-
*
|
|
44
|
-
* A tire makes its peak grip at a few degrees of slip angle, and the steering angle a corner needs
|
|
45
|
-
* falls with the SQUARE of speed. Holding full lock at 100 km/h therefore asks the front for
|
|
46
|
-
* several times what it can give: the tires saturate, the car ploughs on, and the wheel stops
|
|
47
|
-
* answering. In between the lock eases on `(1 − v/speed)²`, which tracks the real curve closely.
|
|
48
|
-
* `0` turns the taper off — full lock at any speed.
|
|
49
|
-
*/
|
|
50
|
-
atSpeed?: number;
|
|
51
|
-
/** The speed in m/s at which the lock has fallen to `atSpeed` (default 30 ≈ 108 km/h). */
|
|
52
|
-
speed?: number;
|
|
53
|
-
/** How fast the front wheels may turn, in degrees per second (default 220). A keyboard asks for
|
|
54
|
-
* full lock in one frame, which no steering wheel can do, and that step alone snaps a tire past
|
|
55
|
-
* its peak. `0` = instantly. */
|
|
56
|
-
rate?: number;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Aerodynamics. Both numbers are quoted the same way — **a fraction of the car's own weight at
|
|
60
|
-
* 30 m/s (108 km/h)** — and both grow with the SQUARE of speed from there, so `0.5` at 30 m/s is
|
|
61
|
-
* `2.0` at 60 m/s. One mental model for both, and no drag coefficients or frontal areas to invent.
|
|
62
|
-
*/
|
|
63
|
-
export interface AeroConfig {
|
|
64
|
-
/**
|
|
65
|
-
* Downforce (default 0 — a car with no wing). The knob that decides whether a car corners better
|
|
66
|
-
* or worse the faster it goes: tire grip is a constant, but the force a corner demands grows with
|
|
67
|
-
* v², so with no downforce every car runs out of road at speed. `0.6` roughly doubles a car's
|
|
68
|
-
* cornering at 150 km/h; a road car is nearer `0.1`, a race car well past `1`.
|
|
69
|
-
*
|
|
70
|
-
* It presses along the CHASSIS' own down axis (that is what keeps a car planted over a crest) and
|
|
71
|
-
* only while a wheel is on the ground — a car on its roof is never launched by its own wing.
|
|
72
|
-
*/
|
|
73
|
-
downforce?: number;
|
|
74
|
-
/** Air resistance (default 0.03 — an ordinary car). What gives a car a top speed at all. */
|
|
75
|
-
drag?: number;
|
|
76
|
-
}
|
|
77
|
-
export declare class Vehicle extends Aspect<"vehicle", Node> {
|
|
78
|
-
static readonly aspect = "vehicle";
|
|
79
|
-
/** Chassis mass in kg (default 1200). Wheels are massless in this model. */
|
|
80
|
-
mass: number;
|
|
81
|
-
/** Centre of mass height in chassis space (metres, negative = lower). Left out, it drops to halfway
|
|
82
|
-
* down the chassis shape — a car with its mass at the shape's centre tips over. */
|
|
83
|
-
centerOfMass?: number;
|
|
84
|
-
/** Which axle the engine drives (default "rear"). A wheel's own `drive` overrides it. */
|
|
85
|
-
driveAxle: DriveLayout;
|
|
86
|
-
/** Differential lock across each driven axle. `locked` is the drift setup — both wheels turn
|
|
87
|
-
* together, so the pair lets go as a pair. Live: re-configure the aspect to switch it mid-drive. */
|
|
88
|
-
differential: DifferentialMode | number;
|
|
89
|
-
/**
|
|
90
|
-
* Anti-roll bars between each axle's wheels — what stops a car rolling onto its inside wheels in a
|
|
91
|
-
* fast corner. `true` (default) is a bar 0.01 as stiff as the wheel's own spring; a number is that
|
|
92
|
-
* ratio directly, and `0` / `false` removes the bars.
|
|
93
|
-
*
|
|
94
|
-
* **The numbers are far smaller than they look and the gain is steep** — Jolt's bar feeds
|
|
95
|
-
* `lengthDifference × stiffness × dt` as a bias into the suspension's own soft constraint, so 4%
|
|
96
|
-
* of the spring already flattens the body. Measured on a 1250 kg car: `0` → 1.3° of roll at 0.86 g,
|
|
97
|
-
* `0.01` → 0.6°, `0.15` → 0.2° (flat), `0.5` → the car HOPS.
|
|
98
|
-
*
|
|
99
|
-
* This is the knob for how much a car visibly LEANS, not for wheel lift: bars change how far the
|
|
100
|
-
* body tips, not how much load transfers. For lift, lower `centerOfMass`.
|
|
101
|
-
*/
|
|
102
|
-
antiRoll: boolean | number;
|
|
103
|
-
/** Pitch/roll limit in degrees (default 60) before the constraint rights the car. 180 turns it off. */
|
|
104
|
-
maxTilt: number;
|
|
105
|
-
/** Friction of the CHASSIS body itself — how it slides when it lands on its roof or side. Nothing
|
|
106
|
-
* to do with the tires; those are the `Wheel`'s `tire.grip` × the ground's friction. */
|
|
107
|
-
friction: number;
|
|
108
|
-
/** Strength of the clutch when fully engaged (default 10). Small values slip; large ones weld the
|
|
109
|
-
* engine to the wheels. The `Gearbox` scales it 0..1 while shifting. */
|
|
110
|
-
clutchStrength: number;
|
|
111
|
-
engine: EngineConfig;
|
|
112
|
-
steering: SteeringConfig;
|
|
113
|
-
aero: AeroConfig;
|
|
114
|
-
/** Scene-editor inspector: the flat, tunable half. The grouped objects are edited in code. */
|
|
115
|
-
static fields: FieldMeta<Vehicle>;
|
|
116
|
-
static editor: {
|
|
117
|
-
rebuild: boolean;
|
|
118
|
-
};
|
|
119
|
-
private _id;
|
|
120
|
-
private _bodyId;
|
|
121
|
-
private _builtMass;
|
|
122
|
-
private _wheels;
|
|
123
|
-
private _state;
|
|
124
|
-
private _stateFrame;
|
|
125
|
-
private _throttle;
|
|
126
|
-
private _steer;
|
|
127
|
-
private _brake;
|
|
128
|
-
private _handbrake;
|
|
129
|
-
onAttach(): void;
|
|
130
|
-
onDetach(): void;
|
|
131
|
-
/**
|
|
132
|
-
* Re-configuring an attached vehicle retunes it in place — the way a drift button switches the
|
|
133
|
-
* differential without the car so much as blinking:
|
|
134
|
-
*
|
|
135
|
-
* car.aspect(Vehicle, { differential: drift ? 'locked' : 'lsd' })
|
|
136
|
-
*
|
|
137
|
-
* Live: `differential`, `engine`, `steering`, `aero`, `maxTilt`, `friction`, `clutchStrength`, and
|
|
138
|
-
* every `Wheel`'s `tire.grip` and brake torques. Everything else describes the car's STRUCTURE —
|
|
139
|
-
* `mass`, `centerOfMass`, which wheels exist and where, their suspension, `driveAxle`, `antiRoll` — and
|
|
140
|
-
* is baked into the constraint at attach; to change one of those, re-attach the aspect.
|
|
141
|
-
*/
|
|
142
|
-
onReconfigure(): void;
|
|
143
|
-
/** Native vehicle id (0 until attached / no physics support). */
|
|
144
|
-
get id(): number;
|
|
145
|
-
/** The chassis rigid-body id — the same handle the plain body calls take. */
|
|
146
|
-
get bodyId(): number;
|
|
147
|
-
/** The wheels, in blob order (front axle first). */
|
|
148
|
-
get wheels(): readonly Wheel[];
|
|
149
|
-
/**
|
|
150
|
-
* The driver's controls, all in [-1, 1] (brakes in [0, 1]). Sticky: the last values keep applying
|
|
151
|
-
* until the next call, so a held key does not need re-sending. `forward < 0` asks for reverse; the
|
|
152
|
-
* `Gearbox` engages it once the car has stopped.
|
|
153
|
-
*/
|
|
154
|
-
drive(forward: number, steer?: number, brake?: number, handbrake?: number): this;
|
|
155
|
-
/** Teleport upright and clear all motion (velocity, engine, gearbox, wheel spin). Defaults to the
|
|
156
|
-
* chassis node's current pose — `reset()` alone un-flips a car where it lies. */
|
|
157
|
-
reset(position?: Vec3Like, rotation?: QuatLike): this;
|
|
158
|
-
/** Push the chassis (a boost pad, an explosion) — an instantaneous impulse in kg·m/s. */
|
|
159
|
-
applyImpulse(v: Vec3Like): this;
|
|
160
|
-
private _read;
|
|
161
|
-
/** Speed along the car's forward axis in m/s — negative when reversing (× 3.6 for km/h). */
|
|
162
|
-
get speed(): number;
|
|
163
|
-
/** Engine revolutions per minute. */
|
|
164
|
-
get rpm(): number;
|
|
165
|
-
/** How many wheels are touching the ground. */
|
|
166
|
-
get wheelsOnGround(): number;
|
|
167
|
-
/** Any wheel on the ground — false while airborne. */
|
|
168
|
-
get grounded(): boolean;
|
|
169
|
-
/** Chassis velocity in world units/s (fresh Vec3). */
|
|
170
|
-
get velocity(): Vec3;
|
|
171
|
-
/** The last throttle handed to `drive()` — what the gearbox reads to know which way you want to go. */
|
|
172
|
-
get throttle(): number;
|
|
173
|
-
/** The last steer input handed to `drive()`, [-1, 1]. */
|
|
174
|
-
get steerInput(): number;
|
|
175
|
-
/** The last foot-brake input handed to `drive()`, [0, 1] — the pedal, not the resulting force. */
|
|
176
|
-
get brake(): number;
|
|
177
|
-
/** The last handbrake input handed to `drive()`, [0, 1]. */
|
|
178
|
-
get handbrake(): number;
|
|
179
|
-
/** Current gear from the attached `Gearbox`: −1 reverse, 0 neutral, 1… forward. */
|
|
180
|
-
get gear(): number;
|
|
181
|
-
/** The steering lock, in degrees, the car is allowed at its current speed — the full lock at rest,
|
|
182
|
-
* falling to `steering.atSpeed`. The same curve the engine applies; useful on a HUD. */
|
|
183
|
-
get steerLock(): number;
|
|
184
|
-
/** Every Wheel under the chassis, ordered front axle first, with its axle group resolved. */
|
|
185
|
-
private _collectWheels;
|
|
186
|
-
/** Pack the whole configuration into the one blob the host ABI takes (see bridges.d.ts). */
|
|
187
|
-
private _buildSettings;
|
|
188
|
-
/** Edit mode: which way the chassis faces. Each wheel draws its own circle and travel range — see
|
|
189
|
-
* `Wheel.rebuild()`. Play mode never calls this. */
|
|
190
|
-
rebuild(): void;
|
|
191
|
-
}
|
package/dist/types/gl/Wheel.d.ts
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { Aspect } from "../core/Aspect";
|
|
2
|
-
import type { FieldMeta } from "../core/fields";
|
|
3
|
-
import { type Vec3Like } from "../math/vec";
|
|
4
|
-
import { Node } from "./Node";
|
|
5
|
-
/** Floats `vehicleGetState` writes before the per-wheel block: speed, rpm, contacts, vx, vy, vz. */
|
|
6
|
-
export declare const STATE_HEADER = 6;
|
|
7
|
-
/** Floats per wheel: contact, slip, slipAngle, suspensionLength, steerDeg, spin. */
|
|
8
|
-
export declare const WHEEL_STATE = 6;
|
|
9
|
-
/** How a tire behaves past its grip peak. `road` is Jolt's own curve — grip falls off after the peak,
|
|
10
|
-
* so the car can be made to let go. `arcade` holds the peak all the way out: much harder to spin. */
|
|
11
|
-
export type TireCurve = "road" | "arcade";
|
|
12
|
-
export interface WheelSuspension {
|
|
13
|
-
/** Total travel in metres, full droop to fully compressed (default 0.4). */
|
|
14
|
-
travel?: number;
|
|
15
|
-
/** Spring frequency in Hz — bigger is stiffer (default 1.4; a race car ~2.5, a truck ~1). It also
|
|
16
|
-
* sets the ride-height sag, and the sag is how far the wheel can still extend DOWN. */
|
|
17
|
-
stiffness?: number;
|
|
18
|
-
/** Damping ratio 0..1 (default 0.5). Low values pogo. */
|
|
19
|
-
damping?: number;
|
|
20
|
-
}
|
|
21
|
-
export interface WheelTire {
|
|
22
|
-
/** Grip multiplier on the friction curves (default 1). The grip a wheel actually gets is combined
|
|
23
|
-
* with the ground it stands on as `sqrt(tire × groundFriction)`, and a body's friction defaults to
|
|
24
|
-
* 0.6 — so a road a car should really corner on wants `Physics { friction: 1 }`. */
|
|
25
|
-
grip?: number;
|
|
26
|
-
/** Which friction curve (default `road`). */
|
|
27
|
-
curve?: TireCurve;
|
|
28
|
-
}
|
|
29
|
-
export interface WheelVisual {
|
|
30
|
-
/** The MODEL's axle direction in its own space (default `[1, 0, 0]`). Set it instead of parenting
|
|
31
|
-
* the mesh under a corrective node when the art points another way. */
|
|
32
|
-
axis?: Vec3Like;
|
|
33
|
-
/** Drawn radius, if the art is not exactly the physical `radius` — sinks a wheel into its arch or
|
|
34
|
-
* lets a fat tire overhang, with no effect on the simulation. Default: the physical radius. */
|
|
35
|
-
radius?: number;
|
|
36
|
-
/** Let the model spin (default true). `false` keeps the steer angle and suspension travel but not
|
|
37
|
-
* the rotation — a brake caliper. */
|
|
38
|
-
spin?: boolean;
|
|
39
|
-
}
|
|
40
|
-
export declare class Wheel extends Aspect<"wheel", Node> {
|
|
41
|
-
static readonly aspect = "wheel";
|
|
42
|
-
/** Wheel radius in metres. Default: measured from the node's rendered bounds, else 0.35. Too small
|
|
43
|
-
* and the car scrapes, too large and it floats. */
|
|
44
|
-
radius?: number;
|
|
45
|
-
/** Wheel width in metres. Default: measured, else 0.25. */
|
|
46
|
-
width?: number;
|
|
47
|
-
/** Does this wheel steer? Default: the wheels on the front axle. */
|
|
48
|
-
steer?: boolean;
|
|
49
|
-
/** Does the engine drive it? Default: from the vehicle's `drive` layout. */
|
|
50
|
-
drive?: boolean;
|
|
51
|
-
/** Foot brake on this wheel. */
|
|
52
|
-
brake: boolean;
|
|
53
|
-
/** Handbrake on this wheel. Default: every non-steering wheel (locking the front wheels of a moving
|
|
54
|
-
* car is not a handbrake turn, it is a crash). */
|
|
55
|
-
handbrake?: boolean;
|
|
56
|
-
/** Axle group, front to back. Default: derived from Z. Set it for a car whose wheels are not in neat
|
|
57
|
-
* left/right pairs — an axle's wheels are paired for the differential and the anti-roll bar. */
|
|
58
|
-
axle?: number;
|
|
59
|
-
/** Foot-brake torque in N·m (default 1500); the handbrake pulls 3× on the wheels that have it. */
|
|
60
|
-
brakeTorque: number;
|
|
61
|
-
suspension: WheelSuspension;
|
|
62
|
-
tire: WheelTire;
|
|
63
|
-
visual: WheelVisual;
|
|
64
|
-
/** Scene-editor inspector. `steer` / `drive` / `handbrake` are deliberately absent: they are
|
|
65
|
-
* tri-state (undefined = derive it from the axle), which a switch cannot express. */
|
|
66
|
-
static fields: FieldMeta<Wheel>;
|
|
67
|
-
static editor: {
|
|
68
|
-
rebuild: boolean;
|
|
69
|
-
};
|
|
70
|
-
private _angle;
|
|
71
|
-
private _scale;
|
|
72
|
-
private _local;
|
|
73
|
-
onAttach(): void;
|
|
74
|
-
onDetach(): void;
|
|
75
|
-
private _state;
|
|
76
|
-
/** Touching the ground this step. */
|
|
77
|
-
get contact(): boolean;
|
|
78
|
-
/** Longitudinal slip RATIO: 0 = rolling in sync with the ground, ~1 = spinning up or locked.
|
|
79
|
-
* Unsigned — smoke, tire marks and wheelspin sound key off this. */
|
|
80
|
-
get slip(): number;
|
|
81
|
-
/** Slip ANGLE in degrees: how far the tire's travel direction is off from where it points.
|
|
82
|
-
* Unsigned, 0..90 — past the curve's peak (~3°) the tire is sliding sideways. Drift particles. */
|
|
83
|
-
get slipAngle(): number;
|
|
84
|
-
/** Steer angle in degrees, positive to the right. */
|
|
85
|
-
get steerAngle(): number;
|
|
86
|
-
/** Wheel spin in rad/s (× radius ≈ the speed the tire is laying down). */
|
|
87
|
-
get spin(): number;
|
|
88
|
-
/** Suspension compression, 0 = fully extended (drooping) … 1 = fully compressed. */
|
|
89
|
-
get compression(): number;
|
|
90
|
-
/** LATE phase: after the step and the transform sync, right before the frame draws. */
|
|
91
|
-
update(dt: number): void;
|
|
92
|
-
/** Edit mode: this wheel's own circle at its resting height, its travel range, and a mark when the
|
|
93
|
-
* engine drives it — enough to place a wheel without running the game. */
|
|
94
|
-
rebuild(): void;
|
|
95
|
-
}
|
package/src/animate/animate.ts
DELETED
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
// animate self-implements its matrix decompose/recompose; these are just the numeric-array shapes.
|
|
2
|
-
type mat4 = Float32Array | number[]
|
|
3
|
-
type quat = Float32Array | number[]
|
|
4
|
-
type vec2 = Float32Array | number[]
|
|
5
|
-
type vec3 = Float32Array | number[]
|
|
6
|
-
import type { Easing } from "./easings"
|
|
7
|
-
|
|
8
|
-
type AnimateProps = number | string | vec2 | vec3 | quat
|
|
9
|
-
|
|
10
|
-
export type AnimateOptions<T> = {
|
|
11
|
-
from: T,
|
|
12
|
-
to: T,
|
|
13
|
-
duration: number,
|
|
14
|
-
onUpdate(val: T): void,
|
|
15
|
-
onComplete?(): void,
|
|
16
|
-
easing?: Easing,
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export const animate = <T extends AnimateProps>(options: AnimateOptions<T>): number => {
|
|
20
|
-
|
|
21
|
-
let onRawUpdate
|
|
22
|
-
if (typeof options.to === "number") {
|
|
23
|
-
const { onUpdate, from, to } = options as AnimateOptions<number>
|
|
24
|
-
onRawUpdate = (t: number) => onUpdate(from + (to - from) * t)
|
|
25
|
-
} else if (options.to === "string") {
|
|
26
|
-
// TODO: Make color animate here
|
|
27
|
-
const { onUpdate, from, to } = options as AnimateOptions<string>
|
|
28
|
-
onRawUpdate = (t: number) => onUpdate(from)
|
|
29
|
-
|
|
30
|
-
// onRawUpdate = (val: number) => onUpdate(from + (to - from) * val)
|
|
31
|
-
} else if (options.to.length === 2) {
|
|
32
|
-
const { onUpdate, from, to } = options as AnimateOptions<vec2>
|
|
33
|
-
const tempVec = new Float32Array(3)
|
|
34
|
-
onRawUpdate = (t: number) => onUpdate(lerp2(tempVec, from, to, t))
|
|
35
|
-
|
|
36
|
-
} else if (options.to.length === 3) {
|
|
37
|
-
const { onUpdate, from, to } = options as AnimateOptions<vec3>
|
|
38
|
-
const tempVec = new Float32Array(3)
|
|
39
|
-
|
|
40
|
-
onRawUpdate = (t: number) => onUpdate(lerp(tempVec, from, to, t))
|
|
41
|
-
} else if (options.to.length === 4) {
|
|
42
|
-
const { onUpdate, from, to } = options as AnimateOptions<quat>
|
|
43
|
-
|
|
44
|
-
const tempQuat = new Float32Array(4)
|
|
45
|
-
onRawUpdate = (t: number) => onUpdate(slerp(tempQuat, from, to, t))
|
|
46
|
-
} else {
|
|
47
|
-
onRawUpdate = () => {}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const animationId = _creatorUtils.animate(val => {
|
|
51
|
-
const _val = options.easing? options.easing(val): val
|
|
52
|
-
onRawUpdate(_val)
|
|
53
|
-
if (val === 1 && options.onComplete) {
|
|
54
|
-
options.onComplete()
|
|
55
|
-
}
|
|
56
|
-
}, options.duration)
|
|
57
|
-
|
|
58
|
-
return animationId
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export const stopAnimation = (id: number): void => _creatorUtils.stopAnimation(id)
|
|
62
|
-
export const pauseAnimation = (id: number): void => _creatorUtils.pauseAnimation(id)
|
|
63
|
-
export const resumeAnimation = (id: number): void => _creatorUtils.resumeAnimation(id)
|
|
64
|
-
|
|
65
|
-
export const animateMat4 = (options: AnimateOptions<mat4>): number => {
|
|
66
|
-
const fromPosition = new Float32Array(3)
|
|
67
|
-
const fromQuaternion = new Float32Array(4)
|
|
68
|
-
const fromScale = new Float32Array(3)
|
|
69
|
-
const toPosition = new Float32Array(3)
|
|
70
|
-
const toQuaternion = new Float32Array(4)
|
|
71
|
-
const toScale = new Float32Array(3)
|
|
72
|
-
decompose(fromQuaternion, fromPosition, fromScale, (options as AnimateOptions<mat4>).from)
|
|
73
|
-
decompose(toQuaternion, toPosition, toScale, (options as AnimateOptions<mat4>).to)
|
|
74
|
-
|
|
75
|
-
const tempPosition = new Float32Array(3)
|
|
76
|
-
const tempQuat = new Float32Array(4)
|
|
77
|
-
const tempScale = new Float32Array(3)
|
|
78
|
-
const tempMat = new Float32Array(16)
|
|
79
|
-
|
|
80
|
-
const onUpdate = (options as AnimateOptions<mat4>).onUpdate
|
|
81
|
-
const onRawUpdate = (t: number) => {
|
|
82
|
-
lerp(tempPosition, fromPosition, toPosition, t)
|
|
83
|
-
slerp(tempQuat, fromQuaternion, toQuaternion, t)
|
|
84
|
-
lerp(tempScale, fromScale, toScale, t)
|
|
85
|
-
|
|
86
|
-
onUpdate(fromRotationTranslationScale(tempMat, tempQuat, tempPosition, tempScale))
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const animationId = _creatorUtils.animate(val => {
|
|
90
|
-
const _val = options.easing? options.easing(val): val
|
|
91
|
-
onRawUpdate(_val)
|
|
92
|
-
if (val === 1 && options.onComplete) {
|
|
93
|
-
options.onComplete()
|
|
94
|
-
}
|
|
95
|
-
}, options.duration)
|
|
96
|
-
|
|
97
|
-
return animationId
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const EPSILON = 1e-6;
|
|
101
|
-
function slerp(out: quat, a: quat, b: quat, t: number) {
|
|
102
|
-
const ax = a[0], ay = a[1], az = a[2], aw = a[3];
|
|
103
|
-
let bx = b[0], by = b[1], bz = b[2], bw = b[3];
|
|
104
|
-
let omega, cosom, sinom, scale0, scale1;
|
|
105
|
-
cosom = ax * bx + ay * by + az * bz + aw * bw;
|
|
106
|
-
if (cosom < 0) {
|
|
107
|
-
cosom = -cosom;
|
|
108
|
-
bx = -bx;
|
|
109
|
-
by = -by;
|
|
110
|
-
bz = -bz;
|
|
111
|
-
bw = -bw;
|
|
112
|
-
}
|
|
113
|
-
if (1 - cosom > EPSILON) {
|
|
114
|
-
omega = Math.acos(cosom);
|
|
115
|
-
sinom = Math.sin(omega);
|
|
116
|
-
scale0 = Math.sin((1 - t) * omega) / sinom;
|
|
117
|
-
scale1 = Math.sin(t * omega) / sinom;
|
|
118
|
-
} else {
|
|
119
|
-
scale0 = 1 - t;
|
|
120
|
-
scale1 = t;
|
|
121
|
-
}
|
|
122
|
-
out[0] = scale0 * ax + scale1 * bx;
|
|
123
|
-
out[1] = scale0 * ay + scale1 * by;
|
|
124
|
-
out[2] = scale0 * az + scale1 * bz;
|
|
125
|
-
out[3] = scale0 * aw + scale1 * bw;
|
|
126
|
-
return out;
|
|
127
|
-
}
|
|
128
|
-
function lerp(out: vec3, a: vec3, b: vec3, t: number) {
|
|
129
|
-
const ax = a[0];
|
|
130
|
-
const ay = a[1];
|
|
131
|
-
const az = a[2];
|
|
132
|
-
out[0] = ax + t * (b[0] - ax);
|
|
133
|
-
out[1] = ay + t * (b[1] - ay);
|
|
134
|
-
out[2] = az + t * (b[2] - az);
|
|
135
|
-
return out;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function lerp2(out: vec2, a: vec2, b: vec2, t: number) {
|
|
139
|
-
const ax = a[0];
|
|
140
|
-
const ay = a[1];
|
|
141
|
-
const az = a[2];
|
|
142
|
-
out[0] = ax + t * (b[0] - ax);
|
|
143
|
-
out[1] = ay + t * (b[1] - ay);
|
|
144
|
-
return out;
|
|
145
|
-
}
|
|
146
|
-
function fromRotationTranslationScale(out: mat4, q: quat, v: vec3, s: vec3) {
|
|
147
|
-
const x = q[0], y = q[1], z = q[2], w = q[3];
|
|
148
|
-
const x2 = x + x;
|
|
149
|
-
const y2 = y + y;
|
|
150
|
-
const z2 = z + z;
|
|
151
|
-
const xx = x * x2;
|
|
152
|
-
const xy = x * y2;
|
|
153
|
-
const xz = x * z2;
|
|
154
|
-
const yy = y * y2;
|
|
155
|
-
const yz = y * z2;
|
|
156
|
-
const zz = z * z2;
|
|
157
|
-
const wx = w * x2;
|
|
158
|
-
const wy = w * y2;
|
|
159
|
-
const wz = w * z2;
|
|
160
|
-
const sx = s[0];
|
|
161
|
-
const sy = s[1];
|
|
162
|
-
const sz = s[2];
|
|
163
|
-
out[0] = (1 - (yy + zz)) * sx;
|
|
164
|
-
out[1] = (xy + wz) * sx;
|
|
165
|
-
out[2] = (xz - wy) * sx;
|
|
166
|
-
out[3] = 0;
|
|
167
|
-
out[4] = (xy - wz) * sy;
|
|
168
|
-
out[5] = (1 - (xx + zz)) * sy;
|
|
169
|
-
out[6] = (yz + wx) * sy;
|
|
170
|
-
out[7] = 0;
|
|
171
|
-
out[8] = (xz + wy) * sz;
|
|
172
|
-
out[9] = (yz - wx) * sz;
|
|
173
|
-
out[10] = (1 - (xx + yy)) * sz;
|
|
174
|
-
out[11] = 0;
|
|
175
|
-
out[12] = v[0];
|
|
176
|
-
out[13] = v[1];
|
|
177
|
-
out[14] = v[2];
|
|
178
|
-
out[15] = 1;
|
|
179
|
-
return out;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function decompose(out_r: mat4, out_t: vec3, out_s: vec3, mat: mat4) {
|
|
183
|
-
out_t[0] = mat[12];
|
|
184
|
-
out_t[1] = mat[13];
|
|
185
|
-
out_t[2] = mat[14];
|
|
186
|
-
const m11 = mat[0];
|
|
187
|
-
const m12 = mat[1];
|
|
188
|
-
const m13 = mat[2];
|
|
189
|
-
const m21 = mat[4];
|
|
190
|
-
const m22 = mat[5];
|
|
191
|
-
const m23 = mat[6];
|
|
192
|
-
const m31 = mat[8];
|
|
193
|
-
const m32 = mat[9];
|
|
194
|
-
const m33 = mat[10];
|
|
195
|
-
out_s[0] = Math.hypot(m11, m12, m13);
|
|
196
|
-
out_s[1] = Math.hypot(m21, m22, m23);
|
|
197
|
-
out_s[2] = Math.hypot(m31, m32, m33);
|
|
198
|
-
const is1 = 1 / out_s[0];
|
|
199
|
-
const is2 = 1 / out_s[1];
|
|
200
|
-
const is3 = 1 / out_s[2];
|
|
201
|
-
const sm11 = m11 * is1;
|
|
202
|
-
const sm12 = m12 * is2;
|
|
203
|
-
const sm13 = m13 * is3;
|
|
204
|
-
const sm21 = m21 * is1;
|
|
205
|
-
const sm22 = m22 * is2;
|
|
206
|
-
const sm23 = m23 * is3;
|
|
207
|
-
const sm31 = m31 * is1;
|
|
208
|
-
const sm32 = m32 * is2;
|
|
209
|
-
const sm33 = m33 * is3;
|
|
210
|
-
const trace = sm11 + sm22 + sm33;
|
|
211
|
-
let S = 0;
|
|
212
|
-
if (trace > 0) {
|
|
213
|
-
S = Math.sqrt(trace + 1) * 2;
|
|
214
|
-
out_r[3] = 0.25 * S;
|
|
215
|
-
out_r[0] = (sm23 - sm32) / S;
|
|
216
|
-
out_r[1] = (sm31 - sm13) / S;
|
|
217
|
-
out_r[2] = (sm12 - sm21) / S;
|
|
218
|
-
} else if (sm11 > sm22 && sm11 > sm33) {
|
|
219
|
-
S = Math.sqrt(1 + sm11 - sm22 - sm33) * 2;
|
|
220
|
-
out_r[3] = (sm23 - sm32) / S;
|
|
221
|
-
out_r[0] = 0.25 * S;
|
|
222
|
-
out_r[1] = (sm12 + sm21) / S;
|
|
223
|
-
out_r[2] = (sm31 + sm13) / S;
|
|
224
|
-
} else if (sm22 > sm33) {
|
|
225
|
-
S = Math.sqrt(1 + sm22 - sm11 - sm33) * 2;
|
|
226
|
-
out_r[3] = (sm31 - sm13) / S;
|
|
227
|
-
out_r[0] = (sm12 + sm21) / S;
|
|
228
|
-
out_r[1] = 0.25 * S;
|
|
229
|
-
out_r[2] = (sm23 + sm32) / S;
|
|
230
|
-
} else {
|
|
231
|
-
S = Math.sqrt(1 + sm33 - sm11 - sm22) * 2;
|
|
232
|
-
out_r[3] = (sm12 - sm21) / S;
|
|
233
|
-
out_r[0] = (sm31 + sm13) / S;
|
|
234
|
-
out_r[1] = (sm23 + sm32) / S;
|
|
235
|
-
out_r[2] = 0.25 * S;
|
|
236
|
-
}
|
|
237
|
-
return out_r;
|
|
238
|
-
}
|