220 lines
5.8 KiB
TypeScript
220 lines
5.8 KiB
TypeScript
|
|
type transform_t = {
|
|
world?: mat4_t;
|
|
local_only?: bool;
|
|
local?: mat4_t;
|
|
loc?: vec4_t;
|
|
rot?: quat_t;
|
|
scale?: vec4_t;
|
|
scale_world?: f32;
|
|
world_unpack?: mat4_t;
|
|
dirty?: bool;
|
|
object?: object_t;
|
|
dim?: vec4_t;
|
|
radius?: f32;
|
|
/// if arm_anim
|
|
// Wrong order returned from get_euler(), store last state for animation
|
|
_euler_x?: f32;
|
|
_euler_y?: f32;
|
|
_euler_z?: f32;
|
|
// Animated delta transform
|
|
dloc?: vec4_t;
|
|
drot?: quat_t;
|
|
dscale?: vec4_t;
|
|
_deuler_x?: f32;
|
|
_deuler_y?: f32;
|
|
_deuler_z?: f32;
|
|
/// end
|
|
};
|
|
|
|
function transform_create(object: object_t): transform_t {
|
|
let raw: transform_t = {};
|
|
raw.local_only = false;
|
|
raw.scale_world = 1.0;
|
|
raw.object = object;
|
|
transform_reset(raw);
|
|
return raw;
|
|
}
|
|
|
|
function transform_reset(raw: transform_t) {
|
|
raw.world = mat4_identity();
|
|
raw.world_unpack = mat4_identity();
|
|
raw.local = mat4_identity();
|
|
raw.loc = vec4_create();
|
|
raw.rot = quat_create();
|
|
raw.scale = vec4_create(1.0, 1.0, 1.0);
|
|
raw.dim = vec4_create(2.0, 2.0, 2.0);
|
|
raw.radius = 1.0;
|
|
raw.dirty = true;
|
|
}
|
|
|
|
function transform_update(raw: transform_t) {
|
|
if (raw.dirty) {
|
|
transform_build_matrix(raw);
|
|
}
|
|
}
|
|
|
|
/// if arm_anim
|
|
function transform_compose_delta(raw: transform_t) {
|
|
// Delta transform
|
|
raw.dloc = vec4_add(raw.loc, raw.dloc);
|
|
raw.dscale = vec4_add(raw.dscale, raw.scale);
|
|
raw.drot = quat_from_euler(raw._deuler_x, raw._deuler_y, raw._deuler_z);
|
|
raw.drot = quat_mult(raw.rot, raw.drot);
|
|
raw.local = mat4_compose(raw.dloc, raw.drot, raw.dscale);
|
|
}
|
|
/// end
|
|
|
|
function transform_build_matrix(raw: transform_t) {
|
|
// if (vec4_isnan(raw.dloc)) {
|
|
raw.local = mat4_compose(raw.loc, raw.rot, raw.scale);
|
|
// }
|
|
// else {
|
|
// transform_compose_delta(raw);
|
|
// }
|
|
|
|
if (raw.object.parent != null && !raw.local_only) {
|
|
raw.world = mat4_mult_mat3x4(raw.local, raw.object.parent.transform.world);
|
|
}
|
|
else {
|
|
raw.world = mat4_clone(raw.local);
|
|
}
|
|
|
|
raw.world_unpack = mat4_clone(raw.world);
|
|
if (raw.scale_world != 1.0) {
|
|
raw.world_unpack.m00 *= raw.scale_world;
|
|
raw.world_unpack.m01 *= raw.scale_world;
|
|
raw.world_unpack.m02 *= raw.scale_world;
|
|
raw.world_unpack.m03 *= raw.scale_world;
|
|
raw.world_unpack.m10 *= raw.scale_world;
|
|
raw.world_unpack.m11 *= raw.scale_world;
|
|
raw.world_unpack.m12 *= raw.scale_world;
|
|
raw.world_unpack.m13 *= raw.scale_world;
|
|
raw.world_unpack.m20 *= raw.scale_world;
|
|
raw.world_unpack.m21 *= raw.scale_world;
|
|
raw.world_unpack.m22 *= raw.scale_world;
|
|
raw.world_unpack.m23 *= raw.scale_world;
|
|
}
|
|
|
|
transform_compute_dim(raw);
|
|
|
|
// Update children
|
|
for (let i: i32 = 0; i < raw.object.children.length; ++i) {
|
|
let n: object_t = raw.object.children[i];
|
|
transform_build_matrix(n.transform);
|
|
}
|
|
|
|
raw.dirty = false;
|
|
}
|
|
|
|
function transform_translate(raw: transform_t, x: f32, y: f32, z: f32) {
|
|
raw.loc.x += x;
|
|
raw.loc.y += y;
|
|
raw.loc.z += z;
|
|
transform_build_matrix(raw);
|
|
}
|
|
|
|
function transform_set_matrix(raw: transform_t, mat: mat4_t) {
|
|
raw.local = mat4_clone(mat);
|
|
transform_decompose(raw);
|
|
transform_build_matrix(raw);
|
|
}
|
|
|
|
function transform_mult_matrix(raw: transform_t, mat: mat4_t) {
|
|
raw.local = mat4_mult_mat(raw.local, mat);
|
|
transform_decompose(raw);
|
|
transform_build_matrix(raw);
|
|
}
|
|
|
|
function transform_decompose(raw: transform_t) {
|
|
let dec: mat4_decomposed_t = mat4_decompose(raw.local);
|
|
raw.loc = dec.loc;
|
|
raw.rot = dec.rot;
|
|
raw.scale = dec.scl;
|
|
}
|
|
|
|
function transform_rotate(raw: transform_t, axis: vec4_t, f: f32) {
|
|
let q: quat_t = quat_from_axis_angle(axis, f);
|
|
raw.rot = quat_mult(q, raw.rot);
|
|
transform_build_matrix(raw);
|
|
}
|
|
|
|
function transform_move(raw: transform_t, axis: vec4_t, f: f32 = 1.0) {
|
|
raw.loc = vec4_fadd(raw.loc, axis.x * f, axis.y * f, axis.z * f);
|
|
transform_build_matrix(raw);
|
|
}
|
|
|
|
function transform_set_rot(raw: transform_t, x: f32, y: f32, z: f32) {
|
|
raw.rot = quat_from_euler(x, y, z);
|
|
/// if arm_anim
|
|
raw._euler_x = x;
|
|
raw._euler_y = y;
|
|
raw._euler_z = z;
|
|
/// end
|
|
raw.dirty = true;
|
|
}
|
|
|
|
function transform_compute_radius(raw: transform_t) {
|
|
raw.radius = math_sqrt(raw.dim.x * raw.dim.x + raw.dim.y * raw.dim.y + raw.dim.z * raw.dim.z);
|
|
}
|
|
|
|
function transform_compute_dim(raw: transform_t) {
|
|
if (raw.object.raw == null && raw.object.ext_type == "mesh_object_t") {
|
|
let mo: mesh_object_t = raw.object.ext;
|
|
let aabb: vec4_t = mesh_data_calculate_aabb(mo.data);
|
|
let o: object_t = raw.object;
|
|
o.raw = {};
|
|
o.raw.dimensions = f32_array_create_xyz(aabb.x, aabb.y, aabb.z);
|
|
}
|
|
|
|
if (raw.object.raw == null || raw.object.raw.dimensions == null) {
|
|
raw.dim = vec4_create(2 * raw.scale.x, 2 * raw.scale.y, 2 * raw.scale.z);
|
|
}
|
|
else {
|
|
let d: f32_array_t = raw.object.raw.dimensions;
|
|
raw.dim = vec4_create(d[0] * raw.scale.x, d[1] * raw.scale.y, d[2] * raw.scale.z);
|
|
}
|
|
transform_compute_radius(raw);
|
|
}
|
|
|
|
function transform_apply_parent_inv(raw: transform_t) {
|
|
let pt: transform_t = raw.object.parent.transform;
|
|
transform_build_matrix(pt);
|
|
let pinv: mat4_t = mat4_inv(pt.world);
|
|
raw.local = mat4_mult_mat(raw.local, pinv);
|
|
transform_decompose(raw);
|
|
transform_build_matrix(raw);
|
|
}
|
|
|
|
function transform_apply_parent(raw: transform_t) {
|
|
let pt: transform_t = raw.object.parent.transform;
|
|
transform_build_matrix(pt);
|
|
raw.local = mat4_mult_mat(raw.local, pt.world);
|
|
transform_decompose(raw);
|
|
transform_build_matrix(raw);
|
|
}
|
|
|
|
function transform_look(raw: transform_t): vec4_t {
|
|
return mat4_look(raw.world);
|
|
}
|
|
|
|
function transform_right(raw: transform_t): vec4_t {
|
|
return mat4_right(raw.world);
|
|
}
|
|
|
|
function transform_up(raw: transform_t): vec4_t {
|
|
return mat4_up(raw.world);
|
|
}
|
|
|
|
function transform_world_x(raw: transform_t): f32 {
|
|
return raw.world.m30;
|
|
}
|
|
|
|
function transform_world_y(raw: transform_t): f32 {
|
|
return raw.world.m31;
|
|
}
|
|
|
|
function transform_world_z(raw: transform_t): f32 {
|
|
return raw.world.m32;
|
|
}
|