exports.get_rotation = function(obj, dest) { if (m_cons.get_type(obj) == m_cons.CONS_TYPE_CHILD_OF) { var offset = m_cons.get_child_of_offset(obj); m_quat.copy(m_tsr.get_quat_view(offset), dest); } else { m_quat.copy(obj._render.quat, dest); } }
var rotate_cb = function(obj, id, pulse) { if (pulse > 0) { var curr_angles = m_ctl.get_sensor_payload(obj, id, 0); if (m_cam.is_eye_camera(obj)) { var alpha = curr_angles[2]; var beta = curr_angles[1]; var gamma = curr_angles[0]; var quaternion = _quat_tmp; var c1 = Math.cos(alpha / 2); var c2 = Math.cos(beta / 2); var c3 = Math.cos(gamma / 2); var s1 = Math.sin(alpha / 2); var s2 = Math.sin(beta / 2); var s3 = Math.sin(gamma / 2); quaternion[0] = c1 * s2 * c3 - s1 * c2 * s3; quaternion[1] = c1 * c2 * s3 + s1 * s2 * c3; quaternion[2] = s1 * c2 * c3 + c1 * s2 * s3; quaternion[3] = c1 * c2 * c3 - s1 * s2 * s3; var orientation = Math.PI * window.orientation / 180; var screen_quat = m_quat.setAxisAngle(m_util.AXIS_Z, -orientation, _quat_tmp2); quaternion = m_quat.multiply(quaternion, screen_quat, _quat_tmp); var quat = m_quat.setAxisAngle(m_util.AXIS_X, Math.PI / 2, _quat_tmp2); quaternion = m_quat.multiply(quaternion, quat, _quat_tmp); if (save_angles) { m_quat.copy(quaternion, _last_gyro_quat); save_angles = false; } else { var last_gyro_inv_quat = m_quat.invert(_last_gyro_quat, _last_gyro_quat); var cam_quat = m_trans.get_rotation(obj, _quat_tmp2); var clear_cam_quat = m_quat.multiply(cam_quat, last_gyro_inv_quat, _quat_tmp2); var new_cam_quat = m_quat.multiply(clear_cam_quat, quaternion, _quat_tmp2); var up_axis = m_vec3.transformQuat(m_util.AXIS_MZ, new_cam_quat, _vec3_tmp); m_cam.set_vertical_axis(obj, up_axis); m_trans.set_rotation_v(obj, new_cam_quat); m_quat.copy(quaternion, _last_gyro_quat); } } } }
exports.append_semi_stiff_cam_obj = function(obj, obj_parent, offset, rotation_offset, clamp_left, clamp_right, clamp_up, clamp_down) { var cons = init_cons(CONS_TYPE_SEMI_STIFF_CAM_OBJ); var quat = obj._render.quat; var p_quat = obj_parent._render.quat; // link to parent object cons.obj_parent = obj_parent; cons.offset = new Float32Array(offset); cons.parent_prev_rotation = new Float32Array(p_quat); cons.clamp_left = clamp_left; cons.clamp_right = clamp_right; cons.clamp_up = clamp_up; cons.clamp_down = clamp_down; // override initial rotation for object if (rotation_offset) { m_quat.copy(rotation_offset, quat); m_quat.multiply(p_quat, quat, quat); } apply_cons(obj, cons); update_cons(obj, cons, 0); }
function hor_rot(ev_track, cur_dir, elapsed, new_rot_q, new_hor_dir) { var cur_rot_q = _quat4_tmp_2; var cur_hor_dir = _vec3_tmp_4; m_trans.get_rotation_quat(ev_track.collider, cur_rot_q); m_vec3.transformQuat(m_util.AXIS_Z, cur_rot_q, cur_dir); cur_hor_dir[0] = cur_dir[0]; cur_hor_dir[1] = 0; cur_hor_dir[2] = cur_dir[2]; m_vec3.normalize(cur_hor_dir, cur_hor_dir); var vec_dot = m_vec3.dot(cur_hor_dir, new_hor_dir); var angle_to_turn = Math.acos(vec_dot); var angle_ratio = Math.abs(angle_to_turn) / Math.PI; var slerp = elapsed / angle_ratio * ev_track.rot_speed * ev_track.rotation_mult; m_quat.rotationTo(cur_hor_dir, new_hor_dir, new_rot_q); m_quat.rotationTo(m_util.AXIS_Z, cur_hor_dir, cur_rot_q); if (Math.abs(vec_dot) >= 1) { m_quat.copy(cur_rot_q, new_rot_q); return; } m_quat.multiply(new_rot_q, cur_rot_q, new_rot_q); m_quat.slerp(cur_rot_q, new_rot_q, Math.min(slerp, 1), new_rot_q); }
exports.append_semi_stiff_cam_obj = function(obj, obj_parent, offset, rotation_offset, clamp_left, clamp_right, clamp_up, clamp_down) { var cons = init_cons(CONS_TYPE_SEMI_STIFF_CAM_OBJ); var quat = obj._render.quat; var p_quat = obj_parent._render.quat; // link to parent object cons.obj_parent = obj_parent; cons.offset = new Float32Array(offset); cons.parent_prev_rotation = new Float32Array(p_quat); cons.clamp_left = m_util.angle_wrap_0_2pi(clamp_left); cons.clamp_right = m_util.angle_wrap_0_2pi(clamp_right); cons.clamp_up = m_util.angle_wrap_periodic(clamp_up, -Math.PI, Math.PI); cons.clamp_down = m_util.angle_wrap_periodic(clamp_down, -Math.PI, Math.PI); if (rotation_offset) { cons.rotation_offset = new Float32Array(rotation_offset); // override initial rotation for object m_quat.copy(rotation_offset, quat); m_quat.multiply(p_quat, quat, quat); } else cons.rotation_offset = m_quat.create(); apply_cons(obj, cons); update_cons(obj, cons, 0); }
/** * @methodOf camera */ function set_view(cam, camobj) { var trans = camobj._render.trans; var quat = camobj._render.quat; var wm = _mat4_tmp; m_mat4.rotateX(camobj._render.world_matrix, -Math.PI/2, wm); m_mat4.invert(wm, cam.view_matrix); if (cam.reflection_plane) { reflect_view_matrix(cam); reflect_proj_matrix(cam); } var x = cam.view_matrix[12]; var y = cam.view_matrix[13]; var z = cam.view_matrix[14]; if (cam.type == exports.TYPE_STEREO_LEFT) cam.view_matrix[12] += cam.stereo_eye_dist/2; else if (cam.type == exports.TYPE_STEREO_RIGHT) cam.view_matrix[12] -= cam.stereo_eye_dist/2; // update view projection matrix m_mat4.multiply(cam.proj_matrix, cam.view_matrix, cam.view_proj_matrix); calc_sky_vp_inverse(cam); m_vec3.copy(cam.eye, cam.eye_last); m_vec3.copy(trans, cam.eye); m_quat.copy(quat, cam.quat); }
var move_cam_cb = function(obj, id, pulse) { var cam_obj = m_scenes.get_active_camera(); if (!cam_obj) return; if (pulse > 0) { // NOTE: init part if (!updated_eye_data) { var hmd_left_fov = get_fov("left", _vec4_tmp); var hmd_right_fov = get_fov("right", _vec4_tmp2); if (hmd_left_fov && hmd_left_fov) m_cam.set_hmd_fov(cam_obj, hmd_left_fov, hmd_right_fov); var eye_distance = get_eye_distance(); if (eye_distance) m_cam.set_eye_distance(cam_obj, eye_distance); var hmd_params = {}; if (_hmd_device.deviceName.toLowerCase().indexOf("oculus") !== -1) var hmd_name = "oculus"; else var hmd_name = "default"; hmd_params.distortion_coefs = [ _devices_params[hmd_name]["distortion_coefs"][0], _devices_params[hmd_name]["distortion_coefs"][1] ]; hmd_params.chromatic_aberration_coefs = [ _devices_params[hmd_name]["chromatic_aberration_coefs"][0], _devices_params[hmd_name]["chromatic_aberration_coefs"][1], _devices_params[hmd_name]["chromatic_aberration_coefs"][2], _devices_params[hmd_name]["chromatic_aberration_coefs"][3] ]; hmd_params.distortion_scale = _devices_params[hmd_name]["distortion_scale"]; // TODO: set distortion_offset hmd_params.distortion_offset = 0.0; hmd_params.enable_hmd_stereo = true; m_scenes.set_hmd_params(hmd_params); var canvas_container_elem = m_cont.get_container(); var ccw = canvas_container_elem.clientWidth; var cch = canvas_container_elem.clientHeight; m_cont.resize(ccw, cch, true); updated_eye_data = true; _last_cam_quat = m_trans.get_rotation(cam_obj, _last_cam_quat); reset_hmd(); } // NOTE: It is executed every frame. // uses _vec3_tmp, _vec3_tmp2, _vec3_tmp3, _quat_tmp, _quat_tmp2 if (m_cam.is_eye_camera(cam_obj)) { if (control_type == HMD_ALL_AXES_MOUSE_NONE) { var hmd_quat = get_sensor_orientation(_quat_tmp); if (hmd_quat) { var quat = m_quat.setAxisAngle(m_util.AXIS_X, Math.PI / 2, _quat_tmp2); m_quat.normalize(quat, quat); hmd_quat = m_quat.multiply(hmd_quat, quat, _quat_tmp); var up_axis = m_vec3.transformQuat(m_util.AXIS_Z, hmd_quat, _vec3_tmp); m_cam.set_vertical_axis(cam_obj, up_axis); m_trans.set_rotation_v(cam_obj, hmd_quat); } } else if (control_type == HMD_ROLL_PITCH_MOUSE_YAW || control_type == HMD_ALL_AXES_MOUSE_YAW) { var hmd_quat = get_sensor_orientation(_quat_tmp); if (hmd_quat) { // NOTE: hmd_quat to WEBGL axis orientation var quat = m_quat.setAxisAngle(m_util.AXIS_X, Math.PI / 2, _quat_tmp2); m_quat.normalize(quat, quat); hmd_quat = m_quat.multiply(hmd_quat, quat, _quat_tmp); var cam_quat = m_trans.get_rotation(cam_obj, _quat_tmp2); var inv_cam_quat = m_quat.invert(cam_quat, _quat_tmp2); var diff_cam_quat = m_quat.multiply(_last_cam_quat, inv_cam_quat, _quat_tmp2); var cur_vertical_axis = m_cam.get_vertical_axis(cam_obj, _vec3_tmp); if (Math.abs(cur_vertical_axis[2]) < Math.PI / 4) var first_horiz_vec = m_vec3.cross(cur_vertical_axis, m_util.AXIS_Z, _vec3_tmp2); else if (Math.abs(cur_vertical_axis[1]) < Math.PI / 4) var first_horiz_vec = m_vec3.cross(cur_vertical_axis, m_util.AXIS_Y, _vec3_tmp2); m_vec3.normalize(first_horiz_vec, first_horiz_vec); var rotated_first_horiz_vec = m_vec3.transformQuat( first_horiz_vec, diff_cam_quat, _vec3_tmp3); var vertical_coef = m_vec3.dot(cur_vertical_axis, rotated_first_horiz_vec); var second_horiz_vec = m_vec3.scaleAndAdd(rotated_first_horiz_vec, cur_vertical_axis, -vertical_coef, _vec3_tmp3); m_vec3.normalize(second_horiz_vec, second_horiz_vec); var sign_horiz_vec = m_vec3.cross(cur_vertical_axis, first_horiz_vec, _vec3_tmp); var abs_yaw_angle = Math.acos(m_util.clamp( m_vec3.dot(first_horiz_vec, second_horiz_vec), 0, 1)); var sign_yaw_angle = m_util.sign(m_vec3.dot( second_horiz_vec, sign_horiz_vec)); var diff_yaw_cam_angle = abs_yaw_angle * sign_yaw_angle; _yaw_cam_angle += diff_yaw_cam_angle; var yaw_cam_quat = m_quat.setAxisAngle(m_util.AXIS_Y, -_yaw_cam_angle, _quat_tmp2); if (control_type == HMD_ALL_AXES_MOUSE_YAW) { var new_cam_quat = m_quat.multiply(yaw_cam_quat, hmd_quat, _quat_tmp); } else { var yaw_hmd_quat = m_util.quat_project(hmd_quat, m_util.AXIS_MY, m_util.AXIS_Y, m_util.AXIS_MZ, _quat_tmp3); var yaw_hmd_inv_quat = m_quat.invert(yaw_hmd_quat, _quat_tmp3); var vertical_hmd_quat = m_quat.multiply( yaw_hmd_inv_quat, hmd_quat, _quat_tmp3); var new_cam_quat = m_quat.multiply(yaw_cam_quat, vertical_hmd_quat, _quat_tmp); } var up_axis = m_vec3.transformQuat(m_util.AXIS_Z, new_cam_quat, _vec3_tmp); m_cam.set_vertical_axis(cam_obj, up_axis); m_trans.set_rotation_v(cam_obj, new_cam_quat); m_quat.copy(new_cam_quat, _last_cam_quat) } } } } }
function update_sensor(sensor, timeline, elapsed) { if (!elapsed) return; switch (sensor.type) { case ST_MOTION: var obj = sensor.source_object; var trans = obj._render.trans; var quat = obj._render.quat; var dist = m_vec3.dist(sensor.trans_last, trans); var quat_temp = sensor.quat_temp; m_quat.invert(sensor.quat_last, quat_temp); m_quat.multiply(quat, quat_temp, quat_temp); m_quat.normalize(quat_temp, quat_temp); var angle = Math.abs(2 * Math.acos(quat_temp[3])); var linear_vel = dist / elapsed; sensor.avg_linear_vel = m_util.smooth(linear_vel, sensor.avg_linear_vel, elapsed, SENSOR_SMOOTH_PERIOD); sensor.payload[0] = linear_vel; var angular_vel = angle / elapsed; sensor.avg_angular_vel = m_util.smooth(angular_vel, sensor.avg_angular_vel, elapsed, SENSOR_SMOOTH_PERIOD); sensor.payload[1] = angular_vel; if (sensor.avg_linear_vel >= sensor.threshold || sensor.avg_angular_vel >= sensor.rotation_threshold) sensor_set_value(sensor, 1); else sensor_set_value(sensor, 0); m_vec3.copy(trans, sensor.trans_last); m_quat.copy(quat, sensor.quat_last); sensor.time_last = timeline; break; case ST_V_VELOCITY: var obj = sensor.source_object; var trans = obj._render.trans; var vel = Math.abs(trans[1] - sensor.trans_last[1]) / elapsed; sensor.avg_vertical_vel = m_util.smooth(vel, sensor.avg_vertical_vel, elapsed, SENSOR_SMOOTH_PERIOD); sensor.payload = vel; if (sensor.avg_vertical_vel >= sensor.threshold) sensor_set_value(sensor, 1); else sensor_set_value(sensor, 0); m_vec3.copy(trans, sensor.trans_last); sensor.time_last = timeline; break; case ST_TIMER: if ((timeline - sensor.time_last) >= sensor.period) { sensor_set_value(sensor, 1); sensor.time_last = timeline; } break; case ST_ELAPSED: if (!sensor.time_last) { sensor.time_last = timeline; } sensor_set_value(sensor, timeline - sensor.time_last); sensor.time_last = timeline; break; case ST_TIMELINE: sensor_set_value(sensor, timeline); 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 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); } }