Files
korenkonder_ReDIVA/src/DivaGL/bone_data.cpp
T

1603 lines
56 KiB
C++

/*
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);
}