import register from "../util/register.js";
import * as m_bounds from "../intern/boundings.js";
import m_obj_util_fact from "../intern/obj_util.js";
import m_phy_fact from "../intern/physics.js";
import m_print_fact from "../intern/print.js";
import * as m_quat from "../libs/gl_matrix/quat.js";
import m_trans_fact from "../intern/transform.js";
import * as m_tsr from "../intern/tsr.js";
import * as m_util from "../intern/util.js";
/**
* Object transformations API.
* With some exceptions specified below, make sure that the objects are dynamic.
* @module transform
*/
function Transform(ns, exports) {
var m_obj_util = m_obj_util_fact(ns);
var m_phy = m_phy_fact(ns);
var m_print = m_print_fact(ns);
var m_trans = m_trans_fact(ns);
var _tsr_tmp = m_tsr.create();
var _vec3_tmp = new Float32Array(3);
var _quat4_tmp = new Float32Array(4);
/**
* Set the object translation.
* @method module:transform.set_translation
* @param {Object3D} obj Object 3D
* @param {number} x X coord
* @param {number} y Y coord
* @param {number} z Z coord
*/
exports.set_translation = function(obj, x, y, z) {
if (m_obj_util.is_dynamic(obj)) {
_vec3_tmp[0] = x;
_vec3_tmp[1] = y;
_vec3_tmp[2] = z;
m_trans.set_translation(obj, _vec3_tmp);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Set the object translation (in the coordinate space of its parent).
* @method module:transform.set_translation_rel
* @param {Object3D} obj Object 3D
* @param {number} x X coord
* @param {number} y Y coord
* @param {number} z Z coord
*/
exports.set_translation_rel = function(obj, x, y, z) {
if (m_obj_util.is_dynamic(obj)) {
_vec3_tmp[0] = x;
_vec3_tmp[1] = y;
_vec3_tmp[2] = z;
m_trans.set_translation_rel(obj, _vec3_tmp);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Set the object translation (vector form).
* @method module:transform.set_translation_v
* @param {Object3D} obj Object 3D
* @param {Vec3} trans Translation vector
*/
exports.set_translation_v = function(obj, trans) {
if (m_obj_util.is_dynamic(obj)) {
m_trans.set_translation(obj, trans);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Set the object translation in vector form
* (in the coordinate space of its parent).
* @method module:transform.set_translation_rel_v
* @param {Object3D} obj Object 3D
* @param {Vec3} trans Translation vector
*/
exports.set_translation_rel_v = function(obj, trans) {
if (m_obj_util.is_dynamic(obj)) {
m_trans.set_translation_rel(obj, trans);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Set the object translation relatively to another object.
* @method module:transform.set_translation_obj_rel
* @param {Object3D} obj Transformed object
* @param {number} x X coord
* @param {number} y Y coord
* @param {number} z Z coord
* @param {Object3D} obj_ref Reference object
*/
exports.set_translation_obj_rel = function(obj, x, y, z, obj_ref) {
if (m_obj_util.is_dynamic(obj)) {
_vec3_tmp[0] = x;
_vec3_tmp[1] = y;
_vec3_tmp[2] = z;
var trans = m_tsr.get_trans_view(obj_ref.render.world_tsr);
var quat = m_tsr.get_quat_view(obj_ref.render.world_tsr);
m_util.transform_vec3(_vec3_tmp, 1, quat, trans, _vec3_tmp);
m_trans.set_translation(obj, _vec3_tmp);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Get the object's translation vector.
* @method module:transform.get_translation
* @param {Object3D} obj Object 3D
* @param {Vec3} [dest] Destination vector
* @returns {Vec3} Destination vector
* @example
* var m_scenes = require("scenes");
* var m_trans = require("transform");
* var m_vec3 = require("vec3");
* // precache 3D vector
* var _vec3_tmp = m_vec3.create();
* // ...
* var cube = m_scenes.get_object_by_name("Cube");
* var translation = m_trans.get_translation(cube, _vec3_tmp);
*/
exports.get_translation = function(obj, dest) {
if (!dest)
dest = new Float32Array(3);
m_trans.get_translation(obj, dest);
return dest;
}
/**
* Get the object's translation vector (in the coordinate space of its parent).
* @method module:transform.get_translation_rel
* @param {Object3D} obj Object 3D
* @param {Vec3} [dest] Destination vector
* @returns {Vec3} Destination vector
*/
exports.get_translation_rel = function(obj, dest) {
if (!dest)
dest = new Float32Array(3);
m_trans.get_translation_rel(obj, dest);
return dest;
}
/**
* Set the object's rotation quaternion.
* @method module:transform.set_rotation
* @param {Object3D} obj Object 3D
* @param {number} x X part of quaternion
* @param {number} y Y part of quaternion
* @param {number} z Z part of quaternion
* @param {number} w W part of quaternion
*/
exports.set_rotation = function(obj, x, y, z, w) {
if (m_obj_util.is_dynamic(obj)) {
_quat4_tmp[0] = x;
_quat4_tmp[1] = y;
_quat4_tmp[2] = z;
_quat4_tmp[3] = w;
m_trans.set_rotation(obj, _quat4_tmp);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Set the object's rotation quaternion (in the coordinate space of its parent).
* @method module:transform.set_rotation_rel
* @param {Object3D} obj Object 3D
* @param {number} x X part of quaternion
* @param {number} y Y part of quaternion
* @param {number} z Z part of quaternion
* @param {number} w W part of quaternion
*/
exports.set_rotation_rel = function(obj, x, y, z, w) {
if (m_obj_util.is_dynamic(obj)) {
_quat4_tmp[0] = x;
_quat4_tmp[1] = y;
_quat4_tmp[2] = z;
_quat4_tmp[3] = w;
m_trans.set_rotation_rel(obj, _quat4_tmp);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Set the object's rotation in vector form.
* @method module:transform.set_rotation_v
* @param {Object3D} obj Object 3D
* @param {Quat} quat Quaternion vector
*/
exports.set_rotation_v = function(obj, quat) {
if (m_obj_util.is_dynamic(obj)) {
m_trans.set_rotation(obj, quat);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Set the object's rotation in vector form
* (in the coordinate space of its parent).
* @method module:transform.set_rotation_rel_v
* @param {Object3D} obj Object 3D
* @param {Quat} quat Quaternion vector
*/
exports.set_rotation_rel_v = function(obj, quat) {
if (m_obj_util.is_dynamic(obj)) {
m_trans.set_rotation_rel(obj, quat);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Get the object's rotation in vector form
* (in the coordinate space of its parent).
* @method module:transform.set_rotation_rel_v
* @param {Object3D} obj Object 3D
* @param {Quat} quat Quaternion vector
* @returns {Quat} Destination vector
* @example
* var m_scenes = require("scenes");
* var m_trans = require("transform");
* var m_quat = require("quat");
* // precache quaternion
* var _quat_tmp = m_quat.create();
* // ...
* var cube = m_scenes.get_object_by_name("Cube");
* var rot_quat = m_trans.get_rotation_rel_v(cube, _quat_tmp);
*/
exports.get_rotation_rel_v = function(obj, quat) {
if (m_obj_util.is_dynamic(obj)) {
m_trans.get_rotation_rel(obj, quat);
return quat;
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Get the object's rotation quaternion.
* @method module:transform.get_rotation
* @param {Object3D} obj Object 3D
* @param {Quat} [opt_dest] Destination vector
* @returns {Quat} Destination vector
* @example
* var m_scenes = require("scenes");
* var m_trans = require("transform");
* var m_quat = require("quat");
* // precache quaternion
* var _quat_tmp = m_quat.create();
* // ...
* var cube = m_scenes.get_object_by_name("Cube");
* var rot_quat = m_trans.get_rotation(cube, _quat_tmp);
*/
exports.get_rotation = function(obj, opt_dest) {
if (!opt_dest)
opt_dest = new Float32Array(4);
m_trans.get_rotation(obj, opt_dest);
return opt_dest;
}
/**
* Get the object's rotation quaternion
* (in the coordinate space of its parent).
* @method module:transform.get_rotation_rel
* @param {Object3D} obj Object 3D
* @param {Quat} [opt_dest] Destination vector
* @returns {Quat} Destination vector
*/
exports.get_rotation_rel = function(obj, opt_dest) {
if (!opt_dest)
opt_dest = new Float32Array(4);
m_trans.get_rotation_rel(obj, opt_dest);
return opt_dest;
}
/**
* Set euler rotation in the ZYX intrinsic system.
* Using euler angles is discouraged, use quaternion instead.
* @method module:transform.set_rotation_euler
* @param {Object3D} obj Object 3D
* @param {number} x Angle X in radians
* @param {number} y Angle Y in radians
* @param {number} z Angle Z in radians
*/
exports.set_rotation_euler = function(obj, x, y, z) {
if (m_obj_util.is_dynamic(obj)) {
_vec3_tmp[0] = x;
_vec3_tmp[1] = y;
_vec3_tmp[2] = z;
m_trans.set_rotation_euler(obj, _vec3_tmp);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Get Euler rotation of object in the ZYX intrinsic system.
* Using euler angles is discouraged, use quaternion instead.
* @method module:transform.get_rotation_euler
* @param {Object3D} obj Object 3D
* @param {Euler} [dest = new Float32Array(3)] Destination vector
* @returns {Euler} Vector with Euler angles
*/
exports.get_rotation_euler = function(obj, dest) {
if (!dest)
dest = new Float32Array(3);
m_trans.get_rotation_euler(obj, dest);
return dest;
}
/**
* Get Euler rotation of object in the ZYX intrinsic system
* (in the coordinate space of its parent).
* Using euler angles is discouraged, use quaternion instead.
* @method module:transform.get_rotation_euler
* @param {Object3D} obj Object 3D
* @param {Euler} [dest = new Float32Array(3)] Destination vector
* @returns {Euler} Vector with Euler angles
*/
exports.get_rotation_euler_rel = function(obj, dest) {
if (!dest)
dest = new Float32Array(3);
m_trans.get_rotation_euler_rel(obj, dest);
return dest;
}
/**
* Set euler rotation in the ZYX intrinsic system
* (in the coordinate space of its parent).
* Using euler angles is discouraged, use quaternion instead.
* @method module:transform.set_rotation_euler_rel
* @param {Object3D} obj Object 3D
* @param {number} x Angle X in radians
* @param {number} y Angle Y in radians
* @param {number} z Angle Z in radians
*/
exports.set_rotation_euler_rel = function(obj, x, y, z) {
if (m_obj_util.is_dynamic(obj)) {
_vec3_tmp[0] = x;
_vec3_tmp[1] = y;
_vec3_tmp[2] = z;
m_trans.set_rotation_euler_rel(obj, _vec3_tmp);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Set euler rotation in vector form.
* Using euler angles is discouraged, use quaternion instead.
* @method module:transform.set_rotation_euler_v
* @param {Object3D} obj Object 3D
* @param {Euler} euler Vector with euler angles
*/
exports.set_rotation_euler_v = function(obj, euler) {
if (m_obj_util.is_dynamic(obj)) {
m_trans.set_rotation_euler(obj, euler);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Set euler rotation in vector form relatively to its parent
* (in the coordinate space of its parent).
* Using euler angles is discouraged, use quaternion instead.
* @method module:transform.set_rotation_euler_rel_v
* @param {Object3D} obj Object 3D
* @param {Euler} euler Vector with euler angles
*/
exports.set_rotation_euler_rel_v = function(obj, euler) {
if (m_obj_util.is_dynamic(obj)) {
m_trans.set_rotation_euler_rel(obj, euler);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Set the object scale.
* @method module:transform.set_scale
* @param {Object3D} obj Object 3D
* @param {number} scale Object scale
*/
exports.set_scale = function(obj, scale) {
if (m_obj_util.is_dynamic(obj)) {
m_trans.set_scale(obj, scale);
m_trans.update_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Set the object's scale
* (in the coordinate space of its parent).
* @method module:transform.set_scale_rel
* @param {Object3D} obj Object 3D
* @param {number} scale Object scale
*/
exports.set_scale_rel = function(obj, scale) {
if (m_obj_util.is_dynamic(obj)) {
m_trans.set_scale_rel(obj, scale);
m_trans.update_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Get the object scale.
* @method module:transform.get_scale
* @param {Object3D} obj Object 3D
* @returns {number} scale
*/
exports.get_scale = function(obj) {
return m_trans.get_scale(obj);
}
/**
* Get the object scale
* (in the coordinate space of its parent).
* @method module:transform.get_scale_rel
* @param {Object3D} obj Object 3D
* @returns {number} scale
*/
exports.get_scale_rel = function(obj) {
return m_trans.get_scale_rel(obj);
}
/**
* Reset EMPTY's transform to allow child objects behave in the absolute (world) space.
* @method module:transform.empty_reset_transform
* @param {Object3D} obj Object 3D
*/
exports.empty_reset_transform = function(obj) {
if (obj.type != "EMPTY") {
m_print.error("Wrong object: " + obj.name);
return;
}
for (var i = 0; i < obj.cons_descends.length; i++)
if (!m_obj_util.is_dynamic(obj.cons_descends[i])) {
m_print.error("Wrong object: \"" + obj.cons_descends[i].name
+ "\" is not dynamic.");
return;
}
m_trans.set_translation(obj, [0, 0, 0]);
m_trans.set_rotation(obj, [0, 0, 0, 1]);
m_trans.set_scale(obj, 1);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
}
/**
* Get object size (maximum radius, calculated from bounding box).
* @method module:transform.get_object_size
* @param {Object3D} obj Object 3D
* @returns {number} Object size
*/
exports.get_object_size = function(obj) {
if (!m_obj_util.is_mesh(obj)) {
m_print.error("Wrong object: " + obj.name);
return 0;
}
return m_trans.get_object_size(obj);
}
/**
* Get the object center in the world space.
* Works for dynamic and static objects.
* @method module:transform.get_object_center
* @param {Object3D} obj Object 3D
* @param {boolean} calc_bs_center Use the object's bounding sphere to
* calculate center, otherwise use the bounding box.
* @param {Vec3} [dest] Destination vector
* @returns {Vec3} Destination vector
*/
exports.get_object_center = function(obj, calc_bs_center, dest) {
if (!m_obj_util.is_mesh(obj)) {
m_print.error("Wrong object: " + obj.name);
return null;
}
if (!dest)
dest = new Float32Array(3);
return m_trans.get_object_center(obj, calc_bs_center, dest);
}
/**
* Perform incremental object translation in the local space.
* @method module:transform.move_local
* @param {Object3D} obj Object 3D
* @param {number} dx Translation offset along X axis
* @param {number} dy Translation offset along Y axis
* @param {number} dz Translation offset along Z axis
*/
exports.move_local = function(obj, dx, dy, dz) {
if (m_obj_util.is_dynamic(obj)) {
m_trans.move_local(obj, dx, dy, dz);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Perform incremental rotation around X axis in the local space.
* @method module:transform.rotate_x_local
* @param {Object3D} obj Object 3D
* @param {number} angle Angle in radians
*/
exports.rotate_x_local = function(obj, angle) {
if (m_obj_util.is_dynamic(obj)) {
var quat = m_quat.setAxisAngle(m_util.AXIS_X, angle, _quat4_tmp);
m_trans.rotate_local(obj, quat);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Perform incremental rotation around Y axis in the local space.
* @method module:transform.rotate_y_local
* @param {Object3D} obj Object 3D
* @param {number} angle Angle in radians
*/
exports.rotate_y_local = function(obj, angle) {
if (m_obj_util.is_dynamic(obj)) {
var quat = m_quat.setAxisAngle(m_util.AXIS_MY, angle, _quat4_tmp);
m_trans.rotate_local(obj, quat);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Perform incremental rotation around Z axis in the local space.
* @method module:transform.rotate_z_local
* @param {Object3D} obj Object 3D
* @param {number} angle Angle in radians
*/
exports.rotate_z_local = function(obj, angle) {
if (m_obj_util.is_dynamic(obj)) {
var quat = m_quat.setAxisAngle(m_util.AXIS_Z, angle, _quat4_tmp);
m_trans.rotate_local(obj, quat);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Get object bounding box.
* @method module:transform.get_object_bounding_box
* @param {Object3D} obj Object 3D
* @returns {BoundingBox} Bounding box
* @cc_externs max_x min_x max_y min_y max_z min_z
*/
exports.get_object_bounding_box = function(obj) {
return m_bounds.clone_bb(obj.render.bb_world);
}
/**
* Set the object's TSR vector.
* @method module:transform.set_tsr
* @param {Object3D} obj Object 3D
* @param {TSR} tsr vector
*/
exports.set_tsr = function(obj, tsr) {
if (m_obj_util.is_dynamic(obj)) {
m_trans.set_tsr(obj, tsr);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Set the object's TSR vector
* (in the coordinate space of its parent).
* @method module:transform.set_tsr_rel
* @param {Object3D} obj Object 3D
* @param {TSR} tsr vector
*/
exports.set_tsr_rel = function(obj, tsr) {
if (m_obj_util.is_dynamic(obj)) {
m_trans.set_tsr_rel(obj, tsr);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Return an object's transformation in TSR form.
* @method module:transform.get_tsr
* @param {Object3D} obj Object 3D
* @param {TSR} [dest] Destination vector.
* @returns {TSR} Destination vector.
*/
exports.get_tsr = function(obj, dest) {
if (!dest)
dest = new Float32Array(8);
m_trans.get_tsr(obj, dest);
return dest;
}
/**
* Return the object transformation in TSR form.
* (in the coordinate space of its parent).
* @method module:transform.get_tsr_rel
* @param {Object3D} obj Object 3D
* @param {TSR} [dest] Destination vector.
* @returns {TSR} Destination vector.
*/
exports.get_tsr_rel = function(obj, dest) {
if (!dest)
dest = new Float32Array(8);
m_trans.get_tsr_rel(obj, dest);
return dest;
}
/**
* Get distance between the two objects.
* @method module:transform.distance
* @param {Object3D} obj1 The first object.
* @param {Object3D} obj2 The second object.
* @returns {number} Distance
*/
exports.distance = function(obj1, obj2) {
return m_trans.distance(obj1, obj2);
}
/**
* Set the object's transformation matrix.
* It's better to use TSR form.
* @method module:transform.set_matrix
* @param {Object3D} obj Object 3D
* @param {Mat4} mat Matrix
*/
exports.set_matrix = function(obj, mat) {
if (m_obj_util.is_dynamic(obj)) {
m_tsr.from_mat4(mat, _tsr_tmp);
m_trans.set_tsr(obj, _tsr_tmp);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Set the object's transformation matrix
* (in the coordinate space of its parent).
* It's better to use TSR form.
* @method module:transform.set_matrix_rel
* @param {Object3D} obj Object 3D
* @param {Mat4} mat Matrix
*/
exports.set_matrix_rel = function(obj, mat) {
if (m_obj_util.is_dynamic(obj)) {
m_tsr.from_mat4(mat, _tsr_tmp);
m_trans.set_tsr_rel(obj, _tsr_tmp);
m_trans.update_transform(obj);
m_phy.sync_transform(obj);
} else
m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
}
/**
* Return the object's transformation matrix.
* It's better to use TSR form.
* @method module:transform.get_matrix
* @param {Object3D} obj Object 3D
* @param {Mat4} [dest] Destination matrix.
* @returns {Mat4} Destination matrix.
*/
exports.get_matrix = function(obj, dest) {
if (!dest)
dest = new Float32Array(16);
m_trans.get_tsr(obj, _tsr_tmp);
m_tsr.to_mat4(_tsr_tmp, dest);
return dest;
}
/**
* Return the object's transformation matrix
* (in the coordinate space of its parent).
* It's better to use TSR form.
* @method module:transform.get_matrix_rel
* @param {Object3D} obj Object 3D
* @param {Mat4} [dest] Destination matrix.
* @returns {Mat4} Destination matrix.
*/
exports.get_matrix_rel = function(obj, dest) {
if (!dest)
dest = new Float32Array(16);
m_trans.get_tsr_rel(obj, _tsr_tmp);
m_tsr.to_mat4(_tsr_tmp, dest);
return dest;
}
}
var transform_factory = register("transform", Transform);
export default transform_factory;