/* 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->max_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.init = false; rob_osg->ring.ring_rectangle_height = 0.0f; rob_osg->ring.coli.work_list.end = rob_osg->ring.coli.work_list.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.work_list.begin) { operator_delete(rob_osg->ring.coli.work_list.begin); rob_osg->ring.coli.work_list.begin = 0; rob_osg->ring.coli.work_list.end = 0; rob_osg->ring.coli.work_list.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_zyx_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_zyx_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 has_children_node) { mat4 v47 = *mat; vec3 v45 = rob_osg->exp_data.position * *parent_scale; 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 v44; mat4_transpose(&rob_osg->parent_mat, &parent_mat); mat4_mult_vec3_inv_trans(&parent_mat, &v19->trans, &v44); mat4_transpose(rob_osg->parent_mat_ptr, &parent_mat); mat4_mult_vec3_trans(&parent_mat, &v44, &v44); v19->trans += (v44 - v19->trans) * move_cancel; } } if (!has_children_node) return; mat4_transpose(&v47, &v47); sub_14047F110(rob_osg, &v47, parent_scale, false); *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 v45; mat4_mult_vec3_inv_trans(&v47, &v30->trans, &v45); mat4_transpose(&v47, &v47); bool v32 = sub_140482FF0(&v47, &v45, &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); 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(); wind_direction *= osg->base.item_equip_object->item_equip->wind_strength; 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 = *a2 - *a3; float_t dist = vec3::length(diff); if (dist <= fabsf(osage_gravity_const)) { diff.y = osage_gravity_const; dist = vec3::length(diff); } diff = -(diff * (weight * diff.y * (1.0f / (dist * dist)))); diff.y -= weight; *a1 = diff; } static void sub_140482F30(vec3* pos1, vec3* pos2, float_t length) { vec3 diff = *pos1 - *pos2; float_t dist = vec3::length_squared(diff); if (dist > length * length) *pos1 = *pos2 + diff * (length / sqrtf(dist)); } static void sub_140482490(rob_osage_node* node, float_t step, float_t a3) { if (step != 1.0f) { vec3 v4 = node->trans - node->trans_orig; float_t v9 = vec3::length(v4); if (v9 != 0.0f) v4 *= 1.0f / v9; node->trans = node->trans_orig + v4 * (step * v9); } sub_140482F30(&node[0].trans, &node[-1].trans, node->length * a3); if (node->sibling_node) sub_140482F30(&node->trans, &node->sibling_node->trans, node->max_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; node->trans = node[-1].trans + vec3::normalize(node->trans - node[-1].trans) * node->length; 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 disable_external_force, bool ring_coli, bool has_children_node) { 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, false); rob_osage_node* v17 = &rob_osg->nodes.begin[0]; v17->trans_orig = v17->trans; vec3 v113 = rob_osg->exp_data.position * *parent_scale; mat4 v130 = *mat; mat4_transpose(&v130, &v130); mat4_mult_vec3_trans(&v130, &v113, &v17->trans); v17->trans_diff = v17->trans - v17->trans_orig; mat4_transpose(&v130, &v130); sub_14047F110(rob_osg, &v130, parent_scale, false); *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); v111 = (v111 + v112) * 0.5f; } } else v111 = rob_osg->external_force * (1.0f / weight); vec3 v127 = v128 * (v31->force * v26->force); float_t v41 = (1.0f - rob_osg->field_1EB4) * (1.0f - rob_osg->skin_param_ptr->air_res); vec3 v126 = v111 + v127 - v26->trans_diff * v41 + v26->external_force * weight; if (!disable_external_force) v126 += rob_osg->wind_direction * rob_osg->skin_param_ptr->wind_afc; if (stiffness) v126 -= (v26->trans_diff - v30->trans_diff) * (1.0f - rob_osg->skin_param_ptr->air_res); v26->field_28 = v126 * (1.0f / (weight - (weight - 1.0f) * v31->skp_osg_node.inertial_cancel)); } 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 v126 = v55->trans + v55->trans_diff + v55->field_28; sub_140482F30(&v126, &v111, v25 * v55->length); vec3 v117 = (v128 - v126) * rob_osg->skin_param_ptr->stiffness; 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); v55->field_28 += v117 * v74; v126 = v55->trans + v55->trans_diff + v55->field_28; 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); mat4_translate_mult(&v131, vec3::distance(v111, v126), 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; v82->trans_diff += v82->field_28; v82->trans += v82->trans_diff; } 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 (ring_coli) { rob_osage_node* v91 = rob_osg->nodes.begin; float_t coli_r = v91->data_ptr->skp_osg_node.coli_r; float_t ring_height; if (v91->trans.x < rob_osg->ring.ring_rectangle_x - coli_r || v91->trans.z < rob_osg->ring.ring_rectangle_y - coli_r || 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) ring_height = rob_osg->ring.ring_out_height; else ring_height = rob_osg->ring.ring_height; float_t v96 = ring_height + coli_r; for (rob_osage_node* v98 = v91 + 1; v98 != v12; v98++) { sub_140482490(v98, step, v25); sub_140482180(v98, v96); } } if (has_children_node) { 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); 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; } // 0x140484E10 static void OsageCollision__get_nearest_line2point(vec3* nearest, const vec3* p0, const vec3* p1, const vec3* q) { vec3 v6 = *p1 - *p0; vec3 v7 = *q - *p0; float_t v8 = vec3::dot(v7, v6); if (v8 < 0.0f) { *nearest = *p0; return; } float_t v9 = vec3::length_squared(v6); if (v9 <= 0.000001f) *nearest = *p0; else if (v8 <= v9) *nearest = *p0 + v6 * (v8 / v9); else *nearest = *p1; } // 0x140483DE0 static int32_t OsageCollision__cls_ball_oidashi(vec3* vec, const vec3* p, const vec3* center, const float_t r) { float_t length = vec3::distance_squared(*p, *center); if (length > 0.000001f && length < r * r) { *vec = (*p - *center) * (r / sqrtf(length) - 1.0f); return 1; } return 0; } // 0x140484450 static int32_t OsageCollision__cls_line2ball_oidashi(vec3* vec, const vec3* p0, const vec3* p1, const vec3* q, const float_t r) { vec3 _vec; OsageCollision__get_nearest_line2point(&_vec, p0, p1, q); return OsageCollision__cls_ball_oidashi(vec, &_vec, q, r); } // 0x140484850 static void closest_pt_segment_segment(vec3* vec, const vec3* p0, const vec3* p1, const OsageCollision__Work* cls) { vec3 v56 = *p1 - *p0; vec3 v60 = vec3::cross(v56, cls->vec_center); float_t v46 = vec3::length_squared(v60); if (v46 <= 0.000001f) { vec3 v56; vec3 v57; vec3 v58; vec3 v59; OsageCollision__get_nearest_line2point(&v59, &cls->pos[0], &cls->pos[1], p0); OsageCollision__get_nearest_line2point(&v58, &cls->pos[0], &cls->pos[1], p1); OsageCollision__get_nearest_line2point(&v57, p0, p1, &cls->pos[0]); OsageCollision__get_nearest_line2point(&v56, p0, p1, &cls->pos[1]); float_t v48 = vec3::distance_squared(*p1, cls->pos[0]); float_t v51 = vec3::distance_squared(cls->pos[0], v57); float_t v52 = vec3::distance_squared(cls->pos[1], v56); float_t v55 = vec3::distance_squared(*p0, v59); *vec = *p0; if (v55 > v48) { *vec = *p1; v55 = v48; } if (v55 > v51) { *vec = v57; v55 = v51; } if (v55 > v52) *vec = v56; } else { float_t v25 = vec3::length(v56); if (v25 != 0.0) v56 *= 1.0f / v25; float_t v30 = 1.0f / cls->vec_center_length; vec3 v61 = cls->vec_center * v30; float_t v34 = vec3::dot(v61, v56); float_t v35 = vec3::dot(v61 * v34 - v56, cls->pos[0] - *p0) / (v34 * v34 - 1.0f); if (v35 < 0.0f) *vec = *p0; else if (v35 <= v25) *vec = *p0 + v56 * v35; else *vec = *p1; } } // 0x140484540 static int32_t OsageCollision__cls_capsule_oidashi(vec3* vec, const vec3* p, const OsageCollision__Work* cls, const float_t r) { vec3 v11 = *p - cls->pos[0]; float_t v17 = vec3::dot(v11, cls->vec_center); if (v17 < 0.0f) return OsageCollision__cls_ball_oidashi(vec, p, &cls->pos[0], r); float_t v19 = cls->vec_center_length_squared; if (fabsf(v19) <= 0.000001) return OsageCollision__cls_ball_oidashi(vec, p, &cls->pos[0], r); else if (v17 > v19) return OsageCollision__cls_ball_oidashi(vec, p, &cls->pos[1], r); float_t v20 = vec3::length_squared(v11); float_t v22 = fabsf(v20 - v17 * v17 / v19); if (v22 > 0.000001f && v22 < r * r) { *vec = (v11 - cls->vec_center * (v17 / v19)) * (r / sqrtf(v22) - 1.0f); return 1; } return 0; } // 0x1404844A0 static int32_t OsageCollision__cls_line2capsule_oidashi(vec3* vec, const vec3* p0, const vec3* p1, const OsageCollision__Work* cls, const float_t r) { vec3 _vec; closest_pt_segment_segment(&_vec, p0, p1, cls); return OsageCollision__cls_capsule_oidashi(vec, &_vec, cls, r); } // 0x140483EA0 static int32_t OsageCollision__cls_ellipse_oidashi(vec3* vec, const vec3* p, const OsageCollision__Work* cls, const float_t r) { if (cls->vec_center_length <= 0.000001f) return OsageCollision__cls_ball_oidashi(vec, p, &cls->pos[0], r); float_t v61 = cls->vec_center_length * 0.5f; float_t v13 = sqrtf(r * r + v61 * v61); vec3 v54 = *p - cls->pos[0]; float_t v20 = vec3::length(v54); vec3 v57 = *p - cls->pos[1]; float_t v21 = vec3::length(v57); 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 / cls->vec_center_length; vec3 v63 = *p - (cls->pos[0] + cls->pos[1]) * 0.5f; float_t v58 = vec3::length(v63); if (v58 != 0.0f) v63 *= 1.0f / v58; float_t v36 =vec3::dot(v63, cls->vec_center) * 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 = (r / v39 - 1.0f) * v42 * v58; float_t v43 = sqrtf(v42 * v42 + v22 * v22); if (v20 != 0.0f) v54 *= 1.0f / v20; if (v21 != 0.0f) v57 *= 1.0f / v21; *vec = vec3::normalize(v54 + v57) * v43; return 1; } // 0x1404844F0 static int32_t OsageCollision__cls_line2ellipse_oidashi(vec3* vec, const vec3* p0, const vec3* p1, const OsageCollision__Work* cls, const float_t r) { vec3 _vec; closest_pt_segment_segment(&_vec, p0, p1, cls); return OsageCollision__cls_ellipse_oidashi(vec, &_vec, cls, r); } // 0x140485000 static int32_t OsageCollision__osage_capsule_cls(vec3* p0, vec3* p1, const float_t* cls_r, const OsageCollision__Work* cls) { if (!cls) return 0; int32_t v8 = 0; while (cls->type != SkinParam::CollisionTypeEnd) { vec3 vec = 0.0f; switch (cls->type) { case SkinParam::CollisionTypeBall: v8 += OsageCollision__cls_line2ball_oidashi(&vec, p0, p1, &cls->pos[0], *cls_r + cls->radius); break; case SkinParam::CollisionTypeCapsulle: v8 += OsageCollision__cls_line2capsule_oidashi(&vec, p0, p1, cls, *cls_r + cls->radius); break; case SkinParam::CollisionTypeEllipse: v8 += OsageCollision__cls_line2ellipse_oidashi(&vec, p0, p1, cls, *cls_r + cls->radius); break; } if (v8 > 0) { *p0 += vec; *p1 += vec; } cls++; } return v8; } // 0x140485450 static void OsageCollision__Work__update_cls_work(OsageCollision__Work* cls, SkinParam__CollisionParam* cls_param, mat4* transform) { cls->type = SkinParam::CollisionTypeEnd; if (!cls_param || !transform) return; for (; cls_param->type; cls++, cls_param++) { cls->type = cls_param->type; cls->radius = cls_param->radius; mat4 mat = transform[cls_param->node_idx[0]]; mat4_transpose(&mat, &mat); mat4_mult_vec3_trans(&mat, &cls_param->pos[0], &cls->pos[0]); switch (cls->type) { case SkinParam::CollisionTypePlane: mat4_mult_vec3(&mat, &cls_param->pos[1], &cls->pos[1]); break; case SkinParam::CollisionTypeCapsulle: case SkinParam::CollisionTypeEllipse: mat = transform[cls_param->node_idx[1]]; mat4_transpose(&mat, &mat); mat4_mult_vec3_trans(&mat, &cls_param->pos[1], &cls->pos[1]); cls->vec_center = cls->pos[1] - cls->pos[0]; cls->vec_center_length_squared = vec3::length_squared(cls->vec_center); cls->vec_center_length = sqrtf(cls->vec_center_length_squared); if (cls->vec_center_length < 0.01f) cls->type = SkinParam::CollisionTypeBall; break; } } cls->type = SkinParam::CollisionTypeEnd; } // 0x140485410 static void OsageCollision__Work__update_cls_work(OsageCollision__Work* cls, vector_old_SkinParam__CollisionParam* cls_list, mat4* transform) { if (cls_list->begin == cls_list->end) { cls->type = SkinParam::CollisionTypeEnd; cls->radius = 0.0f; cls->pos[0] = 0.0f; cls->pos[1] = 0.0f; cls->vec_center = 0.0f; cls->vec_center_length = 0.0f; cls->vec_center_length_squared = 0.0f; cls->friction = 1.0f; } else OsageCollision__Work__update_cls_work(cls, cls_list->begin, transform); } static void rob_osage_coli_set(rob_osage* rob_osg, mat4* transform) { if (vector_old_length(rob_osg->skin_param_ptr->coli)) OsageCollision__Work__update_cls_work(rob_osg->coli, rob_osg->skin_param_ptr->coli.begin, transform); OsageCollision__Work__update_cls_work(rob_osg->coli_ring, &rob_osg->ring.skp_root_coli, transform); } // 0x140484780 static int32_t OsageCollision__cls_plane_oidashi(vec3* vec, const vec3* p, const vec3* p1, const vec3* p2, const float_t r) { float_t v5 = vec3::dot(*p, *p2) - vec3::dot(*p1, *p2) - r; if (v5 < 0.0f) { *vec = *p2 * -v5; return 1; } return 0; } // 0x140483B30 static int32_t OsageCollision__cls_aabb_oidashi(vec3* vec, const vec3* p, const OsageCollision__Work* cls, const float_t r) { vec3 v29; vec3 v30; for (int32_t i = 0; i < 3; i++) { float_t v13 = ((float_t*)p)[i]; float_t v14 = ((float_t*)&cls->pos[0])[i] - v13; ((float_t*)&v30)[i] = v14; if (v14 > r) return 0; v14 = v13 - (((float_t*)&cls->pos[0])[i] + ((float_t*)&cls->pos[1])[i]); ((float_t*)&v29)[i] = v14; if (v14 > r) 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 > r * r) return 0; if (v16 > 0.0f) *vec = v27 * v32 * (1.0f / v16) * (r - sqrtf(v16)); 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*)vec)[v26] -= ((float_t*)&v27)[v26] * (v25 - r); } return 1; } // 0x140485220 static int32_t OsageCollision__osage_cls(vec3* p, const float_t* cls_r, const OsageCollision__Work* cls, float_t* fric) { if (!cls) return 0; int32_t v8 = 0; while (cls->type != SkinParam::CollisionTypeEnd) { int32_t v11 = 0; vec3 v31 = 0.0f; switch (cls->type) { case SkinParam::CollisionTypeBall: v11 = OsageCollision__cls_ball_oidashi(&v31, p, &cls->pos[0], cls->radius + *cls_r); break; case SkinParam::CollisionTypeCapsulle: v11 = OsageCollision__cls_capsule_oidashi(&v31, p, cls, cls->radius + *cls_r); break; case SkinParam::CollisionTypePlane: v11 = OsageCollision__cls_plane_oidashi(&v31, p, &cls->pos[0], &cls->pos[1], *cls_r); break; case SkinParam::CollisionTypeEllipse: v11 = OsageCollision__cls_ellipse_oidashi(&v31, p, cls, cls->radius + *cls_r); break; case SkinParam::CollisionTypeAABB: v11 = OsageCollision__cls_aabb_oidashi(&v31, p, cls, *cls_r); break; } if (fric && v11 > 0 && *fric > cls->friction) *fric = cls->friction; *p += v31; v8 += v11; cls++; } return v8; } // 0x1404851C0 static int32_t OsageCollision__osage_cls_work_list(vec3* p, const float_t* cls_r, const OsageCollision* coli, float_t* fric) { if (vector_old_length(coli->work_list) && coli->work_list.end[-1].type) return OsageCollision__osage_cls(p, cls_r, coli->work_list.begin, fric); return 0; } // 0x140485180 static int32_t OsageCollision__osage_cls(const OsageCollision__Work* cls, vec3* p, const float_t* cls_r) { return OsageCollision__osage_cls(p, cls_r, cls, 0); } static void sub_14047ECA0(rob_osage* rob_osg, float_t step) { if (step <= 0.0f) return; OsageCollision__Work* coli = rob_osg->coli; OsageCollision__Work* coli_ring = rob_osg->coli_ring; OsageCollision* vec_coli = &rob_osg->ring.coli; if (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)OsageCollision__osage_cls_work_list(&i->trans, &data->skp_osg_node.coli_r, vec_coli, &i->field_CC); } else 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)OsageCollision__osage_cls_work_list(&i->trans, &data->skp_osg_node.coli_r, vec_coli, &i->field_CC); for (rob_osage_node** j = data->boc.begin; j != data->boc.end; j++) { rob_osage_node* k = *j; k->field_C8 += (float_t)OsageCollision__osage_cls(coli_ring, &k->trans, &data->skp_osg_node.coli_r); k->field_C8 += (float_t)OsageCollision__osage_cls(coli, &k->trans, &data->skp_osg_node.coli_r); } i->field_C8 += (float_t)OsageCollision__osage_cls(coli_ring, &i->trans, &data->skp_osg_node.coli_r); i->field_C8 += (float_t)OsageCollision__osage_cls(coli, &i->trans, &data->skp_osg_node.coli_r); } } 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; OsageCollision__Work* coli = rob_osg->coli; OsageCollision__Work* coli_ring = rob_osg->coli_ring; for (rob_osage_node* i = nodes->begin + 1; i != nodes->end; i++) { rob_osage_node_data* data = i->data_ptr; for (rob_osage_node** j = data->boc.begin; j != data->boc.end; j++) { rob_osage_node* v15 = *j; float_t v17 = (float_t)( OsageCollision__osage_capsule_cls(&i->trans, &v15->trans, &data->skp_osg_node.coli_r, coli) + OsageCollision__osage_capsule_cls(&i->trans, &v15->trans, &data->skp_osg_node.coli_r, coli_ring)); i->field_C8 += v17; v15->field_C8 += v17; } int32_t v18 = rob_osg->skin_param_ptr->coli_type; if (v18 && (v18 != 1 || i != nodes->begin + 1)) { float_t v20 = (float_t)( OsageCollision__osage_capsule_cls(&i[0].trans, &i[-1].trans, &data->skp_osg_node.coli_r, coli) + OsageCollision__osage_capsule_cls(&i[0].trans, &i[-1].trans, &data->skp_osg_node.coli_r, coli_ring)); i[0].field_C8 += v20; i[-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; OsageCollision__Work* coli = rob_osg->coli; OsageCollision__Work* coli_ring = rob_osg->coli_ring; OsageCollision* vec_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 = rob_osg->exp_data.position * *parent_scale; 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, false); } mat4_transpose(&v64, &v64); float_t v60 = -1000.0f; if (a5) { rob_osage_node* v16 = &rob_osg->nodes.begin[0]; float_t coli_r = v16->data_ptr->skp_osg_node.coli_r; float_t ring_height; if (v16->trans.x < rob_osg->ring.ring_rectangle_x - coli_r || v16->trans.z < rob_osg->ring.ring_rectangle_y - coli_r || 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) ring_height = rob_osg->ring.ring_out_height; else ring_height = rob_osg->ring.ring_height; v60 = ring_height + coli_r; } 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++) OsageCollision__cls_ball_oidashi(&v62, &v27->trans, &v30->trans, v27->data_ptr->skp_osg_node.coli_r + v30->data_ptr->skp_osg_node.coli_r); v27->trans += v62; } } 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)OsageCollision__osage_cls_work_list(&v35->trans, &skp_osg_node->coli_r, vec_coli, &v35->field_CC); if (!rob_osg->field_1F0F) { v35->field_C8 += (float_t)OsageCollision__osage_cls(coli_ring, &v35->trans, &skp_osg_node->coli_r); v35->field_C8 += (float_t)OsageCollision__osage_cls(coli, &v35->trans, &skp_osg_node->coli_r); } 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 = vec3::distance_squared(v35[0].trans, v35[-1].trans); bool v45; 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); v35->trans_diff = (v35->trans - v35->trans_orig) * v9; if (v35->field_C8 > 0.0f) { if (v37 > v35->field_CC) v37 = v35->field_CC; v35->trans_diff *= v37; } float_t v55 = vec3::length_squared(v35->trans_diff); if (v55 > v23 * v23) v35->trans_diff *= v23 / sqrtf(v55); 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; } } // 0x140480F40 static void rob_osage_set_nodes_external_force(rob_osage* rob_osg, vec3* external_force, float_t strength) { vec3 v4; if (external_force) v4 = *external_force; else v4 = 0.0f; size_t exf = rob_osg->osage_setting.exf; size_t v8 = 0; if (exf >= 4) { float_t strength4 = strength * strength * strength * strength; v8 = ((exf - 4) / 4 + 1) * 4; for (size_t v10 = v8 / 4; v10; v10--) v4 *= strength4; } if (v8 < exf) for (size_t v12 = exf - v8; v12; v12--) v4 *= strength; for (rob_osage_node* i = rob_osg->nodes.begin + 1; i != rob_osg->nodes.end; i++) { i->external_force = v4; v4 *= strength; } } // 0x140481540 static void rob_osage_set_nodes_force(rob_osage* rob_osg, float_t force) { for (rob_osage_node* i = rob_osg->nodes.begin + 1; i != rob_osg->nodes.end; i++) i->force = force; } static void sub_140480260(rob_osage* rob_osg, mat4* mat, vec3* parent_scale, float_t step, bool disable_external_force) { if (!disable_external_force) { rob_osage_set_nodes_external_force(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 stage, bool disable_external_force) { 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 (stage) { case 0: sub_1404803B0(&osg->rob, parent_node_mat, &parent_scale, osg->base.has_children_node); break; case 1: case 2: if ((stage == 1 && osg->base.field_58) || (stage == 2 && osg->rob.field_2A0)) { ExOsageBlock__SetWindDirection(osg); sub_14047C800(&osg->rob, parent_node_mat, &parent_scale, step, disable_external_force, true, osg->base.has_children_node); } 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, disable_external_force); 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) { scale = 1.0f / 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); dst->angle = vec3::lerp(src0->angle, src1->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); } // 0x14047E240 void rob_osage_set_osage_play_data(rob_osage* rob_osg, mat4* parent_mat, vec3* parent_scale, vector_old_opd_blend_data* opd_blend_data) { if (!vector_old_length(*opd_blend_data)) return; vec3 v63 = rob_osg->exp_data.position * *parent_scale; mat4 v85; mat4_transpose(parent_mat, &v85); mat4_mult_vec3_trans(&v85, &v63, &rob_osg->nodes.begin[0].trans); mat4_transpose(&v85, &v85); sub_14047F110(rob_osg, &v85, parent_scale, false); *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(parent_mat, parent_mat); size_t v17 = vector_old_length(*opd_blend_data) - 1; for (::opd_blend_data* i = opd_blend_data->end; i != opd_blend_data->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]; mat4_mult_vec3_trans(parent_mat, &v62, &v62); mat4_mult_vec3_trans(parent_mat, &v77, &v77); vec3 v82 = v62 * inv_blend + v77 * blend; 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); struc_477 v72; v72.angle = v64; v72.length = vec3::distance(v62, v22) * inv_blend + vec3::distance(v77, v25) * blend; sub_140482100(&j->field_1B0, i, &v72); v22 = v62; v25 = v77; } } mat4_transpose(parent_mat, parent_mat); 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; rob_osage_set_osage_play_data(&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 * 0.5f; 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); } static bool sub_14053D1B0(vec3* l_trans, vec3* r_trans, vec3* u_trans, vec3* d_trans, vec3* a5, vec3* a6, vec3* a7) { float_t length; *a5 = *d_trans - *u_trans; length = vec3::length_squared(*a5); if (length <= 0.000001f) return false; *a5 *= 1.0f / sqrtf(length); *a6 = vec3::cross(*r_trans - *l_trans, *a5); length = vec3::length_squared(*a6); if (length <= 0.000001f) return false; *a6 *= 1.0f / sqrtf(length); *a7 = vec3::normalize(vec3::cross(*a5, *a6)); return true; } static 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_transpose(&v33, &v33); mat4_mult(&v33, &v34, a2); mat4_transpose(a2, a2); } } static 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); }