/* by korenkonder GitHub/GitLab: korenkonder */ #include "bone_data.hpp" ExNodeBlock_vtbl* ExClothBlock_vftable = (ExNodeBlock_vtbl*)0x0000000140A82FF0; ExNodeBlock_vtbl* ExOsageBlock_vftable = (ExNodeBlock_vtbl*)0x0000000140A82F88; ExNodeBlock_vtbl* ExNodeBlock_vftable = (ExNodeBlock_vtbl*)0x0000000140A82DC8; static void* (*operator_new)(size_t) = (void* (*)(size_t))0x000000014084530C; static void(*operator_delete)(void*) = (void(*)(void*))0x0000000140845378; static const float_t get_osage_gravity_const() { return 0.00299444468691945f; } static void skin_param_hinge_limit(skin_param_hinge* hinge) { hinge->ymin = max_def(hinge->ymin, -179.0f) * DEG_TO_RAD_FLOAT; hinge->ymax = min_def(hinge->ymax, 179.0f) * DEG_TO_RAD_FLOAT; hinge->zmin = max_def(hinge->zmin, -179.0f) * DEG_TO_RAD_FLOAT; hinge->zmax = min_def(hinge->zmax, 179.0f) * DEG_TO_RAD_FLOAT; } static void rob_osage_node_data_init(rob_osage_node_data *node_data) { node_data->force = 0.0f; node_data->boc.end = node_data->boc.begin; node_data->skp_osg_node.coli_r = 0.0f; node_data->skp_osg_node.weight = 1.0f; node_data->skp_osg_node.inertial_cancel = 0.0f; node_data->skp_osg_node.hinge = { -90.0f, 90.0f, -90.0f, 90.0f }; skin_param_hinge_limit(&node_data->skp_osg_node.hinge); node_data->normal_ref.field_0 = 0; node_data->normal_ref.n = 0; node_data->normal_ref.u = 0; node_data->normal_ref.d = 0; node_data->normal_ref.l = 0; node_data->normal_ref.r = 0; node_data->normal_ref.mat = mat4_identity; } static void rob_osage_node_init(rob_osage_node* node) { void (*sub_14021DCC0)(vector_old_opd_vec3_data * vec, size_t size) = (void (*)(vector_old_opd_vec3_data*, size_t))0x000000014021DCC0; node->length = 0.0f; node->trans = 0.0f; node->trans_orig = 0.0f; node->trans_diff = 0.0f; node->field_28 = 0.0f; node->child_length = 0.0f; node->bone_node_ptr = 0; node->bone_node_mat = 0; node->sibling_node = 0; node->distance = 0.0f; node->field_94 = 0.0f; node->reset_data.trans = 0.0f; node->reset_data.trans_diff = 0.0f; node->reset_data.rotation = 0.0f; node->reset_data.length = 0.0f; node->field_C8 = 0.0f; node->field_CC = 1.0f; node->external_force = 0.0f; node->force = 1.0f; rob_osage_node_data_init(&node->data); node->data_ptr = &node->data; node->opd_data.end = node->opd_data.begin; sub_14021DCC0(&node->opd_data, 3); node->mat = mat4_null; } static void skin_param_init(skin_param* skp) { } static void rob_osage_init(rob_osage* rob_osg) { void (*sub_140216750)(tree_motion_reset_data * a1, tree_motion_reset_data_node * a2) = (void (*)(tree_motion_reset_data*, tree_motion_reset_data_node*))0x0000000140216750; void (*vector_old_rob_osage_node_clear)(vector_old_rob_osage_node * vec, rob_osage_node * begin, rob_osage_node * end) = (void (*)(vector_old_rob_osage_node*, rob_osage_node*, rob_osage_node*))0x00000001404817E0; vector_old_rob_osage_node_clear(&rob_osg->nodes, rob_osg->nodes.begin, rob_osg->nodes.end); rob_osg->nodes.end = rob_osg->nodes.begin; rob_osage_node_init(&rob_osg->node); rob_osg->wind_direction = 0.0f; rob_osg->field_1EB4 = 0.0f; rob_osg->yz_order = 0; rob_osg->field_2A0 = true; sub_140216750(&rob_osg->motion_reset_data, rob_osg->motion_reset_data.head->parent); rob_osg->motion_reset_data.head->parent = rob_osg->motion_reset_data.head; rob_osg->motion_reset_data.head->left = rob_osg->motion_reset_data.head; rob_osg->motion_reset_data.head->right = rob_osg->motion_reset_data.head; rob_osg->motion_reset_data.size = 0; rob_osg->move_cancel = 0.0f; rob_osg->field_1F0C = false; rob_osg->osage_reset = false; rob_osg->field_1F0E = false; rob_osg->ring.ring_height = -1000.0f; rob_osg->ring.ring_rectangle_x = 0.0f; rob_osg->ring.ring_rectangle_y = 0.0f; rob_osg->ring.ring_rectangle_width = 0.0f; rob_osg->ring.ring_out_height = -1000.0f; rob_osg->ring.field_18 = 0; rob_osg->ring.ring_rectangle_height = 0.0f; rob_osg->ring.coli.end = rob_osg->ring.coli.begin; rob_osg->ring.skp_root_coli.end = rob_osg->ring.skp_root_coli.begin; rob_osg->field_1F0F = false; skin_param_init(&rob_osg->skin_param); rob_osg->skin_param_ptr = &rob_osg->skin_param; rob_osg->osage_setting.parts = ROB_OSAGE_PARTS_NONE; rob_osg->osage_setting.exf = 0; rob_osg->reset_data_list = 0; rob_osg->field_2A4 = 0.0f; rob_osg->field_2A1 = 0; rob_osg->set_external_force = false; rob_osg->external_force = 0.0f; rob_osg->parent_mat_ptr = 0; rob_osg->parent_mat = mat4_null; } static void rob_osage_node_free(rob_osage_node* node) { if (node->opd_data.begin) { operator_delete(node->opd_data.begin); node->opd_data.begin = 0; node->opd_data.end = 0; node->opd_data.capacity_end = 0; } if (node->data.boc.begin) { operator_delete(node->data.boc.begin); node->data.boc.begin = 0; node->data.boc.end = 0; node->data.boc.capacity_end = 0; } } static void rob_osage_free(rob_osage* rob_osg) { void (*sub_14021BEF0)(tree_motion_reset_data * a1, tree_motion_reset_data_node * *a2, tree_motion_reset_data_node * a3, tree_motion_reset_data_node * a4) = (void (*)(tree_motion_reset_data*, tree_motion_reset_data_node**, tree_motion_reset_data_node*, tree_motion_reset_data_node*))0x000000014021BEF0; void (*vector_old_rob_osage_node_clear)(vector_old_rob_osage_node * vec, rob_osage_node * begin, rob_osage_node * end) = (void (*)(vector_old_rob_osage_node*, rob_osage_node*, rob_osage_node*))0x00000001404817E0; rob_osage_init(rob_osg); tree_motion_reset_data_node* v6; sub_14021BEF0(&rob_osg->motion_reset_data, &v6, rob_osg->motion_reset_data.head->left, rob_osg->motion_reset_data.head); operator_delete(rob_osg->motion_reset_data.head); if (rob_osg->ring.skp_root_coli.begin) { operator_delete(rob_osg->ring.skp_root_coli.begin); rob_osg->ring.skp_root_coli.begin = 0; rob_osg->ring.skp_root_coli.end = 0; rob_osg->ring.skp_root_coli.capacity_end = 0; } if (rob_osg->ring.coli.begin) { operator_delete(rob_osg->ring.coli.begin); rob_osg->ring.coli.begin = 0; rob_osg->ring.coli.end = 0; rob_osg->ring.coli.capacity_end = 0; } if (rob_osg->skin_param.coli.begin) { operator_delete(rob_osg->skin_param.coli.begin); rob_osg->skin_param.coli.begin = 0; rob_osg->skin_param.coli.end = 0; rob_osg->skin_param.coli.capacity_end = 0; } rob_osage_node_free(&rob_osg->node); if (rob_osg->nodes.begin) { vector_old_rob_osage_node_clear(&rob_osg->nodes, rob_osg->nodes.begin, rob_osg->nodes.end); operator_delete(rob_osg->nodes.begin); rob_osg->nodes.begin = 0; rob_osg->nodes.end = 0; rob_osg->nodes.capacity_end = 0; } } void ExNodeBlock__Field_10(ExNodeBlock* node) { node->field_59 = false; } ExOsageBlock* ExOsageBlock__Dispose(ExOsageBlock* osg, bool dispose) { osg->base.__vftable = ExOsageBlock_vftable; ExOsageBlock__Reset(osg); rob_osage_free(&osg->rob); osg->base.__vftable = ExNodeBlock_vftable; if (osg->base.parent_name.capacity > 0x0F) operator_delete(osg->base.parent_name.ptr); osg->base.parent_name = string_empty; if (dispose) operator_delete(osg); return osg; } void ExOsageBlock__Init(ExOsageBlock* osg) { osg->base.__vftable->Reset(&osg->base); } static void sub_14047EE90(rob_osage* rob_osg, mat4* mat) { if (rob_osg->reset_data_list) { list_RobOsageNodeResetData_node* v5 = rob_osg->reset_data_list->head->next; for (rob_osage_node* v6 = rob_osg->nodes.begin + 1; v6 != rob_osg->nodes.end; v6++) { v6->reset_data = v5->value; v5 = v5->next; } rob_osg->reset_data_list = 0; } mat4 temp; mat4_transpose(mat, &temp); for (rob_osage_node* v9 = rob_osg->nodes.begin + 1; v9 != rob_osg->nodes.end; v9++) { mat4_mult_vec3(&temp, &v9->reset_data.trans_diff, &v9->trans_diff); mat4_mult_vec3_trans(&temp, &v9->reset_data.trans, &v9->trans); } rob_osg->parent_mat = *rob_osg->parent_mat_ptr; } static void sub_14047F110(rob_osage* rob_osg, mat4* mat, vec3* parent_scale, bool init_rot) { mat4_transpose(mat, mat); vec3 position = rob_osg->exp_data.position * *parent_scale; mat4_translate_mult(mat, &position, mat); mat4_rotate_mult(mat, &rob_osg->exp_data.rotation, mat); skin_param* skin_param = rob_osg->skin_param_ptr; vec3 rot = skin_param->rot; if (init_rot) rot = skin_param->init_rot + rot; mat4_rotate_mult(mat, &rot, mat); mat4_transpose(mat, mat); } static bool sub_140482FF0(mat4* mat, vec3* trans, skin_param_hinge* hinge, vec3* rot, int32_t* yz_order) { bool clipped = false; float_t z_rot; float_t y_rot; mat4_transpose(mat, mat); if (*yz_order == 1) { y_rot = atan2f(-trans->z, trans->x); z_rot = atan2f(trans->y, sqrtf(trans->x * trans->x + trans->z * trans->z)); if (hinge) { if (y_rot > hinge->ymax) { y_rot = hinge->ymax; clipped = true; } if (y_rot < hinge->ymin) { y_rot = hinge->ymin; clipped = true; } if (z_rot > hinge->zmax) { z_rot = hinge->zmax; clipped = true; } if (z_rot < hinge->zmin) { z_rot = hinge->zmin; clipped = true; } } mat4_rotate_y_mult(mat, y_rot, mat); mat4_rotate_z_mult(mat, z_rot, mat); } else { z_rot = atan2f(trans->y, trans->x); y_rot = atan2f(-trans->z, sqrtf(trans->x * trans->x + trans->y * trans->y)); if (hinge) { if (y_rot > hinge->ymax) { y_rot = hinge->ymax; clipped = true; } if (y_rot < hinge->ymin) { y_rot = hinge->ymin; clipped = true; } if (z_rot > hinge->zmax) { z_rot = hinge->zmax; clipped = true; } if (z_rot < hinge->zmin) { z_rot = hinge->zmin; clipped = true; } } mat4_rotate_z_mult(mat, z_rot, mat); mat4_rotate_y_mult(mat, y_rot, mat); } mat4_transpose(mat, mat); if (rot) { rot->y = y_rot; rot->z = z_rot; } return clipped; } static void sub_1404803B0(rob_osage* rob_osg, mat4* mat, vec3* parent_scale, bool a4) { mat4 v47 = *mat; vec3 v45; vec3_mult(rob_osg->exp_data.position, *parent_scale, v45); mat4_transpose(&v47, &v47); mat4_mult_vec3_trans(&v47, &v45, &rob_osg->nodes.begin[0].trans); if (rob_osg->osage_reset && !rob_osg->field_1F0E) { rob_osg->field_1F0E = true; sub_14047EE90(rob_osg, mat); } if (!rob_osg->field_1F0C) { rob_osg->field_1F0C = true; float_t move_cancel = rob_osg->skin_param_ptr->move_cancel; if (rob_osg->move_cancel == 1.0f) move_cancel = 1.0f; if (move_cancel < 0.0f) move_cancel = rob_osg->move_cancel; if (move_cancel > 0.0f) for (rob_osage_node* v19 = rob_osg->nodes.begin + 1; v19 != rob_osg->nodes.end; v19++) { mat4 parent_mat; vec3 v46; mat4_transpose(&rob_osg->parent_mat, &parent_mat); mat4_mult_vec3_inv_trans(&parent_mat, &v19->trans, &v46); mat4_transpose(rob_osg->parent_mat_ptr, &parent_mat); mat4_mult_vec3_trans(&parent_mat, &v46, &v46); vec3_sub(v46, v19->trans, v46); vec3_mult_scalar(v46, move_cancel, v46); vec3_add(v19->trans, v46, v19->trans); } } if (a4) { mat4_transpose(&v47, &v47); sub_14047F110(rob_osg, &v47, parent_scale, 0); *rob_osg->nodes.begin[0].bone_node_mat = v47; mat4_transpose(&v47, &v47); for (rob_osage_node* v29 = rob_osg->nodes.begin, *v30 = rob_osg->nodes.begin + 1; v30 != rob_osg->nodes.end; v29++, v30++) { vec3 v46; mat4_mult_vec3_inv_trans(&v47, &v30->trans, &v46); mat4_transpose(&v47, &v47); bool v32 = sub_140482FF0(&v47, &v46, &v30->data_ptr->skp_osg_node.hinge, &v30->reset_data.rotation, &rob_osg->yz_order); *v30->bone_node_ptr->ex_data_mat = v47; mat4_transpose(&v47, &v47); float_t v34; vec3_distance(v30->trans, v29->trans, v34); float_t v35 = parent_scale->x * v30->length; bool v36; if (v34 >= fabsf(v35)) { v35 = v34; v36 = false; } else v36 = true; mat4_translate_mult(&v47, v35, 0.0f, 0.0f, &v47); if (v32 || v36) mat4_get_translation(&v47, &v30->trans); } if (vector_old_length(rob_osg->nodes) && rob_osg->node.bone_node_mat) { mat4 v48 = *rob_osg->nodes.end[-1].bone_node_ptr->ex_data_mat; mat4_transpose(&v48, &v48); mat4_translate_mult(&v48, parent_scale->x * rob_osg->node.length, 0.0f, 0.0f, &v48); mat4_transpose(&v48, &v48); *rob_osg->node.bone_node_ptr->ex_data_mat = v48; } } } static void rob_osage_set_wind_direction(rob_osage* osg_block_data, vec3* wind_direction) { if (wind_direction) osg_block_data->wind_direction = *wind_direction; else osg_block_data->wind_direction = 0.0f; } static void ExOsageBlock__SetWindDirection(ExOsageBlock* osg) { vec3* (*wind_task_struct_get_wind_direction)() = (vec3 * (*)())0x000000014053D560; vec3 wind_direction = *wind_task_struct_get_wind_direction(); rob_chara_item_equip_object* item_equip_object = osg->base.item_equip_object; vec3_mult_scalar(wind_direction, item_equip_object->item_equip->wind_strength, wind_direction); rob_osage_set_wind_direction(&osg->rob, &wind_direction); } static void sub_140482300(vec3* a1, vec3* a2, vec3* a3, float_t osage_gravity_const, float_t weight) { weight *= osage_gravity_const; vec3 diff; vec3_sub(*a2, *a3, diff); float_t dist; vec3_length(diff, dist); if (dist <= fabsf(osage_gravity_const)) { diff.y = osage_gravity_const; vec3_length(diff, dist); } vec3_mult_scalar(diff, weight * diff.y * (1.0f / (dist * dist)), diff); vec3_negate(diff, diff); diff.y -= weight; *a1 = diff; } static void sub_140482F30(vec3* pos1, vec3* pos2, float_t length) { vec3 diff; vec3_sub(*pos1, *pos2, diff); float_t dist; vec3_length_squared(diff, dist); if (dist > length * length) { vec3_mult_scalar(diff, length / sqrtf(dist), diff); vec3_add(*pos2, diff, *pos1); } } static void sub_140482490(rob_osage_node* node, float_t step, float_t a3) { if (step != 1.0f) { vec3 v4; vec3_sub(node->trans, node->trans_orig, v4); float_t v9; vec3_length(v4, v9); if (v9 != 0.0f) vec3_mult_scalar(v4, 1.0f / v9, v4); vec3_mult_scalar(v4, step * v9, v4); vec3_add(node->trans_orig, v4, node->trans); } sub_140482F30(&node[0].trans, &node[-1].trans, node->length * a3); if (node->sibling_node) sub_140482F30(&node->trans, &node->sibling_node->trans, node->distance); } static void sub_140482180(rob_osage_node* node, float_t a2) { float_t v2 = node->data_ptr->skp_osg_node.coli_r + a2; if (v2 <= node->trans.y) return; node->trans.y = v2; vec3 v3; vec3_sub(node->trans, node[-1].trans, v3); vec3_normalize(v3, v3); vec3_mult_scalar(v3, node->length, v3); vec3_add(node[-1].trans, v3, node->trans); node->trans_diff = 0.0f; node->field_C8 += 1.0f; } static void sub_14047C800(rob_osage* rob_osg, mat4* mat, vec3* parent_scale, float_t step, bool a5, bool a6, bool a7) { if (!vector_old_length(rob_osg->nodes)) return; const float_t osage_gravity_const = get_osage_gravity_const(); sub_1404803B0(rob_osg, mat, parent_scale, 0); rob_osage_node* v17 = &rob_osg->nodes.begin[0]; v17->trans_orig = v17->trans; vec3 v113; vec3_mult(rob_osg->exp_data.position, *parent_scale, v113); mat4 v130 = *mat; mat4_transpose(&v130, &v130); mat4_mult_vec3_trans(&v130, &v113, &v17->trans); vec3_sub(v17->trans, v17->trans_orig, v17->trans_diff); mat4_transpose(&v130, &v130); sub_14047F110(rob_osg, &v130, parent_scale, 0); *rob_osg->nodes.begin[0].bone_node_mat = v130; *rob_osg->nodes.begin[0].bone_node_ptr->ex_data_mat = v130; mat4_transpose(&v130, &v130); v113 = { 1.0f, 0.0f, 0.0f }; vec3 v128; mat4_mult_vec3(&v130, &v113, &v128); float_t v25 = parent_scale->x; if (!rob_osg->osage_reset && step <= 0.0f) return; bool stiffness = rob_osg->skin_param_ptr->stiffness > 0.0f; rob_osage_node* v12 = rob_osg->nodes.end; rob_osage_node* v30 = rob_osg->nodes.begin; for (rob_osage_node* v26 = rob_osg->nodes.begin + 1; v26 != v12; v26++, v30++) { rob_osage_node_data* v31 = v26->data_ptr; float_t weight = v31->skp_osg_node.weight; vec3 v111; if (!rob_osg->set_external_force) { sub_140482300(&v111, &v26->trans, &v30->trans, osage_gravity_const, weight); if (v26 != &v12[-1]) { vec3 v112; sub_140482300(&v112, &v26->trans, &v26[1].trans, osage_gravity_const, weight); vec3_add(v111, v112, v111); vec3_mult_scalar(v111, 0.5f, v111); } } else vec3_mult_scalar(rob_osg->external_force, 1.0f / weight, v111); vec3 v127; vec3_mult_scalar(v128, v31->force * v26->force, v127); float_t v41 = (1.0f - rob_osg->field_1EB4) * (1.0f - rob_osg->skin_param_ptr->air_res); vec3 v126; vec3_add(v111, v127, v126); vec3_mult_scalar(v26->trans_diff, v41, v111); vec3_sub(v126, v111, v126); vec3_mult_scalar(v26->external_force, weight, v111); vec3_add(v126, v111, v126); if (!a5) { vec3_mult_scalar(rob_osg->wind_direction, rob_osg->skin_param_ptr->wind_afc, v111); vec3_add(v126, v111, v126); } if (stiffness) { vec3 v116; vec3_sub(v26->trans_diff, v30->trans_diff, v116); vec3_mult_scalar(v116, 1.0f - rob_osg->skin_param_ptr->air_res, v116); vec3_sub(v126, v116, v126); } float_t v49 = 1.0f / (weight - (weight - 1.0f) * v31->skp_osg_node.inertial_cancel); vec3_mult_scalar(v126, v49, v26->field_28); } if (stiffness) { mat4 v131 = v130; vec3 v111; mat4_get_translation(&v131, &v111); for (rob_osage_node* v55 = rob_osg->nodes.begin + 1; v55 != v12; v55++) { mat4_mult_vec3_trans(&v131, &v55->field_94, &v128); vec3 v123; vec3_add(v55->trans_diff, v55->field_28, v123); vec3 v126; vec3_add(v55->trans, v123, v126); sub_140482F30(&v126, &v111, v25 * v55->length); vec3 v117; vec3_sub(v128, v126, v117); vec3_mult_scalar(v117, rob_osg->skin_param_ptr->stiffness, v117); float_t weight = v55->data_ptr->skp_osg_node.weight; float_t v74 = 1.0f / (weight - (weight - 1.0f) * v55->data_ptr->skp_osg_node.inertial_cancel); vec3_mult_scalar(v117, v74, v117); vec3_add(v55->field_28, v117, v55->field_28); vec3_add(v55->trans, v117, v126); vec3_add(v126, v123, v126); vec3 v129; mat4_mult_vec3_inv_trans(&v131, &v126, &v129); mat4_transpose(&v131, &v131); sub_140482FF0(&v131, &v129, 0, 0, &rob_osg->yz_order); mat4_transpose(&v131, &v131); float_t v58; vec3_distance(v111, v126, v58); mat4_translate_mult(&v131, v58, 0.0f, 0.0f, &v131); v111 = v126; } } for (rob_osage_node* v82 = rob_osg->nodes.begin + 1; v82 != v12; v82++) { v82->trans_orig = v82->trans; vec3_add(v82->field_28, v82->trans_diff, v82->trans_diff); vec3_add(v82->trans_diff, v82->trans, v82->trans); } for (rob_osage_node* v90 = v12 - 2; v90 != rob_osg->nodes.begin; v90--) sub_140482F30(&v90[0].trans, &v90[1].trans, v25 * v90->child_length); if (a6) { rob_osage_node* v91 = rob_osg->nodes.begin; float_t v93 = v91->data_ptr->skp_osg_node.coli_r; float_t v97; if (v91->trans.x < rob_osg->ring.ring_rectangle_x - v93 || v91->trans.z < rob_osg->ring.ring_rectangle_y - v93 || v91->trans.x > rob_osg->ring.ring_rectangle_x + rob_osg->ring.ring_rectangle_width || v91->trans.z > rob_osg->ring.ring_rectangle_y + rob_osg->ring.ring_rectangle_height) v97 = rob_osg->ring.ring_out_height; else v97 = rob_osg->ring.ring_height; float_t v96 = v97 + v93; for (rob_osage_node* v98 = v91 + 1; v98 != v12; v98++) { sub_140482490(v98, step, v25); sub_140482180(v98, v96); } } if (a7) { for (rob_osage_node* v99 = rob_osg->nodes.begin + 1, *v100 = rob_osg->nodes.begin; v99 != v12; v99++, v100++) { vec3 v129; mat4_mult_vec3_inv_trans(&v130, &v99->trans, &v129); mat4_transpose(&v130, &v130); bool v102 = sub_140482FF0(&v130, &v129, &v99->data_ptr->skp_osg_node.hinge, &v99->reset_data.rotation, &rob_osg->yz_order); *v99->bone_node_ptr->ex_data_mat = v130; mat4_transpose(&v130, &v130); float_t v104; vec3_distance_squared(v99->trans, v100->trans, v104); float_t v105 = v25 * v99->length; bool v106; if (v104 >= v105 * v105) { v105 = sqrtf(v104); v106 = false; } else v106 = true; mat4_translate_mult(&v130, v105, 0.0f, 0.0f, &v130); if (v102 || v106) mat4_get_translation(&v130, &v99->trans); } if (vector_old_length(rob_osg->nodes) && rob_osg->node.bone_node_mat) { mat4 v131 = *rob_osg->nodes.end[-1].bone_node_ptr->ex_data_mat; mat4_transpose(&v131, &v131); mat4_translate_mult(&v131, v25 * rob_osg->node.length, 0.0f, 0.0f, &v131); mat4_transpose(&v131, &v131); *rob_osg->node.bone_node_ptr->ex_data_mat = v131; } } rob_osg->field_2A0 = false; } void sub_140484E10(vec3* a1, vec3* a2, vec3* a3, vec3* a4) { vec3 v6; vec3_sub(*a3, *a2, v6); vec3 v7; vec3_sub(*a4, *a2, v7); float_t v8; vec3_dot(v7, v6, v8); if (v8 < 0.0f) { *a1 = *a2; return; } float_t v9; vec3_length_squared(v6, v9); if (v9 <= 0.000001f) *a1 = *a2; else if (v8 <= v9) { float_t v10 = v8 / v9; vec3_mult_scalar(v6, v8 / v9, v6); vec3_add(*a2, v6, *a1); } else *a1 = *a3; } static int32_t sub_140483DE0(vec3* a1, vec3* a2, vec3* a3, float_t radius) { vec3 v5; float_t length; vec3_sub(*a2, *a3, v5); vec3_length_squared(v5, length); if (length > 0.000001f && length < radius * radius) { vec3_mult_scalar(v5, radius / sqrtf(length) - 1.0f, *a1); return 1; } return 0; } static int32_t sub_140484450(vec3* a1, vec3* a2, vec3* a3, vec3* a4, float_t* radius) { vec3 v8; sub_140484E10(&v8, a2, a3, a4); return sub_140483DE0(a1, &v8, a4, *radius); } static void sub_140484850(vec3* a1, vec3* a2, vec3* a3, osage_coli* coli) { vec3 v56; vec3_sub(*a3, *a2, v56); vec3 v60; vec3_cross(v56, coli->bone_pos_diff, v60); float_t v46; vec3_length_squared(v60, v46); if (v46 <= 0.000001f) { vec3 v56; vec3 v57; vec3 v58; vec3 v59; sub_140484E10(&v59, &coli->bone0_pos, &coli->bone1_pos, a2); sub_140484E10(&v58, &coli->bone0_pos, &coli->bone1_pos, a3); sub_140484E10(&v57, a2, a3, &coli->bone0_pos); sub_140484E10(&v56, a2, a3, &coli->bone1_pos); float_t v48; float_t v51; float_t v52; float_t v55; vec3_distance_squared(*a3, coli->bone0_pos, v48); vec3_distance_squared(coli->bone0_pos, v57, v51); vec3_distance_squared(coli->bone1_pos, v56, v52); vec3_distance_squared(*a2, v59, v55); *a1 = *a2; if (v55 > v48) { *a1 = *a3; v55 = v48; } if (v55 > v51) { *a1 = v57; v55 = v51; } if (v55 > v52) *a1 = v56; } else { float_t v25; vec3_length(v56, v25); if (v25 != 0.0) vec3_mult_scalar(v56, 1.0f / v25, v56); float_t v30 = 1.0f / coli->bone_pos_diff_length; vec3 v61; float_t v34; vec3_mult_scalar(coli->bone_pos_diff, v30, v61); vec3_dot(v61, v56, v34); vec3_mult_scalar(v61, v34, v61); vec3_sub(v61, v56, v61); vec3_sub(coli->bone0_pos, *a2, v60); float_t v35; vec3_dot(v61, v60, v35); v35 /= (v34 * v34 - 1.0f); if (v35 < 0.0f) *a1 = *a2; else if (v35 <= v25) { vec3_mult_scalar(v56, v35, v56); vec3_add(*a2, v56, *a1); } else *a1 = *a3; } } static int32_t sub_140484540(vec3* a1, vec3* a2, osage_coli* coli, float_t radius) { vec3 v11; vec3_sub(*a2, coli->bone0_pos, v11); float_t v17; vec3_dot(v11, coli->bone_pos_diff, v17); if (v17 < 0.0f) return sub_140483DE0(a1, a2, &coli->bone0_pos, radius); float_t v19 = coli->bone_pos_diff_length_squared; if (fabs(coli->bone_pos_diff_length_squared) <= 0.000001) return sub_140483DE0(a1, a2, &coli->bone0_pos, radius); if (v17 > v19) return sub_140483DE0(a1, a2, &coli->bone1_pos, radius); float_t v20; vec3_length_squared(v11, v20); float_t v22 = fabsf(v20 - v17 * v17 / v19); if (v22 <= 0.000001f || v22 >= radius * radius) return 0; vec3 v29; vec3_mult_scalar(coli->bone_pos_diff, v17 / v19, v29); vec3_sub(v11, v29, v29); vec3_mult_scalar(v29, radius / sqrtf(v22) - 1.0f, *a1); return 1; } static int32_t sub_1404844A0(vec3* a1, vec3* a2, vec3* a3, osage_coli* a4, float_t radius) { vec3 v8; sub_140484850(&v8, a2, a3, a4); return sub_140484540(a1, &v8, a4, radius); } static int32_t sub_140483EA0(vec3* a1, vec3* a2, osage_coli* a3, float_t radius) { if (a3->bone_pos_diff_length <= 0.000001f) return sub_140483DE0(a1, a2, &a3->bone0_pos, radius); float_t v61 = a3->bone_pos_diff_length * 0.5f; float_t v13 = sqrtf(radius * radius + v61 * v61); float_t v20; vec3 v54; vec3_sub(*a2, a3->bone0_pos, v54); vec3_length(v54, v20); float_t v21; vec3 v57; vec3_sub(*a2, a3->bone1_pos, v57); vec3_length(v57, v21); if (v20 <= 0.000001f || v21 <= 0.000001f) return 0; float_t v22 = v20 + v21; if (v21 + v20 >= v13 * 2.0f) return 0; float_t v25 = 1.0f / a3->bone_pos_diff_length; vec3 v63; vec3_add(a3->bone0_pos, a3->bone1_pos, v63); vec3_mult_scalar(v63, 0.5f, v63); vec3_sub(*a2, v63, v63); float_t v58; vec3_length(v63, v58); if (v58 != 0.0f) vec3_mult_scalar(v63, 1.0f / v58, v63); float_t v36; vec3_dot(v63, a3->bone_pos_diff, v36); v36 *= v25; float_t v37 = v36 * v36; v37 = min_def(v37, 1.0f); v22 *= 0.5f; float_t v38 = v22 * v22 - v61; if (v38 < 0.0f) return 0; float_t v39 = sqrtf(v38); if (v39 <= 0.000001f) return 0; float_t v42 = sqrtf(1.0f - v37); v22 = (v13 / v22 - 1.0f) * v36 * v58; v42 = (radius / v39 - 1.0f) * v42 * v58; float_t v43 = sqrtf(v42 * v42 + v22 * v22); if (v20 != 0.0f) vec3_mult_scalar(v54, 1.0f / v20, v54); if (v21 != 0.0f) vec3_mult_scalar(v57, 1.0f / v21, v57); vec3 v48; vec3_add(v54, v57, v48); vec3_normalize(v48, v48); vec3_mult_scalar(v48, v43, *a1); return 1; } static int32_t sub_1404844F0(vec3* a1, vec3* a2, vec3* a3, osage_coli* a4, float_t radius) { vec3 v8; sub_140484850(&v8, a2, a3, a4); return sub_140483EA0(a1, &v8, a4, radius); } static int32_t sub_140485000(vec3* a1, vec3* a2, skin_param_osage_node* a3, osage_coli* a4) { if (!a4) return 0; int32_t v8 = 0; while (a4->type) { int32_t type = a4->type; vec3 v21 = 0.0f; switch (a4->type) { case 1: { vec3 v22 = a4->bone0_pos; float_t v23 = a3->coli_r + a4->radius; v8 += sub_140484450(&v21, a1, a2, &v22, &v23); } break; case 2: v8 += sub_1404844A0(&v21, a1, a2, a4, a3->coli_r + a4->radius); break; case 4: v8 += sub_1404844F0(&v21, a1, a2, a4, a3->coli_r + a4->radius); break; } if (v8 > 0) { vec3_add(*a1, v21, *a1); vec3_add(*a2, v21, *a2); } a4++; } return v8; } static void osage_coli_set(osage_coli* osg_coli, skin_param_osage_root_coli* skp_root_coli, mat4* mats) { osg_coli->type = 0; if (!skp_root_coli || !mats) return; for (; skp_root_coli->type; osg_coli++, skp_root_coli++) { osg_coli->type = skp_root_coli->type; osg_coli->radius = skp_root_coli->radius; mat4 mat = mats[skp_root_coli->bone0_index]; mat4_transpose(&mat, &mat); mat4_mult_vec3_trans(&mat, &skp_root_coli->bone0_pos, &osg_coli->bone0_pos); if (skp_root_coli->type == 2 || skp_root_coli->type == 4) { mat = mats[skp_root_coli->bone1_index]; mat4_transpose(&mat, &mat); mat4_mult_vec3_trans(&mat, &skp_root_coli->bone1_pos, &osg_coli->bone1_pos); vec3_sub(osg_coli->bone1_pos, osg_coli->bone0_pos, osg_coli->bone_pos_diff); vec3_length_squared(osg_coli->bone_pos_diff, osg_coli->bone_pos_diff_length_squared); osg_coli->bone_pos_diff_length = sqrtf(osg_coli->bone_pos_diff_length_squared); if (osg_coli->bone_pos_diff_length < 0.01f) osg_coli->type = 1; } else if (skp_root_coli->type == 3) mat4_mult_vec3(&mat, &skp_root_coli->bone1_pos, &osg_coli->bone1_pos); } osg_coli->type = 0; } static void osage_coli_ring_set(osage_coli* osg_coli, vector_old_skin_param_osage_root_coli* vec_skp_root_coli, mat4* mats) { if (vec_skp_root_coli->begin == vec_skp_root_coli->end) { osg_coli->type = 0; osg_coli->radius = 0.0f; osg_coli->bone0_pos = 0.0f; osg_coli->bone1_pos = 0.0f; osg_coli->bone_pos_diff = 0.0f; osg_coli->bone_pos_diff_length = 0.0f; osg_coli->bone_pos_diff_length_squared = 0.0f; osg_coli->field_34 = 1.0f; } else osage_coli_set(osg_coli, vec_skp_root_coli->begin, mats); } static void rob_osage_coli_set(rob_osage* rob_osg, mat4* mats) { if (vector_old_length(rob_osg->skin_param_ptr->coli)) osage_coli_set(rob_osg->coli, rob_osg->skin_param_ptr->coli.begin, mats); osage_coli_ring_set(rob_osg->coli_ring, &rob_osg->ring.skp_root_coli, mats); } static int32_t sub_140484780(vec3* a1, vec3* a2, vec3* a3, vec3* a4, float_t a5) { float_t v5; float_t v6; vec3_dot(*a2, *a4, v5); vec3_dot(*a3, *a4, v6); v5 -= v6; v5 -= a5; if (v5 >= 0.0f) return 0; vec3_mult_scalar(*a4, -v5, *a1); return 1; } static int32_t sub_140483B30(vec3* a1, vec3* a2, osage_coli* a3, float_t radius) { vec3 bone_pos_diff; vec3_add(a3->bone0_pos, a3->bone1_pos, bone_pos_diff); vec3 v29; vec3 v30; for (int32_t i = 0; i < 3; i++) { float_t v13 = ((float_t*)a2)[i]; float_t v14 = ((float_t*)&a3->bone0_pos)[i] - v13; ((float_t*)&v30)[i] = v14; if (v14 > radius) return 0; v14 = v13 - ((float_t*)&bone_pos_diff)[i]; ((float_t*)&v29)[i] = v14; if (v14 > radius) return 0; } vec3 v28 = 0.0f; vec3 v32 = 0.0f; vec3 v27 = 1.0f; float_t v16 = 0.0f; for (int32_t i = 0; i < 3; i++) { float_t v18 = ((float_t*)&v30)[i]; float_t v19 = ((float_t*)&v29)[i]; if (fabsf(v18) >= fabsf(v19)) { ((float_t*)&v28)[i] = v19; ((float_t*)&v27)[i] = 1.0f; v18 = v19; } else { ((float_t*)&v28)[i] = v18; ((float_t*)&v27)[i] = -1.0f; } if (v18 > 0.0f) { float_t v20 = v18 * v18; ((float_t*)&v32)[i] = v20; v16 += v20; } } if (v16 > radius * radius) return 0; if (v16 > 0.0f) { vec3_mult(v27, v32, v32); vec3_mult_scalar(v32, 1.0f / v16, v32); vec3_mult_scalar(v32, radius - sqrtf(v16), *a1); } else { float_t v25 = ((float_t*)&v28)[0]; int32_t v26 = 0; for (int32_t i = 0; i < 3; i++) { if (((float_t*)&v28)[i] > v25) { v25 = ((float_t*)&v28)[i]; v26 = i; } } ((float_t*)a1)[v26] -= ((float_t*)&v27)[v26] * (v25 - radius); } return 1; } static int32_t sub_140485220(vec3* a1, skin_param_osage_node* a2, osage_coli* coli, float_t* a4){ if (!coli) return 0; int32_t v8 = 0; for (osage_coli* v9 = coli; v9->type; v9++) { int32_t v11 = 0; vec3 v31 = 0.0f; switch (v9->type) { case 1: v11 = sub_140483DE0(&v31, a1, &v9->bone0_pos, v9->radius + a2->coli_r); break; case 2: v11 = sub_140484540(&v31, a1, v9, v9->radius + a2->coli_r); break; case 3: v11 = sub_140484780(&v31, a1, &v9->bone0_pos, &v9->bone1_pos, a2->coli_r); break; case 4: v11 = sub_140483EA0(&v31, a1, v9, v9->radius + a2->coli_r); break; case 5: v11 = sub_140483B30(&v31, a1, v9, a2->coli_r); break; } if (a4 && v11 > 0 && v9->field_34 < *a4) *a4 = v9->field_34; vec3_add(*a1, v31, *a1); v8 += v11; } return v8; } static int32_t sub_1404851C0(vec3* a1, skin_param_osage_node* a2, vector_old_osage_coli* a3, float_t* a4) { if (a3->begin == a3->end || a3->end[-1].type) return 0; return sub_140485220(a1, a2, a3->begin, a4); } static int32_t sub_140485180(osage_coli* a1, vec3* a2, skin_param_osage_node* a3) { return sub_140485220(a2, a3, a1, 0); } static void sub_14047ECA0(rob_osage* rob_osg, float_t step) { if (step <= 0.0f) return; osage_coli* coli = rob_osg->coli; osage_coli* coli_ring = rob_osg->coli_ring; vector_old_osage_coli* ring_coli = &rob_osg->ring.coli; bool v11 = rob_osg->field_1F0F; for (rob_osage_node* i = rob_osg->nodes.begin + 1; i != rob_osg->nodes.end; i++) { rob_osage_node_data* data = i->data_ptr; i->field_C8 += (float_t)sub_1404851C0(&i->trans, &data->skp_osg_node, ring_coli, &i->field_CC); if (v11) continue; for (rob_osage_node** j = data->boc.begin; j != data->boc.end; j++) { rob_osage_node* k = *j; k->field_C8 += (float_t)sub_140485180(coli_ring, &k->trans, &data->skp_osg_node); k->field_C8 += (float_t)sub_140485180(coli, &k->trans, &data->skp_osg_node); } i->field_C8 += (float_t)sub_140485180(coli_ring, &i->trans, &data->skp_osg_node); i->field_C8 += (float_t)sub_140485180(coli, &i->trans, &data->skp_osg_node); } } static void sub_14047D620(rob_osage* rob_osg, float_t step) { if (step < 0.0f && rob_osg->field_1F0F) return; vector_old_rob_osage_node* nodes = &rob_osg->nodes; vec3 v7 = nodes->begin[0].trans; osage_coli* coli = rob_osg->coli; osage_coli* coli_ring = rob_osg->coli_ring; for (rob_osage_node* v10 = nodes->begin + 1; v10 != nodes->end; v10++) { rob_osage_node_data* v11 = v10->data_ptr; for (rob_osage_node** j = v11->boc.begin; j != v11->boc.end; j++) { rob_osage_node* v15 = *j; float_t v17 = (float_t)( sub_140485000(&v10->trans, &v15->trans, &v11->skp_osg_node, coli) + sub_140485000(&v10->trans, &v15->trans, &v11->skp_osg_node, coli_ring)); v10->field_C8 += v17; v15->field_C8 += v17; } int32_t v18 = rob_osg->skin_param_ptr->coli_type; if (v18 && (v18 != 1 || v10 != nodes->begin + 1)) { float_t v20 = (float_t)( sub_140485000(&v10[0].trans, &v10[-1].trans, &v11->skp_osg_node, coli) + sub_140485000(&v10[0].trans, &v10[-1].trans, &v11->skp_osg_node, coli_ring)); v10[0].field_C8 += v20; v10[-1].field_C8 += v20; } } nodes->begin[0].trans = v7; } static void sub_14047D8C0(rob_osage* rob_osg, mat4* mat, vec3* parent_scale, float_t step, bool a5) { if (!rob_osg->osage_reset && step <= 0.0f) return; osage_coli* coli = rob_osg->coli; osage_coli* coli_ring = rob_osg->coli_ring; vector_old_osage_coli* vec_ring_coli = &rob_osg->ring.coli; float_t v9 = 0.0f; if (step > 0.0f) v9 = 1.0f / step; mat4 v64; if (a5) v64 = *rob_osg->nodes.begin[0].bone_node_mat; else { v64 = *mat; vec3 trans; vec3_mult(rob_osg->exp_data.position, *parent_scale, trans); mat4_transpose(&v64, &v64); mat4_mult_vec3_trans(&v64, &trans, &rob_osg->nodes.begin[0].trans); mat4_transpose(&v64, &v64); sub_14047F110(rob_osg, &v64, parent_scale, 0); } mat4_transpose(&v64, &v64); float_t v60 = -1000.0f; if (a5) { float_t v22; rob_osage_node* v16 = &rob_osg->nodes.begin[0]; float_t v18 = v16->data_ptr->skp_osg_node.coli_r; if (v16->trans.x < rob_osg->ring.ring_rectangle_x - v18 || v16->trans.z < rob_osg->ring.ring_rectangle_y - v18 || v16->trans.x > rob_osg->ring.ring_rectangle_x + rob_osg->ring.ring_rectangle_width || v16->trans.z > rob_osg->ring.ring_rectangle_y + rob_osg->ring.ring_rectangle_height) v22 = rob_osg->ring.ring_out_height; else v22 = rob_osg->ring.ring_height; v60 = v22 + v18; } float_t v23 = 0.2f; if (step < 1.0f) v23 = 0.2f / (2.0f - step); if (rob_osg->skin_param_ptr->colli_tgt_osg) { vector_old_rob_osage_node* v24 = rob_osg->skin_param_ptr->colli_tgt_osg; rob_osage_node* v26 = v24->end; rob_osage_node* v27 = rob_osg->nodes.begin + 1; for (rob_osage_node* v25 = rob_osg->nodes.begin + 1; v25 != rob_osg->nodes.end; v25++, v27++) { vec3 v62 = 0.0f; for (rob_osage_node* v30 = v24->begin + 1; v30 != v26; v30++) sub_140483DE0(&v62, &v27->trans, &v30->trans, v27->data_ptr->skp_osg_node.coli_r + v30->data_ptr->skp_osg_node.coli_r); vec3_add(v27->trans, v62, v27->trans); } } for (rob_osage_node* v35 = rob_osg->nodes.begin + 1; v35 != rob_osg->nodes.end; v35++) { skin_param_osage_node* skp_osg_node = &v35->data_ptr->skp_osg_node; float_t v37 = (1.0f - rob_osg->field_1EB4) * rob_osg->skin_param_ptr->friction; if (a5) { sub_140482490(v35, step, parent_scale->x); v35->field_C8 = (float_t)sub_1404851C0(&v35->trans, skp_osg_node, vec_ring_coli, &v35->field_CC); if (!rob_osg->field_1F0F) { v35->field_C8 += (float_t)sub_140485180(coli_ring, &v35->trans, skp_osg_node); v35->field_C8 += (float_t)sub_140485180(coli, &v35->trans, skp_osg_node); } sub_140482180(v35, v60); } else sub_140482F30(&v35[0].trans, &v35[-1].trans, v35[0].length * parent_scale->x); vec3 v63; mat4_mult_vec3_inv_trans(&v64, &v35->trans, &v63); mat4_transpose(&v64, &v64); bool v40 = sub_140482FF0(&v64, &v63, &skp_osg_node->hinge, &v35->reset_data.rotation, &rob_osg->yz_order); v35->bone_node_ptr->exp_data.parent_scale = *parent_scale; *v35->bone_node_ptr->ex_data_mat = v64; mat4_transpose(&v64, &v64); if (v35->bone_node_mat) { mat4* v41 = v35->bone_node_mat; mat4_scale_rot(&v64, parent_scale, v41); mat4_transpose(v41, v41); } float_t v42 = v35->length * parent_scale->x; float_t v44; bool v45; vec3_distance_squared(v35[0].trans, v35[-1].trans, v44); if (v44 >= v42 * v42) { v42 = sqrtf(v44); v45 = false; } else v45 = true; mat4_translate_mult(&v64, v42, 0.0f, 0.0f, &v64); v35->reset_data.length = v42; if (v40 || v45) mat4_get_translation(&v64, &v35->trans); vec3 v62; vec3_sub(v35->trans, v35->trans_orig, v62); vec3_mult_scalar(v62, v9, v35->trans_diff); if (v35->field_C8 > 0.0f) { if (v35->field_CC < v37) v37 = v35->field_CC; vec3_mult_scalar(v35->trans_diff, v37, v35->trans_diff); } float_t v55; vec3_length_squared(v35->trans_diff, v55); if (v55 > v23 * v23) vec3_mult_scalar(v35->trans_diff, v23 / sqrtf(v55), v35->trans_diff); mat4 v65; mat4_transpose(mat, &v65); mat4_mult_vec3_inv_trans(&v65, &v35->trans, &v35->reset_data.trans); mat4_mult_vec3_inv(&v65, &v35->trans_diff, &v35->reset_data.trans_diff); } if (vector_old_length(rob_osg->nodes) && rob_osg->node.bone_node_mat) { mat4 v65 = *rob_osg->nodes.end[-1].bone_node_ptr->ex_data_mat; mat4_transpose(&v65, &v65); mat4_translate_mult(&v65, rob_osg->node.length * parent_scale->x, 0.0f, 0.0f, &v65); mat4_transpose(&v65, &v65); *rob_osg->node.bone_node_ptr->ex_data_mat = v65; mat4_transpose(&v65, &v65); mat4_scale_rot(&v65, parent_scale, &v65); mat4_transpose(&v65, &v65); *rob_osg->node.bone_node_mat = v65; rob_osg->node.bone_node_ptr->exp_data.parent_scale = *parent_scale; } } static void sub_140480F40(rob_osage* rob_osg, vec3* external_force, float_t a3) { vec3 v4; if (external_force) v4 = *external_force; else v4 = 0.0f; ssize_t v7 = rob_osg->osage_setting.parts; ssize_t v8 = 0; if (v7 >= 4) { float_t v9 = a3 * a3 * a3 * a3; ssize_t v10 = ((v7 - 4ULL) >> 2) + 1; v8 = 4 * v10; for (; v10; v10--) vec3_mult_scalar(v4, v9, v4); } if (v8 < v7) for (size_t v12 = v7 - v8; v12; v12--) vec3_mult_scalar(v4, a3, v4); for (rob_osage_node* i = rob_osg->nodes.begin + 1; i != rob_osg->nodes.end; i++) { i->external_force = v4; vec3_mult_scalar(v4, a3, v4); } } static void rob_osage_set_nodes_force(rob_osage* rob_osg, float_t a2) { for (rob_osage_node* i = rob_osg->nodes.begin + 1; i != rob_osg->nodes.end; i++) i->force = a2; } static void sub_140480260(rob_osage* rob_osg, mat4* mat, vec3* parent_scale, float_t step, bool v5) { if (!v5) { sub_140480F40(rob_osg, 0, 1.0f); rob_osage_set_nodes_force(rob_osg, 1.0f); rob_osg->set_external_force = false; rob_osg->external_force = 0.0f; } for (rob_osage_node* v6 = rob_osg->nodes.begin; v6 != rob_osg->nodes.end; v6++) { v6->field_C8 = 0.0f; v6->field_CC = 1.0f; } rob_osg->field_2A0 = true; rob_osg->field_2A1 = false; rob_osg->field_2A4 = -1.0f; rob_osg->field_1F0C = false; rob_osg->osage_reset = false; rob_osg->field_1F0E = false; rob_osg->parent_mat = *rob_osg->parent_mat_ptr; } void ExOsageBlock__Field_18(ExOsageBlock* osg, int32_t a2, bool a3) { float_t(*get_delta_frame)() = (float_t(*)())0x0000000140192D50; rob_chara_item_equip* rob_item_equip = osg->base.item_equip_object->item_equip; float_t step = get_delta_frame() * rob_item_equip->step; if (vector_old_length(rob_item_equip->opd_blend_data) && rob_item_equip->opd_blend_data.begin[0].field_C) step = 1.0f; bone_node* parent_node = osg->base.parent_bone_node; mat4* parent_node_mat = parent_node->ex_data_mat; vec3 parent_scale = parent_node->exp_data.parent_scale; switch (a2) { case 0: sub_1404803B0(&osg->rob, parent_node_mat, &parent_scale, osg->base.field_5A); break; case 1: case 2: if ((a2 == 1 && osg->base.field_58) || (a2 == 2 && osg->rob.field_2A0)) { ExOsageBlock__SetWindDirection(osg); sub_14047C800(&osg->rob, parent_node_mat, &parent_scale, step, a3, true, osg->base.field_5A); } break; case 3: rob_osage_coli_set(&osg->rob, osg->mat); sub_14047ECA0(&osg->rob, step); break; case 4: sub_14047D620(&osg->rob, step); break; case 5: sub_14047D8C0(&osg->rob, parent_node_mat, &parent_scale, step, false); sub_140480260(&osg->rob, parent_node_mat, &parent_scale, step, a3); osg->base.field_59 = true; break; } } static void sub_14047C770(rob_osage* rob_osg, mat4* mat, vec3* parent_scale, float_t step, bool a5) { sub_14047C800(rob_osg, mat, parent_scale, step, a5, false, false); sub_14047D8C0(rob_osg, mat, parent_scale, step, true); sub_140480260(rob_osg, mat, parent_scale, step, a5); } static void sub_14047C750(rob_osage* rob_osg, mat4* mat, vec3* parent_scale, float_t step) { sub_14047C770(rob_osg, mat, parent_scale, step, 0); } void ExOsageBlock__Field_20(ExOsageBlock* osg) { osg->field_1FF8 &= ~2; if (osg->base.field_59) { osg->base.field_59 = false; return; } float_t(*get_delta_frame)() = (float_t(*)())0x0000000140192D50; rob_chara_item_equip* rob_item_equip = osg->base.item_equip_object->item_equip; float_t step = get_delta_frame() * rob_item_equip->step; if (vector_old_length(rob_item_equip->opd_blend_data) && rob_item_equip->opd_blend_data.begin[0].field_C) step = 1.0f; bone_node* parent_node = osg->base.parent_bone_node; vec3 parent_scale = parent_node->exp_data.parent_scale; vec3 scale = parent_node->exp_data.scale; mat4 mat = *parent_node->ex_data_mat; if (scale.x != 1.0f || scale.y != 1.0f || scale.z != 1.0f) { vec3_div(1.0f, scale, scale); mat4_transpose(&mat, &mat); mat4_scale_rot(&mat, &scale, &mat); mat4_transpose(&mat, &mat); } ExOsageBlock__SetWindDirection(osg); rob_osage_coli_set(&osg->rob, osg->mat); sub_14047C750(&osg->rob, &mat, &parent_scale, step); } void sub_140482DF0(struc_477* dst, struc_477* src0, struc_477* src1, float_t blend) { dst->length = lerp_def(src0->length, src1->length, blend); vec3_lerp_scalar(src0->angle, src1->angle, dst->angle, blend); } void sub_140482100(struc_476* a1, opd_blend_data* a2, struc_477* a3) { if (!a2->field_C) a1->field_0 = *a3; else if (a2->type == MOTION_BLEND_FREEZE) { if (a2->blend == 0.0f) a1->field_10 = a1->field_0; sub_140482DF0(&a1->field_0, &a1->field_10, a3, a2->blend); } else if (a2->type == MOTION_BLEND_CROSS) sub_140482DF0(&a1->field_0, &a1->field_0, a3, a2->blend); } void sub_14047E240(rob_osage* rob_osg, mat4* a2, vec3* parent_scale, vector_old_opd_blend_data* a4) { if (!vector_old_length(*a4)) return; vec3 v63; vec3_mult(rob_osg->exp_data.position, *parent_scale, v63); mat4 v85; mat4_transpose(a2, &v85); mat4_mult_vec3_trans(&v85, &v63, &rob_osg->nodes.begin[0].trans); mat4_transpose(&v85, &v85); sub_14047F110(rob_osg, &v85, parent_scale, 0); *rob_osg->nodes.begin[0].bone_node_mat = v85; *rob_osg->nodes.begin[0].bone_node_ptr->ex_data_mat = v85; mat4_transpose(&v85, &v85); mat4_transpose(a2, a2); size_t v17 = vector_old_length(*a4) - 1; for (opd_blend_data* i = a4->end; i != a4->begin; v17--) { i--; mat4 v87 = v85; float_t frame = i->frame; vec3 v22 = rob_osg->nodes.begin[0].trans; vec3 v25 = v22; if (frame >= i->frame_count) frame = 0.0f; int32_t frame_int = (int32_t)frame; if (frame != -0.0f && (float_t)frame_int != frame) frame_int = (frame < 0.0f ? frame_int - 1 : frame_int); int32_t curr_key = frame_int; int32_t next_key = frame_int + 1; if ((float_t)next_key >= i->frame_count) next_key = 0; float_t blend = frame - (float_t)frame_int; float_t inv_blend = 1.0f - blend; for (rob_osage_node* j = rob_osg->nodes.begin + 1; j != rob_osg->nodes.end; j++) { opd_vec3_data* opd = &j->opd_data.begin[v17]; float_t* opd_x = opd->x; float_t* opd_y = opd->y; float_t* opd_z = opd->z; vec3 v62; v62.x = opd_x[curr_key]; v62.y = opd_y[curr_key]; v62.z = opd_z[curr_key]; vec3 v77; v77.x = opd_x[next_key]; v77.y = opd_y[next_key]; v77.z = opd_z[next_key]; vec3 v84; mat4_mult_vec3_trans(a2, &v62, &v84); vec3 v83; mat4_mult_vec3_trans(a2, &v77, &v83); vec3 v82; vec3_mult_scalar(v83, blend, v82); vec3 v81; vec3_mult_scalar(v84, inv_blend, v81); vec3_add(v82, v81, v82); vec3 v86; mat4_mult_vec3_inv_trans(&v87, &v82, &v86); mat4_transpose(&v87, &v87); vec3 v64 = 0.0f; sub_140482FF0(&v87, &v86, 0, &v64, &rob_osg->yz_order); mat4_transpose(&v87, &v87); mat4_set_translation(&v87, &v82); float_t v50; vec3_distance(v83, v25, v50); float_t v49; vec3_distance(v84, v22, v49); struc_477 v72; v72.angle = v64; v72.length = v49 * inv_blend + v50 * blend; sub_140482100(&j->field_1B0, i, &v72); v22 = v84; v25 = v83; } } mat4_transpose(a2, a2); for (rob_osage_node* i = rob_osg->nodes.begin + 1; i != rob_osg->nodes.end; i++) { float_t v54 = i->field_1B0.field_0.angle.y; float_t v55 = i->field_1B0.field_0.angle.z; v54 = clamp_def(v54, (float_t)-M_PI, (float_t)M_PI); v55 = clamp_def(v55, (float_t)-M_PI, (float_t)M_PI); mat4_rotate_z_mult(&v85, v55, &v85); mat4_rotate_y_mult(&v85, v54, &v85); mat4_transpose(&v85, &v85); i->bone_node_ptr->exp_data.parent_scale = *parent_scale; *i->bone_node_ptr->ex_data_mat = v85; mat4_transpose(&v85, &v85); if (i->bone_node_mat) { mat4 mat = v85; mat4_scale_rot(&mat, parent_scale, &mat); mat4_transpose(&mat, i->bone_node_mat); } mat4_translate_mult(&v85, i->field_1B0.field_0.length, 0.0f, 0.0f, &v85); i->trans_orig = i->trans; mat4_get_translation(&v85, &i->trans); } if (vector_old_length(rob_osg->nodes) && rob_osg->node.bone_node_mat) { mat4 v87 = *rob_osg->nodes.end[-1].bone_node_ptr->ex_data_mat; mat4_transpose(&v87, &v87); mat4_translate_mult(&v87, rob_osg->node.length * parent_scale->x, 0.0f, 0.0f, &v87); mat4_transpose(&v87, &v87); *rob_osg->node.bone_node_ptr->ex_data_mat = v87; mat4_transpose(&v87, &v87); mat4_scale_rot(&v87, parent_scale, &v87); mat4_transpose(&v87, &v87); *rob_osg->node.bone_node_mat = v87; rob_osg->node.bone_node_ptr->exp_data.parent_scale = *parent_scale; } } void ExOsageBlock__SetOsagePlayData(ExOsageBlock* osg) { rob_chara_item_equip* rob_itm_equip = osg->base.item_equip_object->item_equip; bone_node* parent_node = osg->base.parent_bone_node; vec3 parent_scale = parent_node->exp_data.parent_scale; sub_14047E240(&osg->rob, parent_node->ex_data_mat, &parent_scale, &rob_itm_equip->opd_blend_data); } void ExOsageBlock__Disp(ExOsageBlock* osg) { } void ExOsageBlock__Reset(ExOsageBlock* osg) { osg->index = 0; rob_osage_init(&osg->rob); osg->field_1FF8 &= ~3; osg->mat = 0; osg->step = 1.0f; osg->base.bone_node_ptr = 0; } void ExOsageBlock__Field_40(ExOsageBlock* osg) { } void ExOsageBlock__Field_48(ExOsageBlock* osg) { void (*sub_14047F990) (rob_osage * a1, mat4 * a2, vec3 * a3, bool a4) = (void (*) (rob_osage*, mat4*, vec3*, bool))0x000000014047F990; osg->step = 4.0f; ExOsageBlock__SetWindDirection(osg); rob_osage_coli_set(&osg->rob, osg->mat); bone_node* parent_node = osg->base.parent_bone_node; vec3 parent_scale = parent_node->exp_data.parent_scale; vec3_mult_scalar(parent_scale, 0.5f, parent_scale); sub_14047F990(&osg->rob, parent_node->ex_data_mat, &parent_scale, false); osg->field_1FF8 &= ~2; } void ExOsageBlock__Field_50(ExOsageBlock* osg) { if (osg->base.field_59) { osg->base.field_59 = 0; return; } ExOsageBlock__SetWindDirection(osg); bone_node* parent_node = osg->base.parent_bone_node; vec3 parent_scale = parent_node->exp_data.parent_scale; rob_osage_coli_set(&osg->rob, osg->mat); sub_14047C770(&osg->rob, parent_node->ex_data_mat, &parent_scale, osg->step, 1); float_t step = 0.5f * osg->step; osg->step = max_def(step, 1.0f); } bool sub_14053D1B0(vec3* l_trans, vec3* r_trans, vec3* u_trans, vec3* d_trans, vec3* a5, vec3* a6, vec3* a7) { float_t length; vec3_sub(*d_trans, *u_trans, *a5); vec3_length_squared(*a5, length); if (length <= 0.000001f) return false; vec3_mult_scalar(*a5, 1.0f / sqrtf(length), *a5); vec3 v9; vec3_sub(*r_trans, *l_trans, v9); vec3_cross(v9, *a5, *a6); vec3_length_squared(*a6, length); if (length <= 0.000001f) return false; vec3_mult_scalar(*a6, 1.0f / sqrtf(length), *a6); vec3_cross(*a5, *a6, *a7); vec3_normalize(*a7, *a7); return true; } void sub_14053CE30(rob_osage_node_data_normal_ref* normal_ref, mat4* a2) { if (!normal_ref->field_0) return; mat4 mat; vec3 n_trans; vec3 u_trans; vec3 d_trans; vec3 l_trans; vec3 r_trans; mat4_transpose(normal_ref->n->bone_node_ptr->ex_data_mat, &mat); mat4_get_translation(&mat, &n_trans); mat4_transpose(normal_ref->u->bone_node_ptr->ex_data_mat, &mat); mat4_get_translation(&mat, &u_trans); mat4_transpose(normal_ref->d->bone_node_ptr->ex_data_mat, &mat); mat4_get_translation(&mat, &d_trans); mat4_transpose(normal_ref->l->bone_node_ptr->ex_data_mat, &mat); mat4_get_translation(&mat, &l_trans); mat4_transpose(normal_ref->r->bone_node_ptr->ex_data_mat, &mat); mat4_get_translation(&mat, &r_trans); vec3 v27; vec3 v26; vec3 v28; if (sub_14053D1B0(&l_trans, &r_trans, &u_trans, &d_trans, &v27, &v26, &v28)) { mat4 v34; *(vec3*)&v34.row0 = v28; *(vec3*)&v34.row1 = v26; *(vec3*)&v34.row2 = v27; *(vec3*)&v34.row3 = n_trans; v34.row0.w = 0.0f; v34.row1.w = 0.0f; v34.row2.w = 0.0f; v34.row3.w = 1.0f; mat4 v33 = normal_ref->mat; mat4_mult(&v33, &v34, a2); } } void sub_14047E1C0(rob_osage* rob_osg, vec3* parent_scale) { for (rob_osage_node* i = rob_osg->nodes.begin + 1; i != rob_osg->nodes.end; ++i) { if (!i->data_ptr->normal_ref.field_0) continue; sub_14053CE30(&i->data_ptr->normal_ref, i->bone_node_mat); mat4 mat; mat4_transpose(i->bone_node_mat, &mat); mat4_scale_rot(&mat, parent_scale, &mat); mat4_transpose(&mat, i->bone_node_mat); } } void ExOsageBlock__Field_58(ExOsageBlock* osg) { bone_node* parent_node = osg->base.parent_bone_node; vec3 parent_scale = parent_node->exp_data.parent_scale; sub_14047E1C0(&osg->rob, &parent_scale); }