/** * Calculate pose data for given bone. * recursively calculate _tsr_channel_cache beginning from "root" * store _tsr_channel_cache_valid state in each pose bone */ function calc_pose_bone(pose_bone, dest_trans_scale, dest_quat) { var chain = pose_bone._chain; var pose_bone_root = chain[chain.length-1]; var tsr_channel_parent = pose_bone_root._tsr_channel_cache; // reset "root" bone if not valid if (!pose_bone_root._tsr_channel_cache_valid) m_tsr.identity(tsr_channel_parent); // start from the last bone ("root" for chain) for (var i = chain.length - 1; i >= 0; i--) { var pose_bone = chain[i]; var tsr_channel = pose_bone._tsr_channel_cache; // this can be already calculated because // a bone can participate in other chains // else calculate channel TSR if (pose_bone._tsr_channel_cache_valid) { tsr_channel_parent = tsr_channel; continue; } // bone armature-relative TSR var tsr_local = pose_bone._tsr_local; // pose bone-relative TSR var tsr_basis = pose_bone._tsr_basis; // apply basis translation (delta) in armature space // go to bone space, apply pose, return back to armature space // tsr_local * (tsr_basis * tsr_locali) m_tsr.invert(tsr_local, _tsr8_tmp); m_tsr.multiply(tsr_basis, _tsr8_tmp, _tsr8_tmp); m_tsr.multiply(tsr_local, _tsr8_tmp, _tsr8_tmp); // apply hierarchy m_tsr.multiply(tsr_channel_parent, _tsr8_tmp, tsr_channel); // save tsr_channel_parent = tsr_channel; pose_bone._tsr_channel_cache_valid = true; } // split and store calculated TSR var tsr = pose_bone._tsr_channel_cache; dest_trans_scale[0] = tsr[0]; dest_trans_scale[1] = tsr[1]; dest_trans_scale[2] = tsr[2]; dest_trans_scale[3] = tsr[3]; dest_quat[0] = tsr[4]; dest_quat[1] = tsr[5]; dest_quat[2] = tsr[6]; dest_quat[3] = tsr[7]; m_quat.normalize(dest_quat, dest_quat); }
exports.rotate_local = function(obj, quat) { var p_tsr = get_tsr_rel(obj, _tsr_tmp); var tsr = m_tsr.set_quat(quat, m_tsr.identity(_tsr_tmp2)); m_tsr.multiply(p_tsr, tsr, tsr); set_tsr_rel(obj, tsr); }
function update_bone_tsr_r(bone_pointer, use_bone_space, trans, quats) { var tsr_bone_pose = bone_pointer.tsr_bone_pose; var tsr_local_rest = bone_pointer.tsr_local_rest; var tsr_local_pose = bone_pointer.tsr_local_pose; var parent_bone_ptr = bone_pointer.parent_bone_ptr; if (parent_bone_ptr) { var tsr_par_local = parent_bone_ptr.tsr_local_pose; if (use_bone_space) m_tsr.multiply(tsr_par_local, tsr_bone_pose, tsr_local_pose); else { var inv_tsr_par_local = _tsr_tmp2; m_tsr.invert(tsr_par_local, inv_tsr_par_local); m_tsr.multiply(inv_tsr_par_local, tsr_local_pose, tsr_bone_pose); } } else if (use_bone_space) m_tsr.copy(tsr_bone_pose, tsr_local_pose); else m_tsr.copy(tsr_local_pose, tsr_bone_pose); var dest_tsr = _tsr_tmp; m_tsr.invert(tsr_local_rest, dest_tsr); m_tsr.multiply(tsr_local_pose, dest_tsr, dest_tsr); var index = bone_pointer.bone_index; trans[4*index] = dest_tsr[0]; trans[4*index+1] = dest_tsr[1]; trans[4*index+2] = dest_tsr[2]; trans[4*index+3] = dest_tsr[3]; quats[4*index] = dest_tsr[4]; quats[4*index+1] = dest_tsr[5]; quats[4*index+2] = dest_tsr[6]; quats[4*index+3] = dest_tsr[7]; var descend_ptrs = bone_pointer.descend_bones_ptrs; for (var i = 0; i < descend_ptrs.length; i++) { var desc_bone_ptr = descend_ptrs[i]; // NOTE: temporary do not update child bones with constraints if (desc_bone_ptr.constraint) continue; update_bone_tsr_r(desc_bone_ptr, true, trans, quats) } }
exports.set_tsr = function(obj, tsr) { m_tsr.copy(tsr, obj.render.world_tsr); if (m_cons.has_child_of(obj)) { var tsr_par = m_cons.get_child_of_parent_tsr(obj); var tsr_inv = m_tsr.invert(tsr_par, _tsr_tmp); var offset = m_cons.get_child_of_offset(obj); m_tsr.multiply(tsr_inv, obj.render.world_tsr, offset); } }
exports.set_translation = function(obj, trans) { var render = obj.render; if (m_cons.has_child_of(obj)) { m_tsr.set_trans(trans, render.world_tsr); var tsr_par = m_cons.get_child_of_parent_tsr(obj); var tsr_inv = m_tsr.invert(tsr_par, _tsr_tmp); var offset = m_cons.get_child_of_offset(obj); m_tsr.multiply(tsr_inv, render.world_tsr, offset); } else m_tsr.set_trans(trans, render.world_tsr); }
function set_rotation(obj, quat) { var render = obj.render; if (m_cons.has_child_of(obj)) { m_tsr.set_quat(quat, render.world_tsr); var tsr_par = m_cons.get_child_of_parent_tsr(obj); var tsr_inv = m_tsr.invert(tsr_par, _tsr_tmp); var offset = m_cons.get_child_of_offset(obj); m_tsr.multiply(tsr_inv, render.world_tsr, offset); } else m_tsr.set_quat(quat, render.world_tsr); }
exports.set_bone_tsr = function(armobj, bone_name, tsr, use_bone_space) { var render = armobj.render; var bone_pointer = render.bone_pointers[bone_name]; var trans_before = render.trans_before; var quats_before = render.quats_before; if (use_bone_space) m_tsr.multiply(bone_pointer.tsr_bone_rest, tsr, bone_pointer.tsr_bone_pose); else m_tsr.copy(tsr, bone_pointer.tsr_local_pose); update_bone_tsr_r(bone_pointer, use_bone_space, trans_before, quats_before); render.frame_factor = 0; update_skinned_renders(armobj); }
/** * Get armature bone pose data (animated or static) * NOTE: need to be somewhere else * uses _vec4_tmp, _quat4_tmp, _quat4_tmp2, _tsr8_tmp, _tsr8_tmp2 */ function get_bone_pose(armobj, bone_name, get_pose_tail, dest_transscale, dest_quat) { var render = armobj._render; var frame_factor = render.frame_factor; var bone_pointer = render.bone_pointers[bone_name]; var index = bone_pointer.deform_bone_index; var pose_bone_index = bone_pointer.pose_bone_index; var bone = armobj["pose"]["bones"][pose_bone_index]; var tsr_local = bone._tsr_local; var transcale = _vec4_tmp; var trans_before = render.trans_before; var trans_after = render.trans_after; var quats_before = render.quats_before; var quats_after = render.quats_after; var x = trans_before[4*index]; var y = trans_before[4*index+1]; var z = trans_before[4*index+2]; var s = trans_before[4*index+3]; var xn = trans_after[4*index]; var yn = trans_after[4*index+1]; var zn = trans_after[4*index+2]; var sn = trans_after[4*index+3]; transcale[0] = (1-frame_factor) * x + frame_factor * xn; transcale[1] = (1-frame_factor) * y + frame_factor * yn; transcale[2] = (1-frame_factor) * z + frame_factor * zn; transcale[3] = (1-frame_factor) * s + frame_factor * sn; var quat = _quat4_tmp; var quatn = _quat4_tmp2; quat[0] = quats_before[4*index]; quat[1] = quats_before[4*index+1]; quat[2] = quats_before[4*index+2]; quat[3] = quats_before[4*index+3]; quatn[0] = quats_after[4*index]; quatn[1] = quats_after[4*index+1]; quatn[2] = quats_after[4*index+2]; quatn[3] = quats_after[4*index+3]; m_quat.slerp(quat, quatn, frame_factor, quat); var tsr_bone = _tsr8_tmp; m_tsr.set_transcale(transcale, tsr_bone); m_tsr.set_quat(quat, tsr_bone); if (get_pose_tail) { var tsr_local_tail = _tsr8_tmp2; m_tsr.translate(tsr_local, bone._tail, tsr_local_tail); m_tsr.multiply(tsr_bone, tsr_local_tail, tsr_bone); } else m_tsr.multiply(tsr_bone, tsr_local, tsr_bone); // from armature to world space m_tsr.multiply(render.tsr, tsr_bone, tsr_bone); dest_transscale[0] = tsr_bone[0]; dest_transscale[1] = tsr_bone[1]; dest_transscale[2] = tsr_bone[2]; dest_transscale[3] = tsr_bone[3]; if (dest_quat) { dest_quat[0] = tsr_bone[4]; dest_quat[1] = tsr_bone[5]; dest_quat[2] = tsr_bone[6]; dest_quat[3] = tsr_bone[7]; } }
/** * Only trans/quat affected by constraint here */ function update_cons(obj, cons, elapsed) { switch (cons.type) { case CONS_TYPE_STIFF_OBJ: var trans = obj._render.trans; var quat = obj._render.quat; var p_world_matrix = cons.obj_parent._render.world_matrix; var p_trans = cons.obj_parent._render.trans; var p_quat = cons.obj_parent._render.quat; if (cons.rotation_offset) { m_quat.copy(cons.rotation_offset, quat); m_quat.multiply(p_quat, quat, quat); } else m_quat.copy(p_quat, quat); m_vec3.transformMat4(cons.offset, p_world_matrix, obj._render.trans); obj._render.scale = cons.scale_offset * cons.obj_parent._render.scale; break; case CONS_TYPE_SEMI_STIFF_OBJ: var trans = obj._render.trans; var quat = obj._render.quat; var p_world_matrix = cons.obj_parent._render.world_matrix; var p_quat = cons.obj_parent._render.quat; // Qp * Qp_prev_inv * Q m_quat.multiply( m_quat.invert(cons.parent_prev_rotation, cons.parent_prev_rotation), quat, quat); m_quat.multiply(p_quat, quat, quat); m_vec3.transformMat4(cons.offset, p_world_matrix, trans); m_quat.copy(p_quat, cons.parent_prev_rotation); break; case CONS_TYPE_SEMI_STIFF_CAM_OBJ: var trans = obj._render.trans; var quat = obj._render.quat; var p_world_matrix = cons.obj_parent._render.world_matrix; var p_quat = cons.obj_parent._render.quat; // Qp * Qp_prev_inv * Q m_quat.multiply( m_quat.invert(cons.parent_prev_rotation, cons.parent_prev_rotation), quat, quat); m_quat.multiply(p_quat, quat, quat); m_vec3.transformMat4(cons.offset, p_world_matrix, trans); m_quat.copy(p_quat, cons.parent_prev_rotation) clamp_angles(obj, cons); if (obj._render.type == "CAMERA") { var p_y_axis = m_vec3.transformQuat(m_util.AXIS_Y, p_quat, _vec3_tmp_2); correct_up(obj, p_y_axis); } break; case CONS_TYPE_SEMI_SOFT_CAM_OBJ: var trans = obj._render.trans; var quat = obj._render.quat; var p_world_matrix = cons.obj_parent._render.world_matrix; var p_trans = cons.obj_parent._render.trans; var trans_pivot = _vec3_tmp; var quat_pivot = _quat4_tmp; m_vec3.transformMat4(cons.offset, p_world_matrix, trans_pivot); m_util.smooth_v(trans_pivot, trans, elapsed, 0.3, trans); var dir_to_obj = _vec3_tmp; m_vec3.sub(p_trans, trans, dir_to_obj); m_vec3.normalize(dir_to_obj, dir_to_obj); cam_rotate_to(quat, dir_to_obj, quat_pivot); m_util.smooth_q(quat_pivot, quat, elapsed, 0.1, quat); break; case CONS_TYPE_STIFF_BONE: var trans = obj._render.trans; var quat = obj._render.quat; var p_trans = _vec4_tmp; var p_quat = _quat4_tmp; get_bone_pose(cons.obj_parent, cons.bone_name, true, p_trans, p_quat); if (cons.rotation_offset) { m_quat.copy(cons.rotation_offset, quat); m_quat.multiply(p_quat, quat, quat); } else m_quat.copy(p_quat, quat); m_util.transform_vec3(cons.offset, 1, p_quat, p_trans, obj._render.trans); break; case CONS_TYPE_TRACK_OBJ: var trans = obj._render.trans; var quat = obj._render.quat; var t_trans = cons.obj_parent._render.trans; rotate_to(trans, quat, t_trans); if (obj._render.type == "CAMERA") correct_up(obj, m_util.AXIS_Y); break; case CONS_TYPE_TRACK_POINT: var trans = obj._render.trans; var quat = obj._render.quat; var t_trans = cons.target; rotate_to(trans, quat, t_trans); if (obj._render.type == "CAMERA") correct_up(obj, m_util.AXIS_Y); break; case CONS_TYPE_FOLLOW_OBJ: var trans = obj._render.trans; var quat = obj._render.quat; var t_trans = cons.obj_parent._render.trans; var is_rotated = rotate_to_limits(trans, quat, t_trans, CONS_ROTATE_LIMIT); // shrink distance var dist = m_vec3.dist(trans, t_trans); // passing target location if (!is_rotated) delta = dist + cons.offset_min; else { if (dist > cons.offset_max) var delta = dist - cons.offset_max; else if (dist < cons.offset_min) var delta = dist - cons.offset_min; else var delta = 0.0; } if (delta) { // NOTE: from trans to t_trans m_vec3.sub(t_trans, trans, _vec3_tmp); m_vec3.normalize(_vec3_tmp, _vec3_tmp); m_vec3.scale(_vec3_tmp, delta, _vec3_tmp); m_vec3.add(trans, _vec3_tmp, trans); } if (obj._render.type == "CAMERA") correct_up(obj, m_util.AXIS_Y); break; case CONS_TYPE_FOLLOW_POINT: var trans = obj._render.trans; var quat = obj._render.quat; var t_trans = cons.target; var is_rotated = rotate_to_limits(trans, quat, t_trans, CONS_ROTATE_LIMIT); // shrink distance var dist = m_vec3.dist(trans, t_trans); // passing target location if (!is_rotated) delta = dist + cons.offset_min; else { if (dist > cons.offset_max) var delta = dist - cons.offset_max; else if (dist < cons.offset_min) var delta = dist - cons.offset_min; else var delta = 0.0; } if (delta) { // NOTE: from trans to t_trans m_vec3.sub(t_trans, trans, _vec3_tmp); m_vec3.normalize(_vec3_tmp, _vec3_tmp); m_vec3.scale(_vec3_tmp, delta, _vec3_tmp); m_vec3.add(trans, _vec3_tmp, trans); } if (obj._render.type == "CAMERA") correct_up(obj, m_util.AXIS_Y); break; case CONS_TYPE_STIFF_TRANS_OBJ: var p_world_matrix = cons.obj_parent._render.world_matrix; m_vec3.transformMat4(cons.offset, p_world_matrix, obj._render.trans); break; case CONS_TYPE_COPY_TRANS_OBJ: var p_trans = cons.obj_parent._render.trans; var trans = obj._render.trans; m_vec3.add(p_trans, cons.offset, trans); break; case CONS_TYPE_STIFF_TRANS_ROT_OBJ: var trans = obj._render.trans; var quat = obj._render.quat; var p_world_matrix = cons.obj_parent._render.world_matrix; var p_trans = cons.obj_parent._render.trans; var p_quat = cons.obj_parent._render.quat; if (cons.rotation_offset) { m_quat.copy(cons.rotation_offset, quat); m_quat.multiply(p_quat, quat, quat); } else m_quat.copy(p_quat, quat); m_vec3.transformMat4(cons.offset, p_world_matrix, obj._render.trans); break; case CONS_TYPE_CHILD_OF: var prender = cons.obj_parent._render; var ptsr = m_tsr.create_sep(prender.trans, prender.scale, prender.quat, _tsr8_tmp); var tsr_offset = cons.tsr_offset; m_tsr.multiply(ptsr, tsr_offset, ptsr); var trans = obj._render.trans; trans[0] = ptsr[0]; trans[1] = ptsr[1]; trans[2] = ptsr[2]; obj._render.scale = ptsr[3]; var quat = obj._render.quat; quat[0] = ptsr[4]; quat[1] = ptsr[5]; quat[2] = ptsr[6]; quat[3] = ptsr[7]; break; default: break; } }
/** * Only trans/quat affected by constraint here */ function update_cons(obj, cons, elapsed) { switch (cons.type) { case CONS_TYPE_STIFF_OBJ: var quat = obj._render.quat; var p_world_matrix = cons.obj_parent._render.world_matrix; var p_quat = cons.obj_parent._render.quat; if (cons.rotation_offset) { m_quat.copy(cons.rotation_offset, quat); m_quat.multiply(p_quat, quat, quat); } else m_quat.copy(p_quat, quat); m_vec3.transformMat4(cons.offset, p_world_matrix, obj._render.trans); obj._render.scale = cons.scale_offset * cons.obj_parent._render.scale; break; case CONS_TYPE_SEMI_STIFF_OBJ: var trans = obj._render.trans; var quat = obj._render.quat; var p_world_matrix = cons.obj_parent._render.world_matrix; var p_quat = cons.obj_parent._render.quat; // Qp * Qp_prev_inv * Q m_quat.multiply( m_quat.invert(cons.parent_prev_rotation, cons.parent_prev_rotation), quat, quat); m_quat.multiply(p_quat, quat, quat); m_vec3.transformMat4(cons.offset, p_world_matrix, trans); m_quat.copy(p_quat, cons.parent_prev_rotation); break; case CONS_TYPE_SEMI_STIFF_CAM_OBJ: var trans = obj._render.trans; var quat = obj._render.quat; var p_world_matrix = cons.obj_parent._render.world_matrix; var p_quat = cons.obj_parent._render.quat; // Qp * Qp_prev_inv * Q m_quat.multiply( m_quat.invert(cons.parent_prev_rotation, cons.parent_prev_rotation), quat, quat); m_quat.multiply(p_quat, quat, quat); m_vec3.transformMat4(cons.offset, p_world_matrix, trans); m_quat.copy(p_quat, cons.parent_prev_rotation) clamp_orientation(obj, cons); break; case CONS_TYPE_SEMI_SOFT_CAM_OBJ: var trans = obj._render.trans; var quat = obj._render.quat; var p_world_matrix = cons.obj_parent._render.world_matrix; var p_trans = cons.obj_parent._render.trans; var softness = cons.softness; var trans_pivot = _vec3_tmp; var quat_pivot = _quat4_tmp; var softness_ratio = 0.16; m_vec3.transformMat4(cons.offset, p_world_matrix, trans_pivot); m_util.smooth_v(trans_pivot, trans, elapsed, softness, trans); var dir_to_obj = _vec3_tmp; m_vec3.sub(p_trans, trans, dir_to_obj); m_vec3.normalize(dir_to_obj, dir_to_obj); cam_rotate_to(quat, dir_to_obj, quat_pivot); m_util.smooth_q(quat_pivot, quat, elapsed, softness * softness_ratio, quat); break; case CONS_TYPE_STIFF_BONE: var quat = obj._render.quat; var p_transscale = _vec4_tmp; var p_quat = _quat4_tmp; get_bone_pose(cons.obj_parent, cons.bone_name, true, p_transscale, p_quat); if (cons.rotation_offset) { m_quat.copy(cons.rotation_offset, quat); m_quat.multiply(p_quat, quat, quat); } else m_quat.copy(p_quat, quat); obj._render.scale = cons.scale_offset * p_transscale[3]; m_util.transform_vec3(cons.offset, p_transscale[3], p_quat, p_transscale, obj._render.trans); break; case CONS_TYPE_TRACK_OBJ: var trans = obj._render.trans; var quat = obj._render.quat; var t_trans = cons.obj_parent._render.trans; rotate_to(trans, quat, t_trans); break; case CONS_TYPE_TRACK_POINT: var trans = obj._render.trans; var quat = obj._render.quat; var t_trans = cons.target; rotate_to(trans, quat, t_trans); break; case CONS_TYPE_FOLLOW_OBJ: var trans = obj._render.trans; var quat = obj._render.quat; var t_trans = cons.obj_parent._render.trans; rotate_to(trans, quat, t_trans); // shrink distance var dist = m_vec3.dist(trans, t_trans); // passing target location if (dist > cons.offset_max) var delta = dist - cons.offset_max; else if (dist < cons.offset_min) var delta = dist - cons.offset_min; else var delta = 0.0; if (delta) { // NOTE: from trans to t_trans m_vec3.sub(t_trans, trans, _vec3_tmp); m_vec3.normalize(_vec3_tmp, _vec3_tmp); m_vec3.scale(_vec3_tmp, delta, _vec3_tmp); m_vec3.add(trans, _vec3_tmp, trans); } break; case CONS_TYPE_FOLLOW_POINT: var trans = obj._render.trans; var quat = obj._render.quat; var t_trans = cons.target; rotate_to(trans, quat, t_trans); // shrink distance var dist = m_vec3.dist(trans, t_trans); // passing target location if (dist > cons.offset_max) var delta = dist - cons.offset_max; else if (dist < cons.offset_min) var delta = dist - cons.offset_min; else var delta = 0.0; if (delta) { // NOTE: from trans to t_trans m_vec3.sub(t_trans, trans, _vec3_tmp); m_vec3.normalize(_vec3_tmp, _vec3_tmp); m_vec3.scale(_vec3_tmp, delta, _vec3_tmp); m_vec3.add(trans, _vec3_tmp, trans); } break; case CONS_TYPE_STIFF_TRANS_OBJ: var p_world_matrix = cons.obj_parent._render.world_matrix; m_vec3.transformMat4(cons.offset, p_world_matrix, obj._render.trans); break; case CONS_TYPE_COPY_TRANS_OBJ: var p_trans = cons.obj_parent._render.trans; var trans = obj._render.trans; m_vec3.add(p_trans, cons.offset, trans); break; case CONS_TYPE_STIFF_TRANS_ROT_OBJ: var quat = obj._render.quat; var p_world_matrix = cons.obj_parent._render.world_matrix; var p_quat = cons.obj_parent._render.quat; if (cons.rotation_offset) { m_quat.copy(cons.rotation_offset, quat); m_quat.multiply(p_quat, quat, quat); } else m_quat.copy(p_quat, quat); m_vec3.transformMat4(cons.offset, p_world_matrix, obj._render.trans); break; case CONS_TYPE_CHILD_OF: var prender = cons.obj_parent._render; var ptsr = m_tsr.create_sep(prender.trans, prender.scale, prender.quat, _tsr8_tmp); var tsr_offset = cons.tsr_offset; m_tsr.multiply(ptsr, tsr_offset, ptsr); var trans = obj._render.trans; trans[0] = ptsr[0]; trans[1] = ptsr[1]; trans[2] = ptsr[2]; obj._render.scale = ptsr[3]; var quat = obj._render.quat; quat[0] = ptsr[4]; quat[1] = ptsr[5]; quat[2] = ptsr[6]; quat[3] = ptsr[7]; break; case CONS_TYPE_STIFF_VIEWPORT: var camobj = cons.obj_parent; var cam = m_cam.get_first_cam(camobj); var trans = obj._render.trans; var top = m_cam.get_edge(cam, "TOP"); var bottom = m_cam.get_edge(cam, "BOTTOM"); var height = top - bottom; if (cons.left_edge) { var left = m_cam.get_edge(cam, "LEFT"); trans[0] = left + height * cons.left_right_dist; } else { var right = m_cam.get_edge(cam, "RIGHT"); trans[0] = right - height * cons.left_right_dist; } // in the camera's local space (not view space) if (cons.top_edge) trans[2] = -(top - height * cons.top_bottom_dist); else trans[2] = -(bottom + height * cons.top_bottom_dist); // NOTE: ortho cameras have scaling problems if (m_cam.is_ortho(cam)) { trans[1] = -cons.distance; } else { trans[1] = -1; m_vec3.normalize(trans, trans); var scale = cons.distance/Math.abs(trans[1]); m_vec3.scale(trans, scale, trans); } m_tsr.transform_dir_vec3(trans, camobj._render.tsr, trans); m_vec3.add(camobj._render.trans, trans, trans); var quat = obj._render.quat; if (cons.rotation_offset) { m_quat.copy(cons.rotation_offset, quat); m_quat.multiply(camobj._render.quat, quat, quat); } else m_quat.copy(camobj._render.quat, quat); break; default: break; } if (obj._render.type == "CAMERA") { var corr_axis = m_util.AXIS_Y; if (cons.type == CONS_TYPE_SEMI_STIFF_CAM_OBJ) { var p_quat = cons.obj_parent._render.quat; corr_axis = m_vec3.transformQuat(corr_axis, p_quat, _parent_y_axis); } m_cam.update_camera_upside_down(obj); correct_up(obj, corr_axis); } }
/** * Set object render world_matrix. * NOTE: do not try to update batched objects (buggy _dg_parent influence) * @methodOf transform * @param {Object} obj Object ID */ function update_transform(obj) { var render = obj._render; // NOTE: need to update before constraints, because they rely on to this flag if (obj["type"] == "CAMERA") m_cam.update_camera_upside_down(obj); m_cons.update_constraint(obj, _elapsed); if (obj["type"] == "CAMERA") m_cam.update_camera(obj); // should not change after constraint update var trans = render.trans; var scale = render.scale; var quat = render.quat; m_tsr.set_sep(trans, scale, quat, render.tsr); var wm = render.world_matrix; m_mat4.identity(wm); m_mat4.fromQuat(quat, wm); // TODO: remove world matrix and move to tsr system if (obj["type"] != "CAMERA") m_util.scale_mat4(wm, scale, wm); wm[12] = trans[0]; wm[13] = trans[1]; wm[14] = trans[2]; m_mat4.invert(wm, render.inv_world_matrix); if (obj._anim_slots.length && m_particles.has_anim_particles(obj)) m_particles.update_emitter_transform(obj); // NOTE: available only after batch creation (really needed now?) if (render.bb_local && render.bb_world) { m_bounds.bounding_box_transform(render.bb_local, wm, render.bb_world); m_bounds.bounding_sphere_transform(render.bs_local, wm, render.bs_world); m_bounds.bounding_ellipsoid_transform(render.be_local, render.tsr, render.be_world) if (render.shadow_cast) m_scs.schedule_shadow_update(m_scs.get_active()); } switch (obj["type"]) { case "SPEAKER": m_sfx.speaker_update_transform(obj, _elapsed); break; case "CAMERA": m_cam.update_camera_transform(obj); // listener only for active scene camera if (m_scs.check_active() && m_scs.get_camera(m_scs.get_active()) == obj) m_sfx.listener_update_transform(m_scs.get_active(), trans, quat, _elapsed); break; case "LAMP": m_lights.update_light_transform(obj); if (m_scs.check_active()) m_scs.update_lamp_scene(obj, m_scs.get_active()); break; case "EMPTY": if (obj["field"]) m_scs.update_force(obj); break; } if (obj["type"] == "LAMP" || obj["type"] == "CAMERA") { if (m_scs.check_active()) { var active_scene = m_scs.get_active(); m_scs.schedule_shadow_update(active_scene); m_scs.schedule_grass_map_update(active_scene); } } if (obj["type"] == "MESH") { var modifiers = obj["modifiers"]; var armobj = null; for (var i = 0; i < modifiers.length; i++) { var modifier = modifiers[i]; if (modifier["type"] == "ARMATURE") armobj = modifier["object"]; } if (armobj) { var armobj_tsr = armobj._render.tsr; m_tsr.invert(armobj_tsr, _tsr_tmp); m_tsr.multiply(_tsr_tmp, render.tsr, _tsr_tmp); m_vec4.set(_tsr_tmp[0], _tsr_tmp[1], _tsr_tmp[2], _tsr_tmp[3], render.arm_rel_trans); m_quat.set(_tsr_tmp[4], _tsr_tmp[5], _tsr_tmp[6], _tsr_tmp[7], render.arm_rel_quat); } } var descends = obj._descends; for (var i = 0; i < descends.length; i++) update_transform(descends[i]); render.force_zsort = true; }
/** * Set object render world_tsr. * NOTE: do not try to update batched objects (buggy _dg_parent influence) * @methodOf transform * @param {Object3D} obj Object 3D */ function update_transform(obj) { var render = obj.render; var scenes_data = obj.scenes_data; var obj_type = obj.type; // NOTE: need to update before constraints, because they rely on to this flag if (obj_type == "CAMERA") m_cam.update_camera_upside_down(obj); m_cons.update_constraint(obj, _elapsed); if (obj_type == "CAMERA") m_cam.update_camera(obj); // should not change after constraint update var trans = m_tsr.get_trans_value(render.world_tsr, _vec3_tmp); var quat = m_tsr.get_quat_value(render.world_tsr, _quat4_tmp); // NOTE: available only after batch creation (really needed now?) if (render.bb_local && render.bb_world) { m_bounds.bounding_box_transform(render.bb_local, render.world_tsr, render.bb_world); m_bounds.bounding_sphere_transform(render.bs_local, render.world_tsr, render.bs_world); m_bounds.bounding_ellipsoid_transform(render.be_local, render.world_tsr, render.be_world) } switch (obj_type) { case "SPEAKER": m_sfx.speaker_update_transform(obj, _elapsed); break; case "MESH": var armobj = obj.armobj; if (armobj) { var armobj_tsr = armobj.render.world_tsr; m_tsr.invert(armobj_tsr, _tsr_tmp); m_tsr.multiply(_tsr_tmp, render.world_tsr, _tsr_tmp); m_vec4.set(_tsr_tmp[0], _tsr_tmp[1], _tsr_tmp[2], _tsr_tmp[3], render.arm_rel_trans); m_quat.set(_tsr_tmp[4], _tsr_tmp[5], _tsr_tmp[6], _tsr_tmp[7], render.arm_rel_quat); } break; case "CAMERA": m_cam.update_camera_transform(obj); // listener only for active scene camera if (m_scs.check_active()) { var active_scene = m_scs.get_active(); if (m_scs.get_camera(active_scene) == obj) m_sfx.listener_update_transform(active_scene, trans, quat, _elapsed); } break; case "LAMP": m_lights.update_light_transform(obj); break; } for (var i = 0; i < scenes_data.length; i++) { var sc_data = scenes_data[i]; if (sc_data.is_active) { var scene = sc_data.scene; var sc_render = scene._render; var batches = sc_data.batches; switch (obj_type) { case "LAMP": m_scs.update_lamp_scene(obj, scene); break; case "CAMERA": m_scs.schedule_grass_map_update(scene); if (sc_render.shadow_params) { // camera movement only influence csm shadows if (sc_render.shadow_params.enable_csm) m_scs.schedule_shadow_update(scene); m_scs.update_shadow_billboard_view(obj, sc_render.graph); } break; case "MESH": if (render.bb_local && render.bb_world) { if (render.shadow_cast) m_scs.schedule_shadow_update(scene); var cube_refl_subs = sc_data.cube_refl_subs; if (render.cube_reflection_id != null && cube_refl_subs) { m_scs.update_cube_reflect_subs(cube_refl_subs, trans); } } break; case "EMPTY": m_obj.update_force(obj); break; } var plane_refl_subs = sc_data.plane_refl_subs; var refl_objs = obj.reflective_objs; if (refl_objs.length) { for (var j = 0; j < plane_refl_subs.length; j++) { var cam = plane_refl_subs[j].camera; m_scs.update_plane_reflect_subs(plane_refl_subs[j], trans, quat); m_obj_util.update_refl_objects(refl_objs, cam.reflection_plane); m_cam.set_view(cam, m_scs.get_camera(scene)); m_util.extract_frustum_planes(cam.view_proj_matrix, cam.frustum_planes); } } } } var cons_descends = obj.cons_descends; for (var i = 0; i < cons_descends.length; i++) update_transform(cons_descends[i]); var cons_armat_bone_descends = obj.cons_armat_bone_descends; for (var i = 0; i < cons_armat_bone_descends.length; i++) { var cons_armat_desc = cons_armat_bone_descends[i]; var armobj = cons_armat_desc[0]; var bone_name = cons_armat_desc[1]; m_cons.update_bone_constraint(armobj, bone_name); } render.force_zsort = true; }
function update_object(bpy_armobj, armobj) { var arm_bones = bpy_armobj["data"]["bones"]; var pose_bones = bpy_armobj["pose"]["bones"]; var bone_pointers = {}; for (var i = 0; i < pose_bones.length; i++) { var pose_bone = pose_bones[i]; var arm_bone = pose_bone["bone"]; var bone_name = arm_bone["name"]; var bpointer = bone_pointers[bone_name] = init_bone_pointer(); var mat_loc = new Float32Array(arm_bone["matrix_local"]); var mat_loc_inv = new Float32Array(16); m_mat4.invert(mat_loc, mat_loc_inv); var mat_bas = new Float32Array(pose_bone["matrix_basis"]); var tail = bpointer.tail; m_vec3.subtract(arm_bone["tail_local"], arm_bone["head_local"], tail); // translate tail offset from armature to bone space m_util.vecdir_multiply_matrix(tail, mat_loc_inv, tail); m_tsr.from_mat4(mat_loc, bpointer.tsr_local_rest); m_tsr.from_mat4(mat_bas, bpointer.tsr_basis); m_tsr.copy(bpointer.tsr_local_rest, bpointer.tsr_local_pose); } for (var i = 0; i < arm_bones.length; i++) { var bone = arm_bones[i]; var bone_name = bone["name"]; var pose_bone = m_util.keysearch("name", bone_name, pose_bones); var bpointer = bone_pointers[bone_name]; var parent_pose_bones = pose_bone["parent_recursive"]; // include current bone to chain with its parents bpointer.chain.push(bpointer); for (var j = 0; j < parent_pose_bones.length; j++) { var parent_bone = parent_pose_bones[j]; var parent_bone_name = parent_bone["name"]; var parent_bone_ptr = bone_pointers[parent_bone_name]; bpointer.chain.push(parent_bone_ptr); } if (parent_pose_bones.length) { var parent_bone = parent_pose_bones[0]; var parent_bone_name = parent_bone["name"]; var parent_bone_ptr = bone_pointers[parent_bone_name]; bpointer.parent_bone_ptr = parent_bone_ptr; m_tsr.invert(parent_bone_ptr.tsr_local_rest, _tsr_tmp); m_tsr.multiply(_tsr_tmp, bpointer.tsr_local_rest, bpointer.tsr_bone_rest); // store only direct bone's descendants parent_bone_ptr.descend_bones_ptrs.push(bpointer); } else m_tsr.copy(bpointer.tsr_local_rest, bpointer.tsr_bone_rest); bpointer.bone_index = i; bpointer.name = bone_name; m_tsr.multiply(bpointer.tsr_bone_rest, bpointer.tsr_basis, bpointer.tsr_bone_pose); } armobj.render.bone_pointers = bone_pointers; }
exports.get_bone_tsr = function(armobj, bone_name, get_pose_tail, use_bone_space, dest_tsr) { var render = armobj.render; var frame_factor = render.frame_factor; var bone_pointer = render.bone_pointers[bone_name]; var index = bone_pointer.bone_index; var tsr_local = bone_pointer.tsr_local_rest; var transcale = _vec4_tmp; var trans_before = render.trans_before; var trans_after = render.trans_after; var quats_before = render.quats_before; var quats_after = render.quats_after; var x = trans_before[4*index]; var y = trans_before[4*index+1]; var z = trans_before[4*index+2]; var s = trans_before[4*index+3]; var xn = trans_after[4*index]; var yn = trans_after[4*index+1]; var zn = trans_after[4*index+2]; var sn = trans_after[4*index+3]; transcale[0] = (1-frame_factor) * x + frame_factor * xn; transcale[1] = (1-frame_factor) * y + frame_factor * yn; transcale[2] = (1-frame_factor) * z + frame_factor * zn; transcale[3] = (1-frame_factor) * s + frame_factor * sn; var quat = _quat4_tmp; var quatn = _quat4_tmp2; quat[0] = quats_before[4*index]; quat[1] = quats_before[4*index+1]; quat[2] = quats_before[4*index+2]; quat[3] = quats_before[4*index+3]; quatn[0] = quats_after[4*index]; quatn[1] = quats_after[4*index+1]; quatn[2] = quats_after[4*index+2]; quatn[3] = quats_after[4*index+3]; m_quat.slerp(quat, quatn, frame_factor, quat); var tsr_bone = _tsr_tmp; m_tsr.set_transcale(transcale, tsr_bone); m_tsr.set_quat(quat, tsr_bone); if (get_pose_tail) { var tsr_local_tail = _tsr_tmp2; m_tsr.translate(tsr_local, bone_pointer.tail, tsr_local_tail); m_tsr.multiply(tsr_bone, tsr_local_tail, tsr_bone); } else m_tsr.multiply(tsr_bone, tsr_local, tsr_bone); if (use_bone_space) { var parent_bone_ptr = bone_pointer.parent_bone_ptr; if (parent_bone_ptr) { // move to bone space var tsr_par_local = parent_bone_ptr.tsr_local_pose; var inv_tsr_par_local = _tsr_tmp2; m_tsr.invert(tsr_par_local, inv_tsr_par_local); m_tsr.multiply(inv_tsr_par_local, tsr_bone, tsr_bone); } // calculate difference with rest pose tsr var tsr_bone_rest = bone_pointer.tsr_bone_rest; var inv_tsr_bone_rest = _tsr_tmp2; m_tsr.invert(tsr_bone_rest, inv_tsr_bone_rest); m_tsr.multiply(inv_tsr_bone_rest, tsr_bone, tsr_bone); } m_tsr.copy(tsr_bone, dest_tsr); }