function animate(obj, elapsed) { // not animatable if (!obj._anim) return; // update paused animation only if elapsed == 0 if (!(obj._anim.play || elapsed == 0)) return var render = obj._render; var cff = obj._anim.current_frame_float; var start = obj._anim.start; var length = obj._anim.length; var finish_callback; cff += elapsed * cfg_ani.framerate; if (cff >= start + length) { finish_callback = obj._anim.finish_callback; switch(obj._anim.behavior) { case AB_CYCLIC: cff = ((cff-start) % length) + start; break; case AB_FINISH_RESET: cff = start; stop(obj); break; case AB_FINISH_STOP: cff = start + length - 0.000001; stop(obj); break; } } obj._anim.current_frame_float = cff; obj._render.time = (cff - start) / cfg_ani.framerate; var anim_type = obj._anim.type; switch (anim_type) { case OBJ_ANIM_TYPE_ARMATURE: case OBJ_ANIM_TYPE_SKELETAL: var finfo = action_anim_finfo(obj._anim, cff, _frame_info_tmp); var frame = finfo[0]; var frame_next = finfo[1]; var frame_factor = finfo[2]; var trans = obj._anim.trans; var quats = obj._anim.quats; render.quats_before = quats[frame]; render.quats_after = quats[frame_next]; render.trans_before = trans[frame]; render.trans_after = trans[frame_next]; render.frame_factor = frame_factor; if (anim_type === OBJ_ANIM_TYPE_ARMATURE) m_trans.update_transform(obj); break; case OBJ_ANIM_TYPE_OBJECT: var finfo = action_anim_finfo(obj._anim, cff, _frame_info_tmp); var trans = get_anim_translation(obj, 0, finfo, _vec3_tmp); var quat = get_anim_rotation(obj, 0, finfo, _quat4_tmp); var scale = get_anim_scale(obj, 0, finfo); if (obj._anim.trans_smooth_period) { var trans_old = _vec3_tmp2; m_trans.get_translation(obj, trans_old); m_util.smooth_v(trans, trans_old, elapsed, obj._anim.trans_smooth_period, trans); } if (obj._anim.quat_smooth_period) { var quat_old = _quat4_tmp2; m_trans.get_rotation(obj, quat_old); m_util.smooth_q(quat, quat_old, elapsed, obj._anim.quat_smooth_period, quat); } m_trans.set_translation(obj, trans); m_trans.set_rotation(obj, quat); m_trans.set_scale(obj, scale); m_trans.update_transform(obj); m_phy.sync_transform(obj); break; case OBJ_ANIM_TYPE_VERTEX: vertex_anim_finfo(obj._anim, cff, _frame_info_tmp); var finfo = _frame_info_tmp; render.va_frame = finfo[0]; render.va_frame_factor = finfo[2]; break; case OBJ_ANIM_TYPE_SOUND: var finfo = action_anim_finfo(obj._anim, cff, _frame_info_tmp); var fc = finfo[0]; var fn = finfo[1]; var ff = finfo[2]; if (obj._anim.volume) { var volume = (1-ff) * obj._anim.volume[fc] + ff * obj._anim.volume[fn]; m_sfx.set_volume(obj, volume); } if (obj._anim.pitch) { var pitch = (1-ff) * obj._anim.pitch[fc] + ff * obj._anim.pitch[fn]; m_sfx.playrate(obj, pitch); } break; case OBJ_ANIM_TYPE_STATIC: // do nothing break; default: throw("Unknown animation type:" + anim_type); break; } if (finish_callback) finish_callback(obj); }
function update_object(obj) { var is_dynamic = obj_is_dynamic(obj); obj._is_dynamic = is_dynamic; if (obj["type"] === "MESH") var render_type = is_dynamic ? "DYNAMIC" : "STATIC"; else var render_type = obj["type"]; obj._render = create_render(render_type); obj._constraint = null; obj._descends = []; if (!obj._dg_parent) obj._dg_parent = null; var render = obj._render; var pos = obj["location"]; var scale = obj["scale"][0]; var rot = _quat4_tmp; m_util.quat_bpy_b4w(obj["rotation_quaternion"], rot); m_trans.set_translation(obj, pos); m_trans.set_rotation(obj, rot); m_trans.set_scale(obj, scale); switch (obj["type"]) { case "ARMATURE": var pose_bones = obj["pose"]["bones"]; for (var i = 0; i < pose_bones.length; i++) { var pose_bone = pose_bones[i]; var arm_bone = pose_bone["bone"]; 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 = new Float32Array(3); 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); pose_bone._tail = tail; // include current bone to chain with its parents pose_bone._chain = [pose_bone].concat(pose_bone["parent_recursive"]); pose_bone._tsr_local = m_tsr.from_mat4(mat_loc, m_tsr.create()); pose_bone._tsr_basis = m_tsr.from_mat4(mat_bas, m_tsr.create()); pose_bone._tsr_channel_cache = m_tsr.create(); pose_bone._tsr_channel_cache_valid = false; } var bone_pointers = m_anim.calc_armature_bone_pointers(obj); render.bone_pointers = bone_pointers; var pose_data = m_anim.calc_pose_data(obj, bone_pointers); render.quats_before = pose_data.quats; render.quats_after = pose_data.quats; render.trans_before = pose_data.trans; render.trans_after = pose_data.trans; render.frame_factor = 0; break; case "MESH": render.selectable = cfg_def.all_objs_selectable || obj["b4w_selectable"]; render.origin_selectable = obj["b4w_selectable"]; render.glow_anim_settings = { glow_duration: obj["b4w_glow_settings"]["glow_duration"], glow_period: obj["b4w_glow_settings"]["glow_period"], glow_relapses: obj["b4w_glow_settings"]["glow_relapses"] }; if (render.selectable) { // assign color id obj._color_id = m_util.gen_color_id(_color_id_counter); _color_id_counter++; } prepare_skinning_info(obj); prepare_vertex_anim(obj); // apply pose if any var armobj = m_anim.get_first_armature_object(obj); if (armobj) { var bone_pointers = obj._render.bone_pointers; var pose_data = m_anim.calc_pose_data(armobj, bone_pointers); render.quats_before = pose_data.quats; render.quats_after = pose_data.quats; render.trans_before = pose_data.trans; render.trans_after = pose_data.trans; render.frame_factor = 0; } obj._batches = []; render.shadow_cast = obj["b4w_shadow_cast"]; render.shadow_receive = obj["b4w_shadow_receive"]; render.shadow_cast_only = obj["b4w_shadow_cast_only"] && render.shadow_cast; render.reflexible = obj["b4w_reflexible"]; render.reflexible_only = obj["b4w_reflexible_only"] && render.reflexible; render.reflective = obj["b4w_reflective"]; render.caustics = obj["b4w_caustics"]; render.wind_bending = obj["b4w_wind_bending"]; render.wind_bending_angle = obj["b4w_wind_bending_angle"]; var amp = m_batch.wb_angle_to_amp(obj["b4w_wind_bending_angle"], m_batch.bb_bpy_to_b4w(obj["data"]["b4w_bounding_box"]), obj["scale"][0]); render.wind_bending_amp = amp; render.wind_bending_freq = obj["b4w_wind_bending_freq"]; render.detail_bending_freq = obj["b4w_detail_bending_freq"]; render.detail_bending_amp = obj["b4w_detail_bending_amp"]; render.branch_bending_amp = obj["b4w_branch_bending_amp"]; render.hide = false; render.main_bend_col = obj["b4w_main_bend_stiffness_col"]; var bnd_st = obj["b4w_detail_bend_colors"]; render.detail_bend_col = {}; render.detail_bend_col.leaves_stiffness = bnd_st["leaves_stiffness_col"]; render.detail_bend_col.leaves_phase = bnd_st["leaves_phase_col"]; render.detail_bend_col.overall_stiffness = bnd_st["overall_stiffness_col"]; render.do_not_cull = obj["b4w_do_not_cull"]; render.disable_fogging = obj["b4w_disable_fogging"]; render.dynamic_geometry = obj["b4w_dynamic_geometry"]; // assign params for object (bounding) physics simulation // it seams BGE uses first material to get physics param var first_mat = first_mesh_material(obj); render.friction = first_mat["physics"]["friction"]; render.elasticity = first_mat["physics"]["elasticity"]; render.lod_dist_min = 0; render.lod_dist_max = 10000; render.lod_transition_ratio = obj["b4w_lod_transition"]; render.last_lod = true; break; case "CAMERA": m_cam.camera_object_to_camera(obj); m_cam.assign_boundings(obj); break; case "LAMP": m_lights.lamp_to_light(obj); break; case "CURVE": var spline = m_curve.create_spline(obj); if (spline) obj._spline = spline; break; case "SPEAKER": break; case "EMPTY": // NOTE: center = 1/2 height var bb = m_bounds.zero_bounding_box(); render.bb_local = bb; var bs = m_bounds.zero_bounding_sphere(); render.bs_local = bs; break; default: break; } // NOTE: temporary disable armature parenting if (obj["parent"] && obj["parent_type"] == "OBJECT" && obj["parent"]["type"] != "ARMATURE") { var trans = render.trans; var quat = render.quat; var scale = render.scale; m_cons.append_stiff_obj(obj, obj["parent"], trans, quat, scale); } else if (obj["parent"] && obj["parent_type"] == "BONE" && obj["parent"]["type"] == "ARMATURE") { var trans = render.trans; var quat = render.quat; m_cons.append_stiff_bone(obj, obj["parent"], obj["parent_bone"], trans, quat); } else if (obj._dg_parent && obj._dg_parent["b4w_group_relative"]) { // get offset from render before child-of constraint being applied var offset = m_tsr.create_sep(render.trans, render.scale, render.quat); m_cons.append_child_of(obj, obj._dg_parent, offset); } else if (obj._dg_parent && !obj._dg_parent["b4w_group_relative"]) { m_trans.update_transform(obj); // to get world matrix var wm = render.world_matrix; m_mat4.multiply(obj._dg_parent._render.world_matrix, wm, wm); var trans = m_util.matrix_to_trans(wm); var scale = m_util.matrix_to_scale(wm); var quat = m_util.matrix_to_quat(wm); m_trans.set_translation(obj, trans); m_trans.set_rotation(obj, quat); m_trans.set_scale(obj, scale); } // store force field if (obj["field"]) { render.force_strength = obj["field"]["strength"]; m_scenes.update_force(obj); } // make links from group objects to their parent var dupli_group = obj["dupli_group"]; if (dupli_group) { var dg_objects = dupli_group["objects"]; for (var i = 0; i < dg_objects.length; i++) { var dg_obj = dg_objects[i]; dg_obj._dg_parent = obj; } } render.use_collision_compound = obj["game"]["use_collision_compound"]; render.physics_type = obj["game"]["physics_type"]; m_trans.update_transform(obj); }