diff --git a/src/CRE/Glitter/curve.cpp b/src/CRE/Glitter/curve.cpp index 772af5a7..85f5c2b4 100644 --- a/src/CRE/Glitter/curve.cpp +++ b/src/CRE/Glitter/curve.cpp @@ -4,7 +4,6 @@ */ #include "glitter.hpp" -#include "../../KKdLib/interpolation.hpp" namespace Glitter { #if defined(CRE_DEV) @@ -142,24 +141,28 @@ namespace Glitter { Curve::Key* next, KeyType key_type, Random* random) { if (key_type == KEY_CONSTANT) return F2RandomizeKey(GLT_VAL, curr, random); + else if (key_type == KEY_HERMITE) + return F2InterpolateHermite(GLT_VAL, curr, next, frame, random); + else + return F2InterpolateLinear(GLT_VAL, curr, next, frame, random); + } + float_t Curve::F2InterpolateHermite(GLT, Glitter::Curve::Key* curr, + Glitter::Curve::Key* next, float_t frame, Random* random) { + float_t next_val = F2RandomizeKey(GLT_VAL, next, random); + float_t curr_val = F2RandomizeKey(GLT_VAL, curr, random); + return InterpolateHermite(F2RandomizeKey(GLT_VAL, curr, random), + next_val - curr_val, curr->tangent2, next->tangent1, + (float_t)curr->frame, (float_t)next->frame, frame); + } + + float_t Curve::F2InterpolateLinear(GLT, Glitter::Curve::Key* curr, + Glitter::Curve::Key* next, float_t frame, Random* random) { float_t df = (float_t)(next->frame - curr->frame); - float_t t = (frame - (float_t)curr->frame) / df; - float_t val; - if (key_type == KEY_HERMITE) { - float_t t_1 = t - 1.0f; - float_t next_val = F2RandomizeKey(GLT_VAL, next, random); - float_t curr_val = F2RandomizeKey(GLT_VAL, curr, random); - val = F2RandomizeKey(GLT_VAL, curr, random); - val += t * t * (3.0f - 2.0f * t) * (next_val - curr_val) - + (t_1 * curr->tangent2 + t * next->tangent1) * t_1 * df; - } - else { - float_t curr_val = F2RandomizeKey(GLT_VAL, curr, random); - float_t next_val = F2RandomizeKey(GLT_VAL, next, random); - val = (1.0f - t) * curr_val + next_val * t; - } - return val; + float_t t = (frame - (float_t)curr->frame) / (float_t)(next->frame - curr->frame); + float_t curr_val = F2RandomizeKey(GLT_VAL, curr, random); + float_t next_val = F2RandomizeKey(GLT_VAL, next, random); + return curr_val * (1.0f - t) + next_val * t; } float_t Curve::F2Randomize(GLT, float_t value, Random* random) { @@ -188,42 +191,6 @@ namespace Glitter { return rand + key->value; } - void Curve::GetKeyIndices(std::vector* keys, - float_t frame, size_t* curr, size_t* next) { - size_t count = keys->size(); - if (count <= 1) { - *curr = 0; - *next = 0; - return; - } - - size_t first_key = 0; - Curve::Key* key = keys->data(); - size_t last_key = count - 1; - size_t temp = last_key / 2; - while (first_key <= last_key) { - temp = (last_key + first_key) / 2; - if (frame <= key[(temp + 1) % count].frame) { - if (frame >= key[temp].frame) - goto NextKey; - last_key = temp - 1; - } - else - first_key = temp + 1; - } - - if (frame > key[temp].frame) { - NextKey: - *curr = temp; - *next = temp + 1; - } - else { - *curr = temp - 1; - *next = temp; - } - *next %= count; - } - #if defined(CRE_DEV) void Curve::FitKeysIntoCurve(GLT) { size_t count = keys.size(); @@ -339,20 +306,21 @@ namespace Glitter { double_t tt1 = 0.0; double_t tt2 = 0.0; for (size_t j = 1; j < i - 1; j++) { - float_t df_1 = (float_t)(j * step); - float_t df_2 = (float_t)((j + 1) * step); - float_t _t1 = df_1 / (float_t)(i * step); - float_t _t2 = df_2 / (float_t)(i * step); + float_t _t1 = (float_t)(j * step) / (float_t)(i * step); + float_t _t2 = (float_t)((j + 1) * step) / (float_t)(i * step); float_t t1_1 = _t1 - 1.0f; float_t t2_1 = _t2 - 1.0f; float_t t1_t2_1 = a[j] - a[0] - (_t1 * 2.0f - 3.0f) * (_t1 * _t1) * (a[0] - a[i]); float_t t1_t2_2 = a[j + 1] - a[0] - (_t2 * 2.0f - 3.0f) * (_t2 * _t2) * (a[0] - a[i]); - t1_t2_1 /= df_1 * t1_1; - t1_t2_2 /= df_2 * t2_1; + t1_t2_1 /= t1_1 * _t1; + t1_t2_2 /= t2_1 * _t2; - tt1 += (t1_t2_1 * _t2 - t1_t2_2 * _t1) / (_t1 - _t2); - tt2 += (-t1_t2_1 * t2_1 + t1_t2_2 * t1_1) / (_t1 - _t2); + float_t t1 = -t1_t2_1 * _t2 + t1_t2_2 * _t1; + float_t t2 = t1_t2_1 * t2_1 - t1_t2_2 * t1_1; + + tt1 += t1; + tt2 += t2; } t1 = (float_t)(tt1 / (double_t)(i - 2)); t2 = (float_t)(tt2 / (double_t)(i - 2)); @@ -362,7 +330,7 @@ namespace Glitter { has_error_lerp = false; has_error_hermite = false; for (size_t j = 1; j < i; j++) { - float_t val = interpolate_chs_value(a[0], a[i], t1, t2, 0.0f, + float_t val = InterpolateHermite(a[0], a[i] - a[0], t1, t2, 0.0f, (float_t)(i * step), (float_t)(j * step)); float_t val_lerp = lerp_def(a[0], a[i], (float_t)j / (float_t)i); if (fabsf(val - a[0]) > reverse_bias[0]) { @@ -496,21 +464,17 @@ namespace Glitter { rand_range = curr_key->random_range; } else if (curr_key->type == KEY_HERMITE) { - val = interpolate_chs_value(curr_key->value, next_key->value, + val = InterpolateHermite(curr_key->value, next_key->value - curr_key->value, curr_key->tangent2, next_key->tangent1, (float_t)curr_key->frame, (float_t)next_key->frame, (float_t)frame); - rand_range = interpolate_chs_value(curr_key->random_range, next_key->random_range, - 0.0f, 0.0f, - (float_t)curr_key->frame, (float_t)next_key->frame, (float_t)frame); - float_t val1 = interpolate_chs_value(curr_key->value + curr_key->random_range, - next_key->value + next_key->random_range, - curr_key->tangent2, next_key->tangent1, + rand_range = InterpolateHermite(curr_key->random_range, + next_key->random_range - curr_key->random_range, 0.0f, 0.0f, (float_t)curr_key->frame, (float_t)next_key->frame, (float_t)frame); } else { - val = interpolate_linear_value(curr_key->value, next_key->value, + val = InterpolateLinear(curr_key->value, next_key->value, (float_t)curr_key->frame, (float_t)next_key->frame, (float_t)frame); - rand_range = interpolate_linear_value(curr_key->random_range, next_key->random_range, + rand_range = InterpolateLinear(curr_key->random_range, next_key->random_range, (float_t)curr_key->frame, (float_t)next_key->frame, (float_t)frame); } @@ -602,28 +566,32 @@ namespace Glitter { return true; } - float_t Curve::XInterpolate(float_t frame, - Curve::Key* curr, Curve::Key* next, KeyType key_type, Random* random) { + float_t Curve::XInterpolate(float_t frame, Curve::Key* curr, + Curve::Key* next, KeyType key_type, Random* random) { if (key_type == KEY_CONSTANT) return XRandomizeKey(curr, random); + else if (key_type == KEY_HERMITE) + return XInterpolateHermite(curr, next, frame, random); + else + return XInterpolateLinear(curr, next, frame, random); + } - float_t df = frame - (float_t)curr->frame; - float_t t = df / (float_t)(next->frame - curr->frame); - float_t val; - if (key_type == KEY_HERMITE) { - float_t t_1 = t - 1.0f; - float_t next_val = XRandomizeKey(next, random); - float_t curr_val = XRandomizeKey(curr, random); - val = XRandomizeKey(curr, random); - val += t * t * (3.0f - 2.0f * t) * (next_val - curr_val) - + (t_1 * curr->tangent2 + t * next->tangent1) * t_1 * df; - } - else { - float_t curr_val = XRandomizeKey(curr, random); - float_t next_val = XRandomizeKey(next, random); - val = (1.0f - t) * curr_val + next_val; - } - return val; + float_t Curve::XInterpolateHermite(Glitter::Curve::Key* curr, + Glitter::Curve::Key* next, float_t frame, Random* random) { + float_t next_val = XRandomizeKey(next, random); + float_t curr_val = XRandomizeKey(curr, random); + return InterpolateHermite(XRandomizeKey(curr, random), + next_val - curr_val, curr->tangent2, next->tangent1, + (float_t)curr->frame, (float_t)next->frame, frame); + } + + float_t Curve::XInterpolateLinear(Glitter::Curve::Key* curr, + Glitter::Curve::Key* next, float_t frame, Random* random) { + float_t df = (float_t)(next->frame - curr->frame); + float_t t = (frame - (float_t)curr->frame) / (float_t)(next->frame - curr->frame); + float_t curr_val = XRandomizeKey(curr, random); + float_t next_val = XRandomizeKey(next, random); + return curr_val * (1.0f - t) + next_val * t; } float_t Curve::XRandomize(float_t value, Random* random) { @@ -647,6 +615,42 @@ namespace Glitter { return rand + key->value; } + void Curve::GetKeyIndices(std::vector* keys, + float_t frame, size_t* curr, size_t* next) { + size_t count = keys->size(); + if (count <= 1) { + *curr = 0; + *next = 0; + return; + } + + size_t first_key = 0; + Curve::Key* key = keys->data(); + size_t last_key = count - 1; + size_t temp = last_key / 2; + while (first_key <= last_key) { + temp = (last_key + first_key) / 2; + if (frame <= key[(temp + 1) % count].frame) { + if (frame >= key[temp].frame) + goto NextKey; + last_key = temp - 1; + } + else + first_key = temp + 1; + } + + if (frame > key[temp].frame) { + NextKey: + *curr = temp; + *next = temp + 1; + } + else { + *curr = temp - 1; + *next = temp; + } + *next %= count; + } + #if defined(CRE_DEV) static float_t glitter_curve_add_key(bool has_error, bool has_error_lerp, bool has_error_hermite, float_t* a, float_t* b, int32_t frame, diff --git a/src/CRE/Glitter/glitter.hpp b/src/CRE/Glitter/glitter.hpp index dfb9567c..4d63e268 100644 --- a/src/CRE/Glitter/glitter.hpp +++ b/src/CRE/Glitter/glitter.hpp @@ -542,6 +542,10 @@ namespace Glitter { float_t* value, int32_t random_value, Random* random); float_t F2Interpolate(GLT, float_t frame, Curve::Key* curr, Curve::Key* next, KeyType key_type, Random* random); + float_t F2InterpolateHermite(GLT, Glitter::Curve::Key* curr, + Glitter::Curve::Key* next, float_t frame, Random* random); + float_t F2InterpolateLinear(GLT, Glitter::Curve::Key* curr, + Glitter::Curve::Key* next, float_t frame, Random* random); float_t F2Randomize(GLT, float_t value, Random* random); float_t F2RandomizeKey(GLT, Curve::Key* key, Random* random); #if defined(CRE_DEV) @@ -552,11 +556,35 @@ namespace Glitter { float_t* value, int32_t random_value, Random* random); float_t XInterpolate(float_t frame, Curve::Key* curr, Curve::Key* next, KeyType key_type, Random* random); + float_t XInterpolateHermite(Glitter::Curve::Key* curr, + Glitter::Curve::Key* next, float_t frame, Random* random); + float_t XInterpolateLinear(Glitter::Curve::Key* curr, + Glitter::Curve::Key* next, float_t frame, Random* random); float_t XRandomize(float_t value, Random* random); float_t XRandomizeKey(Curve::Key* key, Random* random); static void GetKeyIndices(std::vector* keys, float_t frame, size_t* curr, size_t* next); + + template + inline static T InterpolateHermite(const T p, const T dv, + const T t1, const T t2, const T f1, const T f2, const T f) { + const T df = (f2 - f1); + const T t = (f - f1) / df; + const T t_2 = t * t; + const T t_3 = t_2 * t; + return p + + (t_3 - 2.0f * t_2 + t) * (t1 * df) + + (t_3 - t_2) * (t2 * df) + + (3.0f * t_2 - 2.0f * t_3) * dv; + }; + + template + inline static T InterpolateLinear(const T p1, const T p2, + const T f1, const T f2, const T f) { + const T t = (f - f1) / (f2 - f1); + return (1.0f - t) * p1 + t * p2; + }; }; class ItemBase { diff --git a/src/CRE/auth_2d.cpp b/src/CRE/auth_2d.cpp index 41576ef4..ab7cc85e 100644 --- a/src/CRE/auth_2d.cpp +++ b/src/CRE/auth_2d.cpp @@ -975,7 +975,8 @@ void AetObj::DispSpriteSource(const mat4& mat, const aet_layer* layer, auto elem_replace = sprite_replace.find(sprite_index); if (elem_replace != sprite_replace.end() && elem_replace->second != -1) { const spr_db_spr* spr = spr_db->get_spr_by_id(elem_replace->second); - const spr_db_spr_set* spr_set = spr_db->get_spr_set_by_index(spr->info.set_index & 0xFFF); + //const spr_db_spr_set* spr_set = spr_db->get_spr_set_by_index(spr->info.set_index & 0x0FFF); + const spr_db_spr_set* spr_set = spr_db->get_spr_set_by_index(spr->info.set_index & 0x3FFF); if (sprite_manager_get_set_ready(spr_set->id, spr_db)) args.id.index = elem_replace->second; } @@ -1479,26 +1480,31 @@ void AetMgr::Basic() { uint32_t AetMgr::AddSetModern() { uint32_t index = this->set_counter; - for (; index <= 0x0FFF; index++) { + //for (; index <= 0x0FFF; index++) { + for (; index <= 0x3FFF; index++) { auto elem = sets.find(0x8000 | index); if (elem == sets.end()) break; } - if (!index || index > 0x0FFF) { - for (index = 1; index <= 0x0FFF; index++) { + //if (!index || index > 0x0FFF) { + if (!index || index > 0x3FFF) { + //for (index = 1; index <= 0x0FFF; index++) { + for (index = 1; index <= 0x3FFF; index++) { auto elem = sets.find(0x8000 | index); if (elem == sets.end()) break; } - if (!index || index > 0x0FFF) + //if (!index || index > 0x0FFF) + if (!index || index > 0x3FFF) return 0x8000; } sets.insert({ 0x8000 | index, AetSet(0x8000 | index) }); set_counter = index + 1; - if (index + 1 > 0x0FFF) + //if (index + 1 > 0x0FFF) + if (index + 1 > 0x3FFF) set_counter = 1; return 0x8000 | index; } diff --git a/src/CRE/auth_3d.cpp b/src/CRE/auth_3d.cpp index 90b2400a..b1240392 100644 --- a/src/CRE/auth_3d.cpp +++ b/src/CRE/auth_3d.cpp @@ -2906,6 +2906,96 @@ namespace auth_3d_detail { } } +static void a3da_msgpack_read_key(a3da_key& key, msgpack* msg) { + if (msg->read_bool("remove")) { + key = {}; + return; + } + + if (msg->read_bool("ignore_tangents") && key.keys.size()) { + float_t ep_pre_val = key.keys.front().tangent1; + float_t ep_post_val = key.keys.back().tangent2; + for (kft3& i : key.keys) { + i.tangent1 = 0.0f; + i.tangent2 = 0.0f; + } + key.keys.front().tangent1 = ep_pre_val; + key.keys.back().tangent2 = ep_post_val; + } + + msgpack* change_type = msg->read("change_type"); + if (change_type) { + a3da_key_type type = (a3da_key_type)change_type->read_int32_t(); + switch (type) { + case A3DA_KEY_NONE: + key.type = A3DA_KEY_NONE; + break; + case A3DA_KEY_LINEAR: + case A3DA_KEY_HERMITE: + case A3DA_KEY_HOLD: + switch (key.type) { + case A3DA_KEY_LINEAR: + case A3DA_KEY_HERMITE: + case A3DA_KEY_HOLD: + key.type = type; + break; + } + break; + } + } +} + +static void a3da_msgpack_read_rgba(a3da_rgba& rgba, msgpack* msg) { + if (msg->read_bool("remove")) { + rgba = {}; + return; + } + + if (rgba.flags & A3DA_RGBA_R) { + msgpack* r = msg->read_map("r"); + if (r) + a3da_msgpack_read_key(rgba.r, r); + + if (rgba.r.type == A3DA_KEY_NONE) { + rgba.r = {}; + enum_and(rgba.flags, ~A3DA_RGBA_R); + } + } + + if (rgba.flags & A3DA_RGBA_G) { + msgpack* g = msg->read_map("g"); + if (g) + a3da_msgpack_read_key(rgba.g, g); + + if (rgba.g.type == A3DA_KEY_NONE) { + rgba.g = {}; + enum_and(rgba.flags, ~A3DA_RGBA_G); + } + } + + if (rgba.flags & A3DA_RGBA_B) { + msgpack* b = msg->read_map("b"); + if (b) + a3da_msgpack_read_key(rgba.b, b); + + if (rgba.b.type == A3DA_KEY_NONE) { + rgba.b = {}; + enum_and(rgba.flags, ~A3DA_RGBA_B); + } + } + + if (rgba.flags & A3DA_RGBA_A) { + msgpack* a = msg->read_map("a"); + if (a) + a3da_msgpack_read_key(rgba.a, a); + + if (rgba.a.type == A3DA_KEY_NONE) { + rgba.a = {}; + enum_and(rgba.flags, ~A3DA_RGBA_A); + } + } +} + static void a3da_msgpack_read(const char* path, const char* file, a3da* auth_file) { if (!path_check_directory_exists(path)) return; @@ -2961,6 +3051,53 @@ static void a3da_msgpack_read(const char* path, const char* file, a3da* auth_fil } } + msgpack* material_lists = msg.read_array("material_list"); + if (material_lists) { + msgpack_array* ptr = material_lists->data.arr; + for (msgpack& i : *ptr) { + msgpack& material_list = i; + + std::string name = material_list.read_string("name"); + uint32_t name_hash = hash_string_murmurhash(name); + + bool remove = material_list.read_bool("remove"); + + auto j_begin = auth_file->material_list.begin(); + auto j_end = auth_file->material_list.end(); + for (auto j = j_begin; j != j_end; j++) { + if (name_hash != hash_string_murmurhash(j->name)) + continue; + + if (remove) { + auth_file->material_list.erase(j); + break; + } + + if (j->flags & A3DA_MATERIAL_LIST_BLEND_COLOR) { + msgpack* blend_color = material_list.read_map("blend_color"); + if (blend_color) { + a3da_msgpack_read_rgba(j->blend_color, blend_color); + if (!j->blend_color.flags) + enum_and(j->flags, ~A3DA_MATERIAL_LIST_BLEND_COLOR); + } + } + + if (j->flags & A3DA_MATERIAL_LIST_EMISSION) { + msgpack* emission = material_list.read_map("emission"); + if (emission) { + a3da_msgpack_read_rgba(j->emission, emission); + if (!j->emission.flags) + enum_and(j->flags, ~A3DA_MATERIAL_LIST_EMISSION); + } + } + + if (!j->flags) + auth_file->material_list.erase(j); + break; + } + } + } + msgpack* objhrcs = msg.read_array("objhrc"); if (objhrcs) { msgpack_array* ptr = objhrcs->data.arr; diff --git a/src/CRE/object.cpp b/src/CRE/object.cpp index dd9f282e..5b60ec00 100644 --- a/src/CRE/object.cpp +++ b/src/CRE/object.cpp @@ -871,7 +871,7 @@ void object_material_msgpack_read(const char* path, const char* set_name, uint32_t id = hash_string_murmurhash(name); ids.push_back(id); - tex_db->texture.push_back({}); + tex_db->texture.emplace_back(); texture_info* info = &tex_db->texture.back(); info->name.assign(name); info->name_hash = hash_string_murmurhash(info->name); diff --git a/src/CRE/sprite.cpp b/src/CRE/sprite.cpp index 6ac6ce14..0f678bf4 100644 --- a/src/CRE/sprite.cpp +++ b/src/CRE/sprite.cpp @@ -547,26 +547,31 @@ namespace spr { uint32_t SpriteManager::AddSetModern() { uint32_t index = this->set_counter; - for (; index <= 0x0FFF; index++) { + //for (; index <= 0x0FFF; index++) { + for (; index <= 0x3FFF; index++) { auto elem = sets.find(0x8000 | index); if (elem == sets.end()) break; } - if (!index || index > 0x0FFF) { - for (index = 1; index <= 0x0FFF; index++) { + //if (!index || index >= 0x0FFF) { + if (!index || index > 0x3FFF) { + //for (index = 1; index <= 0x0FFF; index++) { + for (index = 1; index <= 0x3FFF; index++) { auto elem = sets.find(0x8000 | index); if (elem == sets.end()) break; } - if (!index || index > 0x0FFF) + //if (!index || index > 0x0FFF) + if (!index || index > 0x3FFF) return 0x8000; } sets.insert({ 0x8000 | index, SprSet(0x8000 | index) }); set_counter = index + 1; - if (index + 1 > 0x0FFF) + //if (index + 1 > 0x0FFF) + if (index + 1 > 0x3FFF) set_counter = 1; return 0x8000 | index; } @@ -1673,14 +1678,16 @@ SprSet::~SprSet() { } const char* SprSet::GetName(spr_info info) { - if (info.set_index & 0x1000) + //if (info.set_index & 0x1000) + if (info.set_index & 0x4000) return spr_set->texname[info.index]; else return spr_set->sprname[info.index]; } rectangle SprSet::GetRectangle(spr_info info) { - if (info.set_index & 0x1000) { + //if (info.set_index & 0x1000) { + if (info.set_index & 0x4000) { texture* tex = textures[info.index]; return { 0.0f, 0.0f, (float_t)tex->width, (float_t)tex->height }; } @@ -1691,14 +1698,16 @@ rectangle SprSet::GetRectangle(spr_info info) { } resolution_mode SprSet::GetResolutionMode(spr_info info) { - if (info.set_index & 0x1000) + //if (info.set_index & 0x1000) + if (info.set_index & 0x4000) return RESOLUTION_MODE_HD; else return spr_set->sprdata[info.index].resolution_mode; } texture* SprSet::GetTexture(spr_info info) { - if (info.set_index & 0x1000) + //if (info.set_index & 0x1000) + if (info.set_index & 0x4000) return textures[info.index]; else return textures[spr_set->sprinfo[info.index].texid]; @@ -1816,7 +1825,8 @@ bool SprSet::LoadTexture() { return false; std::vector ids(spr_set->num_of_texture); - uint32_t set_index = (uint32_t)(0x1000 | index & 0x0FFF); + //uint32_t set_index = (uint32_t)(0x1000 | index & 0x0FFF); + uint32_t set_index = (uint32_t)(0x4000 | index & 0x3FFF); uint32_t index = 0; for (uint32_t& i : ids) i = (set_index << 16) | index++; @@ -1831,7 +1841,8 @@ bool SprSet::LoadTextureModern(const void* data, size_t size) { return false; std::vector ids(spr_set->num_of_texture); - uint32_t set_index = (uint32_t)(0x8000 | 0x1000 | index & 0x0FFF); + //uint32_t set_index = (uint32_t)(0x8000 | 0x1000 | index & 0x0FFF); + uint32_t set_index = (uint32_t)(0x8000 | 0x4000 | index & 0x3FFF); uint32_t index = 0; for (uint32_t& i : ids) i = (set_index << 16) | index++; diff --git a/src/KKdLib/database/sprite.cpp b/src/KKdLib/database/sprite.cpp index 4196a554..947ca00b 100644 --- a/src/KKdLib/database/sprite.cpp +++ b/src/KKdLib/database/sprite.cpp @@ -278,7 +278,8 @@ void sprite_database::add(sprite_database_file* spr_db_file) { spr.id = j.id; spr.name.assign(j.name); spr.name_hash = hash_string_murmurhash(spr.name); - spr.info = { j.index, (uint16_t)((j.texture ? 0x1000 : 0x0000) | spr_set.index) }; + //spr.info = { j.index, (uint16_t)((j.texture ? 0x1000 : 0x0000) | spr_set.index) }; + spr.info = { j.index, (uint16_t)((j.texture ? 0x4000 : 0x0000) | spr_set.index) }; spr.load_count = 1; spr_ids.push_back({ spr.id, &spr }); @@ -360,7 +361,8 @@ void sprite_database::parse(const spr_db_spr_set_file* set_file, spr->id = id; spr->name.assign(i.name); spr->name_hash = hash_string_murmurhash(spr->name); - spr->info = { i.index, (uint16_t)((i.texture ? 0x1000 : 0x0000) | set_index) }; + //spr->info = { i.index, (uint16_t)((i.texture ? 0x1000 : 0x0000) | set_index) }; + spr->info = { i.index, (uint16_t)((i.texture ? 0x4000 : 0x0000) | set_index) }; spr->load_count++; spr_ids.push_back({ spr->id, spr }); @@ -473,7 +475,8 @@ const spr_db_spr* sprite_database::get_spr_by_set_id_index(uint32_t set_id, uint } const spr_db_spr* sprite_database::get_tex_by_set_id_index(uint32_t set_id, uint32_t index) const { - auto elem = spr_indices.find({ (uint16_t)index, (uint16_t)(0x1000 | get_spr_set_by_id(set_id)->index) }); + //auto elem = spr_indices.find({ (uint16_t)index, (uint16_t)(0x1000 | get_spr_set_by_id(set_id)->index) }); + auto elem = spr_indices.find({ (uint16_t)index, (uint16_t)(0x4000 | get_spr_set_by_id(set_id)->index) }); if (elem != spr_indices.end()) return elem->second; return &spr_db_spr_null; diff --git a/src/KKdLib/interpolation.cpp b/src/KKdLib/interpolation.cpp index 8c9cd9df..4d3c7d3a 100644 --- a/src/KKdLib/interpolation.cpp +++ b/src/KKdLib/interpolation.cpp @@ -13,22 +13,34 @@ void interpolate_chs_reverse_value(float_t* arr, size_t length, if (!arr || length < 2 || f - f1 + 1 >= length || f < 1 || f < f1 || f + 2 > f2) return; - float_t df_1 = (float_t)(f - f1); - float_t df_2 = (float_t)(f - f1 + 1); - float_t _t1 = df_1 / (float_t)(f2 - f1); - float_t _t2 = df_2 / (float_t)(f2 - f1); - float_t t1_1 = _t1 - 1.0f; - float_t t2_1 = _t2 - 1.0f; + float_t _t1 = (float_t)(f - f1) / (float_t)(f2 - f1); + float_t _t2 = (float_t)(f - f1 + 1) / (float_t)(f2 - f1); + float_t t1_2 = _t1 * _t1; + float_t t2_2 = _t2 * _t2; + float_t t1_3 = t1_2 * _t1; + float_t t2_3 = t2_2 * _t2; + float_t t1_23 = 3.0f * t1_2; + float_t t2_23 = 3.0f * t2_2; + float_t t1_32 = 2.0f * t1_3; + float_t t2_32 = 2.0f * t2_3; - float_t t1_t2_1 = arr[f] - (1.0f + 2.0f * _t1) * (t1_1 * t1_1) * arr[f1] - - _t1 * _t1 * (3.0f - 2.0f * _t1) * arr[f2]; - float_t t1_t2_2 = arr[f + 1] - (1.0f + 2.0f * _t2) * (t2_1 * t2_1) * arr[f1] - - _t2 * _t2 * (3.0f - 2.0f * _t2) * arr[f2]; - t1_t2_1 /= df_1 * t1_1; - t1_t2_2 /= df_2 * t2_1; + float_t h00_1 = t1_32 - t1_23 + 1.0f; + float_t h00_2 = t2_32 - t2_23 + 1.0f; + float_t h01_1 = t1_23 - t1_32; + float_t h01_2 = t2_23 - t2_32; + float_t h10_1 = t1_3 - 2.0f * t1_2 + _t1; + float_t h10_2 = t2_3 - 2.0f * t2_2 + _t2; + float_t h11_1 = t1_3 - t1_2; + float_t h11_2 = t2_3 - t2_2; - t1 = (t1_t2_1 * _t2 - t1_t2_2 * _t1) / (_t1 - _t2); - t2 = (-t1_t2_1 * t2_1 + t1_t2_2 * t1_1) / (_t1 - _t2); + float_t t1_t2_1 = (arr[f] - h00_1 * arr[f1] - h01_1 * arr[f2]); + float_t t1_t2_2 = (arr[f + 1] - h00_2 * arr[f1] - h01_2 * arr[f2]); + + t1_t2_1 /= (t1_2 - _t1) * (t2_2 - _t2); + t1_t2_2 /= (t1_2 - _t1) * (t2_2 - _t2); + + t1 = -h11_2 * t1_t2_1 + h11_1 * t1_t2_2; + t2 = h10_2 * t1_t2_1 - h10_1 * t1_t2_2; } void interpolate_chs_reverse(float_t* arr, size_t length, diff --git a/src/KKdLib/interpolation.hpp b/src/KKdLib/interpolation.hpp index c833d6bf..c80ab38f 100644 --- a/src/KKdLib/interpolation.hpp +++ b/src/KKdLib/interpolation.hpp @@ -12,72 +12,69 @@ inline float_t interpolate_linear_value(const float_t p1, const float_t p2, const float_t f1, const float_t f2, const float_t f) { + if (p1 == p2) + return p1; + float_t t = (f - f1) / (f2 - f1); return (1.0f - t) * p1 + t * p2; } inline vec2 interpolate_linear_value(const vec2 p1, const vec2 p2, const vec2 f1, const vec2 f2, const vec2 f) { - __m128 _p1; - __m128 _p2; - __m128 _f1; - __m128 _f2; - __m128 _f; - _p1 = vec2::load_xmm(p1); - _p2 = vec2::load_xmm(p2); - _f1 = vec2::load_xmm(f1); - _f2 = vec2::load_xmm(f2); - _f = vec2::load_xmm(f); + if (p1 == p2) + return p1; + + __m128 _p1 = vec2::load_xmm(p1); + __m128 _p2 = vec2::load_xmm(p2); + __m128 _f1 = vec2::load_xmm(f1); + __m128 _f2 = vec2::load_xmm(f2); + __m128 _f = vec2::load_xmm(f); const __m128 _1 = vec4::load_xmm(1.0f); __m128 t = _mm_div_ps(_mm_sub_ps(_f, _f1), _mm_sub_ps(_f2, _f1)); - __m128 t1 = _mm_sub_ps(_1, t); - return vec2::store_xmm(_mm_add_ps(_mm_mul_ps(_p1, t1), _mm_mul_ps(_p2, t))); + return vec2::store_xmm(_mm_add_ps(_mm_mul_ps(_p1, _mm_sub_ps(_1, t)), _mm_mul_ps(_p2, t))); } inline vec3 interpolate_linear_value(const vec3 p1, const vec3 p2, const vec3 f1, const vec3 f2, const vec3 f) { - __m128 _p1; - __m128 _p2; - __m128 _f1; - __m128 _f2; - __m128 _f; - _p1 = vec3::load_xmm(p1); - _p2 = vec3::load_xmm(p2); - _f1 = vec3::load_xmm(f1); - _f2 = vec3::load_xmm(f2); - _f = vec3::load_xmm(f); + if (p1 == p2) + return p1; + + __m128 _p1 = vec3::load_xmm(p1); + __m128 _p2 = vec3::load_xmm(p2); + __m128 _f1 = vec3::load_xmm(f1); + __m128 _f2 = vec3::load_xmm(f2); + __m128 _f = vec3::load_xmm(f); const __m128 _1 = vec4::load_xmm(1.0f); __m128 t = _mm_div_ps(_mm_sub_ps(_f, _f1), _mm_sub_ps(_f2, _f1)); - __m128 t1 = _mm_sub_ps(_1, t); - return vec3::store_xmm(_mm_add_ps(_mm_mul_ps(_p1, t1), _mm_mul_ps(_p2, t))); + return vec3::store_xmm(_mm_add_ps(_mm_mul_ps(_p1, _mm_sub_ps(_1, t)), _mm_mul_ps(_p2, t))); } inline vec4 interpolate_linear_value(const vec4 p1, const vec4 p2, const vec4 f1, const vec4 f2, const vec4 f) { - __m128 _p1; - __m128 _p2; - __m128 _f1; - __m128 _f2; - __m128 _f; - _p1 = vec4::load_xmm(p1); - _p2 = vec4::load_xmm(p2); - _f1 = vec4::load_xmm(f1); - _f2 = vec4::load_xmm(f2); - _f = vec4::load_xmm(f); + if (p1 == p2) + return p1; + + __m128 _p1 = vec4::load_xmm(p1); + __m128 _p2 = vec4::load_xmm(p2); + __m128 _f1 = vec4::load_xmm(f1); + __m128 _f2 = vec4::load_xmm(f2); + __m128 _f = vec4::load_xmm(f); const __m128 _1 = vec4::load_xmm(1.0f); __m128 t = _mm_div_ps(_mm_sub_ps(_f, _f1), _mm_sub_ps(_f2, _f1)); - __m128 t1 = _mm_sub_ps(_1, t); - return vec4::store_xmm(_mm_add_ps(_mm_mul_ps(_p1, t1), _mm_mul_ps(_p2, t))); + return vec4::store_xmm(_mm_add_ps(_mm_mul_ps(_p1, _mm_sub_ps(_1, t)), _mm_mul_ps(_p2, t))); } inline std::vector interpolate_linear(float_t p1, float_t p2, size_t f1, size_t f2) { size_t length = f2 - f1 + 1; + if (p1 == p2) + return std::vector(length, p1); + std::vector arr(length); float_t* a = arr.data(); for (size_t i = 0, j = length; j; i++, j--, a++) @@ -90,116 +87,136 @@ inline float_t interpolate_chs_value(const float_t p1, const float_t p2, const float_t t1, const float_t t2, const float_t f1, const float_t f2, const float_t f) { if (p1 == p2 && fabsf(t1) == 0.0f && fabsf(t2) == 0.0f) return p1; - float_t df = f - f1; - float_t t = df / (f2 - f1); - float_t t_1 = t - 1.0f; - return (t_1 * t1 + t * t2) * df * t_1 - + t * t * (3.0f - 2.0f * t) * p2 - + (1.0f + 2.0f * t) * (t_1 * t_1) * p1; + + float_t df = f2 - f1; + float_t t = (f - f1) / df; + float_t t_2 = t * t; + float_t t_3 = t_2 * t; + float_t t_23 = 3.0f * t_2; + float_t t_32 = 2.0f * t_3; + + float_t h00 = t_32 - t_23 + 1.0f; + float_t h01 = t_23 - t_32; + float_t h10 = t_3 - 2.0f * t_2 + t; + float_t h11 = t_3 - t_2; + + return h00 * p1 + h01 * p2 + h10 * (t1 * df) + h11 * (t2 * df); } inline vec2 interpolate_chs_value(const vec2 p1, const vec2 p2, const vec2 t1, const vec2 t2, const vec2 f1, const vec2 f2, const vec2 f) { if (p1 == p2 && vec2::abs(t1) == 0.0f && vec2::abs(t2) == 0.0f) return p1; - __m128 _p1; - __m128 _p2; - __m128 _t1; - __m128 _t2; - __m128 _f1; - __m128 _f2; - __m128 _f; - _p1 = vec2::load_xmm(p1); - _p2 = vec2::load_xmm(p2); - _t1 = vec2::load_xmm(t1); - _t2 = vec2::load_xmm(t2); - _f1 = vec2::load_xmm(f1); - _f2 = vec2::load_xmm(f2); - _f = vec2::load_xmm(f); + + __m128 _p1 = vec2::load_xmm(p1); + __m128 _p2 = vec2::load_xmm(p2); + __m128 _t1 = vec2::load_xmm(t1); + __m128 _t2 = vec2::load_xmm(t2); + __m128 _f1 = vec2::load_xmm(f1); + __m128 _f2 = vec2::load_xmm(f2); + __m128 _f = vec2::load_xmm(f); const __m128 _1 = vec4::load_xmm(1.0f); const __m128 _2 = vec4::load_xmm(2.0f); const __m128 _3 = vec4::load_xmm(3.0f); - __m128 df = _mm_sub_ps(_f, _f1); - __m128 t = _mm_div_ps(df, _mm_sub_ps(_f2, _f1)); - __m128 t_1 = _mm_sub_ps(t, _1); + __m128 df = _mm_sub_ps(_f2, _f1); + __m128 t = _mm_div_ps(_mm_sub_ps(_f, _f1), df); + __m128 t_2 = _mm_mul_ps(t, t); + __m128 t_3 = _mm_mul_ps(t_2, t); + __m128 t_23 = _mm_mul_ps(_3, t_2); + __m128 t_32 = _mm_mul_ps(_2, t_3); - _p1 = _mm_mul_ps(_mm_mul_ps(_mm_add_ps(_1, _mm_mul_ps(_2, t)), _mm_mul_ps(t_1, t_1)), _p1); - _p2 = _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(t, t), _mm_sub_ps(_3, _mm_mul_ps(_2, t))), _p2); - __m128 tangent = _mm_mul_ps(_mm_add_ps(_mm_mul_ps(t_1, _t1), _mm_mul_ps(t, _t2)), _mm_mul_ps(df, t_1)); - return vec2::store_xmm(_mm_add_ps(_mm_add_ps(tangent, _p2), _p1)); + __m128 h00 = _mm_add_ps(_mm_sub_ps(t_32, t_23), _1); + __m128 h01 = _mm_sub_ps(t_23, t_32); + __m128 h10 = _mm_add_ps(_mm_sub_ps(t_3, _mm_mul_ps(_2, t_2)), t); + __m128 h11 = _mm_sub_ps(t_3, t_2); + + _p1 = _mm_mul_ps(h00, _p1); + _p2 = _mm_mul_ps(h01, _p2); + _t1 = _mm_mul_ps(h10, _mm_mul_ps(_t1, df)); + _t2 = _mm_mul_ps(h11, _mm_mul_ps(_t2, df)); + return vec2::store_xmm(_mm_add_ps(_mm_add_ps(_p1, _p2), _mm_add_ps(_t1, _t2))); } inline vec3 interpolate_chs_value(const vec3 p1, const vec3 p2, const vec3 t1, const vec3 t2, const vec3 f1, const vec3 f2, const vec3 f) { if (p1 == p2 && vec3::abs(t1) == 0.0f && vec3::abs(t2) == 0.0f) return p1; - __m128 _p1; - __m128 _p2; - __m128 _t1; - __m128 _t2; - __m128 _f1; - __m128 _f2; - __m128 _f; - _p1 = vec3::load_xmm(p1); - _p2 = vec3::load_xmm(p2); - _t1 = vec3::load_xmm(t1); - _t2 = vec3::load_xmm(t2); - _f1 = vec3::load_xmm(f1); - _f2 = vec3::load_xmm(f2); - _f = vec3::load_xmm(f); + + __m128 _p1 = vec3::load_xmm(p1); + __m128 _p2 = vec3::load_xmm(p2); + __m128 _t1 = vec3::load_xmm(t1); + __m128 _t2 = vec3::load_xmm(t2); + __m128 _f1 = vec3::load_xmm(f1); + __m128 _f2 = vec3::load_xmm(f2); + __m128 _f = vec3::load_xmm(f); const __m128 _1 = vec4::load_xmm(1.0f); const __m128 _2 = vec4::load_xmm(2.0f); const __m128 _3 = vec4::load_xmm(3.0f); - __m128 df = _mm_sub_ps(_f, _f1); - __m128 t = _mm_div_ps(df, _mm_sub_ps(_f2, _f1)); - __m128 t_1 = _mm_sub_ps(t, _1); + __m128 df = _mm_sub_ps(_f2, _f1); + __m128 t = _mm_div_ps(_mm_sub_ps(_f, _f1), df); + __m128 t_2 = _mm_mul_ps(t, t); + __m128 t_3 = _mm_mul_ps(t_2, t); + __m128 t_23 = _mm_mul_ps(_3, t_2); + __m128 t_32 = _mm_mul_ps(_2, t_3); - _p1 = _mm_mul_ps(_mm_mul_ps(_mm_add_ps(_1, _mm_mul_ps(_2, t)), _mm_mul_ps(t_1, t_1)), _p1); - _p2 = _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(t, t), _mm_sub_ps(_3, _mm_mul_ps(_2, t))), _p2); - __m128 tangent = _mm_mul_ps(_mm_add_ps(_mm_mul_ps(t_1, _t1), _mm_mul_ps(t, _t2)), _mm_mul_ps(df, t_1)); - return vec3::store_xmm(_mm_add_ps(_mm_add_ps(tangent, _p2), _p1)); + __m128 h00 = _mm_add_ps(_mm_sub_ps(t_32, t_23), _1); + __m128 h01 = _mm_sub_ps(t_23, t_32); + __m128 h10 = _mm_add_ps(_mm_sub_ps(t_3, _mm_mul_ps(_2, t_2)), t); + __m128 h11 = _mm_sub_ps(t_3, t_2); + + _p1 = _mm_mul_ps(h00, _p1); + _p2 = _mm_mul_ps(h01, _p2); + _t1 = _mm_mul_ps(h10, _mm_mul_ps(_t1, df)); + _t2 = _mm_mul_ps(h11, _mm_mul_ps(_t2, df)); + return vec3::store_xmm(_mm_add_ps(_mm_add_ps(_p1, _p2), _mm_add_ps(_t1, _t2))); } inline vec4 interpolate_chs_value(const vec4 p1, const vec4 p2, const vec4 t1, const vec4 t2, const vec4 f1, const vec4 f2, const vec4 f) { if (p1 == p2 && vec4::abs(t1) == 0.0f && vec4::abs(t2) == 0.0f) return p1; - __m128 _p1; - __m128 _p2; - __m128 _t1; - __m128 _t2; - __m128 _f1; - __m128 _f2; - __m128 _f; - _p1 = vec4::load_xmm(p1); - _p2 = vec4::load_xmm(p2); - _t1 = vec4::load_xmm(t1); - _t2 = vec4::load_xmm(t2); - _f1 = vec4::load_xmm(f1); - _f2 = vec4::load_xmm(f2); - _f = vec4::load_xmm(f); + + __m128 _p1 = vec4::load_xmm(p1); + __m128 _p2 = vec4::load_xmm(p2); + __m128 _t1 = vec4::load_xmm(t1); + __m128 _t2 = vec4::load_xmm(t2); + __m128 _f1 = vec4::load_xmm(f1); + __m128 _f2 = vec4::load_xmm(f2); + __m128 _f = vec4::load_xmm(f); const __m128 _1 = vec4::load_xmm(1.0f); const __m128 _2 = vec4::load_xmm(2.0f); const __m128 _3 = vec4::load_xmm(3.0f); - __m128 df = _mm_sub_ps(_f, _f1); - __m128 t = _mm_div_ps(df, _mm_sub_ps(_f2, _f1)); - __m128 t_1 = _mm_sub_ps(t, _1); + __m128 df = _mm_sub_ps(_f2, _f1); + __m128 t = _mm_div_ps(_mm_sub_ps(_f, _f1), df); + __m128 t_2 = _mm_mul_ps(t, t); + __m128 t_3 = _mm_mul_ps(t_2, t); + __m128 t_23 = _mm_mul_ps(_3, t_2); + __m128 t_32 = _mm_mul_ps(_2, t_3); - _p1 = _mm_mul_ps(_mm_mul_ps(_mm_add_ps(_1, _mm_mul_ps(_2, t)), _mm_mul_ps(t_1, t_1)), _p1); - _p2 = _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(t, t), _mm_sub_ps(_3, _mm_mul_ps(_2, t))), _p2); - __m128 tangent = _mm_mul_ps(_mm_add_ps(_mm_mul_ps(t_1, _t1), _mm_mul_ps(t, _t2)), _mm_mul_ps(df, t_1)); - return vec4::store_xmm(_mm_add_ps(_mm_add_ps(tangent, _p2), _p1)); + __m128 h00 = _mm_add_ps(_mm_sub_ps(t_32, t_23), _1); + __m128 h01 = _mm_sub_ps(t_23, t_32); + __m128 h10 = _mm_add_ps(_mm_sub_ps(t_3, _mm_mul_ps(_2, t_2)), t); + __m128 h11 = _mm_sub_ps(t_3, t_2); + + _p1 = _mm_mul_ps(h00, _p1); + _p2 = _mm_mul_ps(h01, _p2); + _t1 = _mm_mul_ps(h10, _mm_mul_ps(_t1, df)); + _t2 = _mm_mul_ps(h11, _mm_mul_ps(_t2, df)); + return vec4::store_xmm(_mm_add_ps(_mm_add_ps(_p1, _p2), _mm_add_ps(_t1, _t2))); } inline std::vector interpolate_chs(const float_t p1, const float_t p2, const float_t t1, const float_t t2, const size_t f1, const size_t f2) { size_t length = f2 - f1 + 1; + if (p1 == p2 && fabsf(t1) == 0.0f && fabsf(t2) == 0.0f) + return std::vector(length, p1); + std::vector arr(length); float_t* a = arr.data(); for (size_t i = 0, j = length; j; i++, j--, a++) diff --git a/src/KKdLib/mot.cpp b/src/KKdLib/mot.cpp index 3bfce746..8bc43759 100644 --- a/src/KKdLib/mot.cpp +++ b/src/KKdLib/mot.cpp @@ -7,7 +7,6 @@ #include "f2/struct.hpp" #include "io/path.hpp" #include "io/memory_stream.hpp" -#include "interpolation.hpp" #include "half_t.hpp" #include "hash.hpp" #include "str_utils.hpp" @@ -117,7 +116,8 @@ inline static float_t interpolate_mot_value(float_t p1, float_t p2, float_t df = f - f1; float_t t = df / (f2 - f1); float_t t_1 = t - 1.0f; - return (t_1 * t1 + t * t2) * t_1 * df + (t * 2.0f - 3.0f) * (t * t) * (p1 - p2) + p1; + return (t_1 * t1 + t * t2) * t_1 * df + + (t * 2.0f - 3.0f) * (t * t) * (p1 - p2) + p1; } inline static void interpolate_mot_reverse_value(float_t* arr, size_t length, @@ -127,20 +127,18 @@ inline static void interpolate_mot_reverse_value(float_t* arr, size_t length, if (!arr || length < 2 || f - f1 + 1 >= length || f < 1 || f < f1 || f + 2 > f2) return; - float_t df_1 = (float_t)(f - f1); - float_t df_2 = (float_t)(f - f1 + 1); - float_t _t1 = df_1 / (float_t)(f2 - f1); - float_t _t2 = df_2 / (float_t)(f2 - f1); + float_t _t1 = (float_t)(f - f1) / (float_t)(f2 - f1); + float_t _t2 = (float_t)(f - f1 + 1) / (float_t)(f2 - f1); float_t t1_1 = _t1 - 1.0f; float_t t2_1 = _t2 - 1.0f; float_t t1_t2_1 = arr[f] - arr[f1] - (_t1 * 2.0f - 3.0f) * (_t1 * _t1) * (arr[f1] - arr[f2]); float_t t1_t2_2 = arr[f + 1] - arr[f1] - (_t2 * 2.0f - 3.0f) * (_t2 * _t2) * (arr[f1] - arr[f2]); - t1_t2_1 /= df_1 * t1_1; - t1_t2_2 /= df_2 * t2_1; + t1_t2_1 /= t1_1 * _t1; + t1_t2_2 /= t2_1 * _t2; - *t1 = (t1_t2_1 * _t2 - t1_t2_2 * _t1) / (_t1 - _t2); - *t2 = (-t1_t2_1 * t2_1 + t1_t2_2 * t1_1) / (_t1 - _t2); + *t1 = -t1_t2_1 * _t2 + t1_t2_2 * _t1; + *t2 = t1_t2_1 * t2_1 - t1_t2_2 * t1_1; } inline static void mot_set_add_key(uint16_t frame, float_t v, float_t t, @@ -176,36 +174,6 @@ inline static float_t mot_set_add_key(bool has_error, float_t* a, int32_t frame, } } -mot_key_set_type mot_set::fit_keys_into_curve(std::vector& values_src, - prj::shared_ptr alloc, uint16_t*& frames, float_t*& values, size_t& keys_count) { - std::vector _frames; - std::vector _values; - mot_key_set_type type = mot_set::fit_keys_into_curve(values_src, _frames, _values); - switch (type) { - case MOT_KEY_SET_NONE: - keys_count = 0; - frames = 0; - values = 0; - break; - case MOT_KEY_SET_STATIC: - keys_count = 1; - frames = 0; - values = alloc->allocate(_values.data(), 1); - break; - case MOT_KEY_SET_HERMITE: - keys_count = _frames.size(); - frames = alloc->allocate(_frames.data(), keys_count); - values = alloc->allocate(_values.data(), keys_count); - break; - case MOT_KEY_SET_HERMITE_TANGENT: - keys_count = _frames.size(); - frames = alloc->allocate(_frames.data(), keys_count); - values = alloc->allocate(_values.data(), keys_count * 2); - break; - } - return type; -} - mot_key_set_type mot_set::fit_keys_into_curve(std::vector& values_src, std::vector& frames, std::vector& values) { size_t count = values_src.size(); diff --git a/src/KKdLib/mot.hpp b/src/KKdLib/mot.hpp index 9e64e5b4..b8c65a44 100644 --- a/src/KKdLib/mot.hpp +++ b/src/KKdLib/mot.hpp @@ -79,8 +79,6 @@ struct mot_set { void pack_file(void** data, size_t* size); void unpack_file(prj::shared_ptr alloc, const void* data, size_t size, bool modern); - static mot_key_set_type fit_keys_into_curve(std::vector& values_src, - prj::shared_ptr alloc, uint16_t*& frames, float_t*& values, size_t& keys_count); static mot_key_set_type fit_keys_into_curve(std::vector& values_src, std::vector& frames, std::vector& values); }; diff --git a/src/ReDIVA/classes/glitter_editor.cpp b/src/ReDIVA/classes/glitter_editor.cpp index 8bb95dea..0a965657 100644 --- a/src/ReDIVA/classes/glitter_editor.cpp +++ b/src/ReDIVA/classes/glitter_editor.cpp @@ -5298,11 +5298,12 @@ static void glitter_editor_curve_editor_property_window(GlitterEditor* glt_edt, value = n->frame == crv_edt->frame ? n->value : c->value; break; case Glitter::KEY_LINEAR: - value = interpolate_linear_value(c->value, n->value, + value = Glitter::Curve::InterpolateLinear(c->value, n->value, (float_t)c->frame, (float_t)n->frame, (float_t)crv_edt->frame); break; case Glitter::KEY_HERMITE: - value = interpolate_chs_value(c->value, n->value, c->tangent2, n->tangent1, + value = Glitter::Curve::InterpolateHermite( + c->value, n->value - c->value, c->tangent2, n->tangent1, (float_t)c->frame, (float_t)n->frame, (float_t)crv_edt->frame); break; } @@ -6810,13 +6811,13 @@ static void glitter_editor_curve_editor_window_draw(GlitterEditor* glt_edt, cons break; case Glitter::KEY_LINEAR: default: - value = interpolate_linear_value(c_value_vec, n_value_vec, - (float_t)c->frame, (float_t)n->frame, (float_t)start_time); + value = Glitter::Curve::InterpolateLinear(c_value_vec, n_value_vec, + vec3((float_t)c->frame), vec3((float_t)n->frame), vec3((float_t)start_time)); break; case Glitter::KEY_HERMITE: - value = interpolate_chs_value(c_value_vec, n_value_vec, - (float_t)c->tangent2, (float_t)n->tangent1, - (float_t)c->frame, (float_t)n->frame, (float_t)start_time); + value = Glitter::Curve::InterpolateHermite(c_value_vec, n_value_vec - c_value_vec, + vec3((float_t)c->tangent2), vec3((float_t)n->tangent1), + vec3((float_t)c->frame), vec3((float_t)n->frame), vec3((float_t)start_time)); break; } else @@ -6857,13 +6858,13 @@ static void glitter_editor_curve_editor_window_draw(GlitterEditor* glt_edt, cons break; case Glitter::KEY_LINEAR: default: - value = interpolate_linear_value(c_value_vec, n_value_vec, - (float_t)c->frame, (float_t)n->frame, (float_t)end_time); + value = Glitter::Curve::InterpolateLinear(c_value_vec, n_value_vec, + vec3((float_t)c->frame), vec3((float_t)n->frame), vec3((float_t)end_time)); break; case Glitter::KEY_HERMITE: - value = interpolate_chs_value(c_value_vec, n_value_vec, - (float_t)c->tangent2, (float_t)n->tangent1, - (float_t)c->frame, (float_t)n->frame, (float_t)end_time); + value = Glitter::Curve::InterpolateHermite(c_value_vec, n_value_vec - c_value_vec, + vec3((float_t)c->tangent2), vec3((float_t)n->tangent1), + vec3((float_t)c->frame), vec3((float_t)n->frame), vec3((float_t)end_time)); break; } } @@ -6923,9 +6924,9 @@ static void glitter_editor_curve_editor_window_draw(GlitterEditor* glt_edt, cons const float_t x1 = canvas_pos.x + (float_t)(c_frame - base_start_time) * frame_width; const float_t x2 = canvas_pos.x + (float_t)(n_frame - base_start_time) * frame_width; - const float_t _c_value = interpolate_linear_value(c_value, n_value, + const float_t _c_value = Glitter::Curve::InterpolateLinear(c_value, n_value, (float_t)c->frame, (float_t)n->frame, (float_t)c_frame); - const float_t _n_value = interpolate_linear_value(c_value, n_value, + const float_t _n_value = Glitter::Curve::InterpolateLinear(c_value, n_value, (float_t)c->frame, (float_t)n->frame, (float_t)n_frame); const vec3 c_value_vec = { _c_value + c_random_range, _c_value, _c_value - c_random_range }; @@ -6953,27 +6954,27 @@ static void glitter_editor_curve_editor_window_draw(GlitterEditor* glt_edt, cons const vec3 n_value_vec = { n_value + n_random_range, n_value, n_value - n_random_range }; const vec3 c_tangent2_vec = c_tangent2; const vec3 n_tangent1_vec = n_tangent1; - const size_t frame_width_int = (size_t)roundf(frame_width); - for (size_t j = c->frame; j < n->frame; j++) { + const int32_t frame_width_int = (int32_t)roundf(frame_width); + for (int32_t j = c->frame; j < n->frame; j++) { if (j < start_time) continue; else if (j >= end_time) break; - for (size_t k = 0; k < frame_width_int; k++) { - const float_t frame = (float_t)(int32_t)j + (float_t)(int32_t)k / frame_width; + for (int32_t k = 0; k < frame_width_int; k++) { + const float_t frame = (float_t)j + (float_t)k / frame_width; const vec3 frame_vec = frame; - const vec3 value = interpolate_chs_value(c_value_vec, n_value_vec, + const vec3 value = Glitter::Curve::InterpolateHermite(c_value_vec, n_value_vec - c_value_vec, c_tangent2_vec, n_tangent1_vec, c_frame_vec, n_frame_vec, frame_vec); const vec3 random = !random_range_mult ? random_range : glt_type_ft ? (random_range * value) : (random_range * value * 0.01f); const float_t x1 = canvas_pos.x - + (float_t)(int32_t)(j - base_start_time) * frame_width + (float_t)(int32_t)k; + + (float_t)(j - base_start_time) * frame_width + (float_t)k; const float_t x2 = canvas_pos.x - + (float_t)(int32_t)(j - base_start_time) * frame_width + (float_t)(int32_t)(k + 1); + + (float_t)(j - base_start_time) * frame_width + (float_t)(k + 1); glitter_editor_curve_editor_window_draw_random_range(crv_edt, x1, x2, value, random, min, max, random_range_negate, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max); @@ -7008,11 +7009,11 @@ static void glitter_editor_curve_editor_window_draw(GlitterEditor* glt_edt, cons break; case Glitter::KEY_LINEAR: default: - value = interpolate_linear_value(c_value, n_value, + value = Glitter::Curve::InterpolateLinear(c_value, n_value, (float_t)c->frame, (float_t)n->frame, (float_t)start_time); break; case Glitter::KEY_HERMITE: - value = interpolate_chs_value(c_value, n_value, + value = Glitter::Curve::InterpolateHermite(c_value, n_value - c_value, (float_t)c->tangent2, (float_t)n->tangent1, (float_t)c->frame, (float_t)n->frame, (float_t)start_time); break; @@ -7051,11 +7052,11 @@ static void glitter_editor_curve_editor_window_draw(GlitterEditor* glt_edt, cons break; case Glitter::KEY_LINEAR: default: - value = interpolate_linear_value(c_value, n_value, + value = Glitter::Curve::InterpolateLinear(c_value, n_value, (float_t)c->frame, (float_t)n->frame, (float_t)end_time); break; case Glitter::KEY_HERMITE: - value = interpolate_chs_value(c_value, n_value, + value = Glitter::Curve::InterpolateHermite(c_value, n_value - c_value, (float_t)c->tangent2, (float_t)n->tangent1, (float_t)c->frame, (float_t)n->frame, (float_t)end_time); break; @@ -7115,9 +7116,9 @@ static void glitter_editor_curve_editor_window_draw(GlitterEditor* glt_edt, cons const float_t x1 = canvas_pos.x + (float_t)(c_frame - base_start_time) * frame_width; const float_t x2 = canvas_pos.x + (float_t)(n_frame - base_start_time) * frame_width; - const float_t _c_value = interpolate_linear_value(c_value, n_value, + const float_t _c_value = Glitter::Curve::InterpolateLinear(c_value, n_value, (float_t)c->frame, (float_t)n->frame, (float_t)c_frame); - const float_t _n_value = interpolate_linear_value(c_value, n_value, + const float_t _n_value = Glitter::Curve::InterpolateLinear(c_value, n_value, (float_t)c->frame, (float_t)n->frame, (float_t)n_frame); const float_t y1 = convert_value_to_height(crv_edt, _c_value, @@ -7139,7 +7140,7 @@ static void glitter_editor_curve_editor_window_draw(GlitterEditor* glt_edt, cons const float_t c_tangent2 = (float_t)c->tangent2; const float_t n_tangent1 = (float_t)n->tangent1; - float_t value = interpolate_chs_value(c_value, n_value, + float_t value = Glitter::Curve::InterpolateHermite(c_value, n_value - c_value, c_tangent2, n_tangent1, c_frame, n_frame, (float_t)max_def(c->frame, start_time)); float_t x = canvas_pos.x + (float_t)(max_def(c->frame, start_time) @@ -7149,19 +7150,19 @@ static void glitter_editor_curve_editor_window_draw(GlitterEditor* glt_edt, cons if (!points.size() || points.back().x < x || points.back().y != y) points.push_back({ x, y }); - const size_t frame_width_int = (size_t)roundf(frame_width); - for (size_t j = c->frame; j < n->frame; j++) { + const int32_t frame_width_int = (int32_t)roundf(frame_width); + for (int32_t j = c->frame; j < n->frame; j++) { if (j < start_time) continue; else if (j >= end_time) break; - for (size_t k = 0; k < frame_width_int; k++) { - const float_t value = interpolate_chs_value(c_value, n_value, c_tangent2, n_tangent1, - c_frame, n_frame, (float_t)(int32_t)j + (float_t)(int32_t)k / frame_width); + for (int32_t k = 0; k < frame_width_int; k++) { + const float_t value = Glitter::Curve::InterpolateHermite(c_value, n_value - c_value, + c_tangent2, n_tangent1, c_frame, n_frame, (float_t)j + (float_t)k / frame_width); float_t x = canvas_pos.x - + (float_t)(int32_t)(j - base_start_time) * frame_width + (float_t)(int32_t)k; + + (float_t)(j - base_start_time) * frame_width + (float_t)k; const float_t y = convert_value_to_height(crv_edt, value, canvas_pos.y, canvas_size.y, min, max); diff --git a/src/ReDIVA/render.cpp b/src/ReDIVA/render.cpp index b8f1de03..a1215f50 100644 --- a/src/ReDIVA/render.cpp +++ b/src/ReDIVA/render.cpp @@ -203,7 +203,7 @@ int32_t render_main(render_init_struct* ris) { if (!render_lock) return 0; - render_timer = new timer(60.0); + render_timer = new timer(600.0); window_handle = 0; diff --git a/src/ReDIVA/x_pv_game.cpp b/src/ReDIVA/x_pv_game.cpp index ef6f61ca..3c4613ac 100644 --- a/src/ReDIVA/x_pv_game.cpp +++ b/src/ReDIVA/x_pv_game.cpp @@ -1167,6 +1167,13 @@ void x_pv_game_effect::set_song_effect_time_inner(int32_t index, int64_t time, b } } +void x_pv_game_effect::set_time(int64_t time, bool glitter) { + size_t size = song_effect.size(); + for (size_t i = 0; i < size; i++) + if (song_effect[i].enable) + set_song_effect_time_inner((int32_t)i, time, glitter); +} + void x_pv_game_effect::stop() { size_t song_effect_count = song_effect.size(); for (size_t i = 0; i < song_effect_count; i++) @@ -1528,6 +1535,20 @@ void x_pv_game_chara_effect::set_chara_effect_time(int32_t chara_id, int32_t ind } } +void x_pv_game_chara_effect::set_time(int64_t time) { + if (!state) + return; + + for (auto& i : auth_3d) + for (x_pv_game_chara_effect_auth_3d& j : i) { + if (!j.id.check_not_empty() || !j.id.get_enable()) + continue; + + j.id.set_req_frame((float_t)((double_t)(time - j.time) * 0.000000001) * 60.0f); + j.id.set_paused(false); + } +} + void x_pv_game_chara_effect::stop() { if (!state) return; @@ -3532,6 +3553,442 @@ static void a3da_key_rev(a3da_key& k, std::vector& values_src) { } #endif +#if BAKE_PV826 +mot_key_set_type mot_fit_keys_into_curve(std::vector& values_src, + std::vector& frames, std::vector& values) { + std::vector value; + int32_t type = interpolate_chs_reverse_sequence(values_src, value); + + frames.resize(0); + values.resize(0); + + switch (type) { + case 0: + default: + return MOT_KEY_SET_NONE; + case 1: + values.push_back(value[0].value); + return MOT_KEY_SET_STATIC; + case 2: + break; + } + + bool tangent = false; + for (kft3& i : value) + if (i.tangent1 != 0.0f || i.tangent2 != 0.0f) { + tangent = true; + break; + } + + if (!tangent) { + frames.reserve(value.size() + value.size() / 2); + values.reserve((value.size() + value.size() / 2)); + + for (kft3& i : value) { + frames.push_back((uint16_t)i.frame); + values.push_back(i.value); + if (i.value == 0.0f) { + frames.push_back((uint16_t)i.frame); + values.push_back(i.value); + } + } + return MOT_KEY_SET_HERMITE; + } + else { + frames.reserve(value.size() + value.size() / 2); + values.reserve((value.size() + value.size() / 2) * 2); + + for (kft3& i : value) { + frames.push_back((uint16_t)i.frame); + values.push_back(i.value); + values.push_back(i.tangent1); + + if (i.value == 0.0f) { + frames.push_back((uint16_t)i.frame); + values.push_back(i.value); + values.push_back(i.tangent1); + } + + if (i.tangent1 != i.tangent2) { + frames.push_back((uint16_t)i.frame); + values.push_back(i.value); + values.push_back(i.tangent2); + + if (i.value == 0.0f) { + frames.push_back((uint16_t)i.frame); + values.push_back(i.value); + values.push_back(i.tangent2); + } + } + } + return MOT_KEY_SET_HERMITE_TANGENT; + } +} + +static void fix_rotation(std::vector& vec) { + if (vec.size() < 2) + return; + + const float_t half_pi = (float_t)(M_PI / 2.0); + + int32_t curr_rot = 0; + float_t rot_fix = 0.0f; + float_t rot_prev = vec.data()[0]; + float_t* i_begin = vec.data() + 1; + float_t* i_end = vec.data() + vec.size(); + for (float_t* i = i_begin; i != i_end; i++) { + float_t rot = *i; + if (rot < -half_pi && rot_prev > half_pi && fabsf(rot - rot_prev) > half_pi) { + curr_rot++; + rot_fix = (float_t)(M_PI * 2.0 * (double_t)curr_rot); + } + else if (rot > half_pi && rot_prev < -half_pi && fabsf(rot - rot_prev) > half_pi) { + curr_rot--; + rot_fix = (float_t)(M_PI * 2.0 * (double_t)curr_rot); + } + + if (curr_rot) + *i = rot + rot_fix; + rot_prev = rot; + } +} + +struct mot_data_bake { + int32_t performer; + x_pv_game_a3da_to_mot* data; + lock state; +}; + +const int32_t bake_pv826_threads_count = 2; + +const motion_set_info* bake_pv826_set_info; +std::thread* bake_pv826_thread; +mot_data_bake* bake_pv826_mot_data; +int32_t bake_pv826_performer; +std::mutex* bake_pv826_alloc_mutex; +prj::shared_ptr* bake_pv826_alloc; +::mot_set* bake_pv826_mot_set; + +mot_key_set_type mot_write_motion_fit_keys_into_curve(std::vector& values_src, + prj::shared_ptr alloc, uint16_t*& frames, float_t*& values, size_t& keys_count) { + std::vector _frames; + std::vector _values; + mot_key_set_type type = mot_set::fit_keys_into_curve(values_src, _frames, _values); + switch (type) { + case MOT_KEY_SET_NONE: + keys_count = 0; + frames = 0; + values = 0; + break; + case MOT_KEY_SET_STATIC: + keys_count = 1; + { + std::unique_lock u_lock(*bake_pv826_alloc_mutex); + frames = 0; + values = (*bake_pv826_alloc)->allocate(1); + } + memcpy(values, _values.data(), sizeof(float_t)); + break; + case MOT_KEY_SET_HERMITE: + keys_count = _frames.size(); + { + std::unique_lock u_lock(*bake_pv826_alloc_mutex); + frames = (*bake_pv826_alloc)->allocate(_frames.data(), keys_count); + values = (*bake_pv826_alloc)->allocate(keys_count); + } + memcpy(frames, _frames.data(), sizeof(uint16_t) * keys_count); + memcpy(values, _values.data(), sizeof(float_t) * keys_count); + break; + case MOT_KEY_SET_HERMITE_TANGENT: + keys_count = _frames.size(); + { + std::unique_lock u_lock(*bake_pv826_alloc_mutex); + frames = (*bake_pv826_alloc)->allocate(keys_count); + values = (*bake_pv826_alloc)->allocate(keys_count * 2); + } + memcpy(frames, _frames.data(), sizeof(uint16_t) * keys_count); + memcpy(values, _values.data(), sizeof(float_t) * keys_count * 2); + break; + } + return type; +} + +void mot_write_motion(mot_data_bake* bake) { + data_struct* aft_data = &data_list[DATA_AFT]; + bone_database* aft_bone_data = &aft_data->data_ft.bone_data; + motion_database* aft_mot_db = &aft_data->data_ft.mot_db; + + char buf[0x200]; + sprintf_s(buf, sizeof(buf), "PV826_OST_P%d_00", bake->performer); + + int32_t motion_id = aft_mot_db->get_motion_id(buf); + + size_t motion_index = -1; + const motion_set_info* set_info = bake_pv826_set_info; + for (const motion_info& j : set_info->motion) + if (j.id == motion_id) { + motion_index = &j - set_info->motion.data(); + break; + } + + mot_data* mot_data = &bake_pv826_mot_set->mot_data[motion_index]; + + uint16_t key_set_count = mot_data->key_set_count - 1; + if (!key_set_count) + return; + + const char* name = bone_database_skeleton_type_to_string(BONE_DATABASE_SKELETON_COMMON); + std::string* bone_names = aft_mot_db->bone_name.data(); + const std::vector* bones = aft_bone_data->get_skeleton_bones(name); + if (!bones) + return; + + prj::shared_ptr& alloc = *bake_pv826_alloc; + x_pv_game_a3da_to_mot& a2m = *bake->data; + const mot_bone_info* bone_info = mot_data->bone_info_array; + for (size_t key_set_offset = 0, i = 0; key_set_offset < key_set_count; i++) { + motion_bone_index bone_index = (motion_bone_index)aft_bone_data->get_skeleton_bone_index( + name, bone_names[bone_info[i].index].c_str()); + if (bone_index == -1) { + i++; + bone_index = (motion_bone_index)aft_bone_data->get_skeleton_bone_index( + name, bone_names[bone_info[i].index].c_str()); + if (bone_index == -1) + break; + } + + const bone_database_bone* bone = &(*bones)[bone_index]; + + auto elem = a2m.bone_keys.find(bone_index); + if (elem != a2m.bone_keys.end()) { + x_pv_game_a3da_to_mot_keys& keys = elem->second; + + if (bone->type == BONE_DATABASE_BONE_ROTATION) { + fix_rotation(keys.x); + fix_rotation(keys.y); + fix_rotation(keys.z); + } + + mot_key_set_data& key_set_data_x = mot_data->key_set_array[key_set_offset]; + key_set_data_x.frames = 0; + key_set_data_x.values = 0; + size_t keys_x_count = 0; + key_set_data_x.type = mot_write_motion_fit_keys_into_curve(keys.x, alloc, + key_set_data_x.frames, key_set_data_x.values, keys_x_count); + key_set_data_x.keys_count = (uint16_t)keys_x_count; + key_set_data_x.data_type = MOT_KEY_SET_DATA_F32; + + mot_key_set_data& key_set_data_y = mot_data->key_set_array[key_set_offset + 1]; + key_set_data_y.frames = 0; + key_set_data_y.values = 0; + size_t keys_y_count = 0; + key_set_data_y.type = mot_write_motion_fit_keys_into_curve(keys.y, alloc, + key_set_data_y.frames, key_set_data_y.values, keys_y_count); + key_set_data_y.keys_count = (uint16_t)keys_y_count; + key_set_data_y.data_type = MOT_KEY_SET_DATA_F32; + + mot_key_set_data& key_set_data_z = mot_data->key_set_array[key_set_offset + 2]; + key_set_data_z.frames = 0; + key_set_data_z.values = 0; + size_t keys_z_count = 0; + key_set_data_z.type = mot_write_motion_fit_keys_into_curve(keys.z, alloc, + key_set_data_z.frames, key_set_data_z.values, keys_z_count); + key_set_data_z.keys_count = (uint16_t)keys_z_count; + key_set_data_z.data_type = MOT_KEY_SET_DATA_F32; + } + + elem = a2m.sec_bone_keys.find(bone_index); + if (elem != a2m.sec_bone_keys.end()) { + x_pv_game_a3da_to_mot_keys& keys = elem->second; + + fix_rotation(keys.x); + fix_rotation(keys.y); + fix_rotation(keys.z); + + mot_key_set_data& key_set_data_x = mot_data->key_set_array[key_set_offset + 3]; + key_set_data_x.frames = 0; + key_set_data_x.values = 0; + size_t keys_x_count = 0; + key_set_data_x.type = mot_write_motion_fit_keys_into_curve(keys.x, alloc, + key_set_data_x.frames, key_set_data_x.values, keys_x_count); + key_set_data_x.keys_count = (uint16_t)keys_x_count; + key_set_data_x.data_type = MOT_KEY_SET_DATA_F32; + + mot_key_set_data& key_set_data_y = mot_data->key_set_array[key_set_offset + 4]; + key_set_data_y.frames = 0; + key_set_data_y.values = 0; + size_t keys_y_count = 0; + key_set_data_y.type = mot_write_motion_fit_keys_into_curve(keys.y, alloc, + key_set_data_y.frames, key_set_data_y.values, keys_x_count); + key_set_data_y.keys_count = (uint16_t)keys_y_count; + key_set_data_y.data_type = MOT_KEY_SET_DATA_F32; + + mot_key_set_data& key_set_data_z = mot_data->key_set_array[key_set_offset + 5]; + key_set_data_z.frames = 0; + key_set_data_z.values = 0; + size_t keys_z_count = 0; + key_set_data_z.type = mot_write_motion_fit_keys_into_curve(keys.z, alloc, + key_set_data_z.frames, key_set_data_z.values, keys_z_count); + key_set_data_z.keys_count = (uint16_t)keys_z_count; + key_set_data_z.data_type = MOT_KEY_SET_DATA_F32; + } + + if (bone_index == MOTION_BONE_KL_AGO_WJ) { + mot_key_set_data& key_set_data_x = mot_data->key_set_array[key_set_offset]; + key_set_data_x.frames = 0; + { + std::unique_lock u_lock(*bake_pv826_alloc_mutex); + key_set_data_x.values = alloc->allocate(1); + key_set_data_x.values[0] = 0.0491406508f; + } + key_set_data_x.type = MOT_KEY_SET_STATIC; + key_set_data_x.keys_count = 1; + key_set_data_x.data_type = MOT_KEY_SET_DATA_F32; + + mot_key_set_data& key_set_data_y = mot_data->key_set_array[key_set_offset + 1]; + key_set_data_y.frames = 0; + key_set_data_y.values = 0; + key_set_data_y.type = MOT_KEY_SET_NONE; + key_set_data_y.keys_count = 0; + key_set_data_y.data_type = MOT_KEY_SET_DATA_F32; + + mot_key_set_data& key_set_data_z = mot_data->key_set_array[key_set_offset + 2]; + key_set_data_z.frames = 0; + key_set_data_z.values = 0; + key_set_data_z.type = MOT_KEY_SET_NONE; + key_set_data_z.keys_count = 0; + key_set_data_z.data_type = MOT_KEY_SET_DATA_F32; + } + else if (bone_index == MOTION_BONE_N_KUBI_WJ_EX) { + mot_key_set_data& key_set_data_x = mot_data->key_set_array[key_set_offset]; + key_set_data_x.frames = 0; + key_set_data_x.values = 0; + key_set_data_x.type = MOT_KEY_SET_NONE; + key_set_data_x.keys_count = 1; + key_set_data_x.data_type = MOT_KEY_SET_DATA_F32; + + mot_key_set_data& key_set_data_y = mot_data->key_set_array[key_set_offset + 1]; + key_set_data_y.frames = 0; + { + std::unique_lock u_lock(*bake_pv826_alloc_mutex); + key_set_data_y.values = alloc->allocate(1); + key_set_data_y.values[0] = 0.0331281610f; + } + key_set_data_y.type = MOT_KEY_SET_STATIC; + key_set_data_y.keys_count = 0; + key_set_data_y.data_type = MOT_KEY_SET_DATA_F32; + + mot_key_set_data& key_set_data_z = mot_data->key_set_array[key_set_offset + 2]; + key_set_data_z.frames = 0; + key_set_data_z.values = 0; + key_set_data_z.type = MOT_KEY_SET_NONE; + key_set_data_z.keys_count = 0; + key_set_data_z.data_type = MOT_KEY_SET_DATA_F32; + } + + if (bone->type >= BONE_DATABASE_BONE_POSITION_ROTATION) + key_set_offset += 6; + else + key_set_offset += 3; + } + + bake->state.set(0); +} + +bool mot_write_motion_set(void* data, const char* path, const char* file, uint32_t hash) { + x_pv_game* xpvgm = (x_pv_game*)data; + + data_struct* aft_data = &data_list[DATA_AFT]; + bone_database* aft_bone_data = &aft_data->data_ft.bone_data; + motion_database* aft_mot_db = &aft_data->data_ft.mot_db; + + char buf[0x200]; + sprintf_s(buf, sizeof(buf), "PV%03d", xpvgm->pv_id); + bake_pv826_set_info = aft_mot_db->get_motion_set_by_name(buf); + if (!bake_pv826_set_info) + return true; + + bake_pv826_alloc = new prj::shared_ptr(new prj::stack_allocator); + bake_pv826_alloc_mutex = 0; + bake_pv826_thread = 0; + bake_pv826_mot_data = 0; + bake_pv826_performer = 1; + + bake_pv826_mot_set = (*bake_pv826_alloc)->allocate<::mot_set>(); + { + std::string mot_file; + mot_file.append("mot_"); + mot_file.append(bake_pv826_set_info->name); + mot_file.append(".bin"); + + farc f; + farc::load_file(&f, path, file, hash); + + farc_file* ff = f.read_file(mot_file.c_str()); + if (!ff) { + delete bake_pv826_alloc; + bake_pv826_alloc = 0; + bake_pv826_mot_set = 0; + return true; + } + + bake_pv826_mot_set->unpack_file(*bake_pv826_alloc, ff->data, ff->size, false); + } + + if (!bake_pv826_mot_set->ready) { + delete bake_pv826_alloc; + bake_pv826_alloc = 0; + bake_pv826_mot_set = 0; + return true; + } + + bake_pv826_alloc_mutex = new std::mutex; + bake_pv826_thread = new std::thread[bake_pv826_threads_count]; + bake_pv826_mot_data = new mot_data_bake[bake_pv826_threads_count]; + return true; +} + +void mot_write_motion_set(x_pv_game* xpvgm) { + if (!bake_pv826_set_info) + return; + + data_struct* aft_data = &data_list[DATA_AFT]; + bone_database* aft_bone_data = &aft_data->data_ft.bone_data; + motion_database* aft_mot_db = &aft_data->data_ft.mot_db; + + { + std::string mot_file; + mot_file.append("mot_"); + mot_file.append(bake_pv826_set_info->name); + mot_file.append(".bin"); + + farc f; + + f.add_file(mot_file.c_str()); + farc_file* ff = &f.files.back(); + bake_pv826_mot_set->pack_file(&ff->data, &ff->size); + + std::string mot_farc; + mot_farc.append("pv826\\mot_"); + mot_farc.append(bake_pv826_set_info->name); + f.write(mot_farc.c_str(), FARC_COMPRESS_FArC, false); + } + + delete[] bake_pv826_thread; + delete[] bake_pv826_mot_data; + delete bake_pv826_alloc_mutex; + + delete bake_pv826_alloc; + + bake_pv826_thread = 0; + bake_pv826_mot_data = 0; + bake_pv826_alloc_mutex = 0; + bake_pv826_mot_set = 0; + bake_pv826_alloc = 0; + bake_pv826_set_info = 0; +} +#endif + #if BAKE_PNG || BAKE_VIDEO static int32_t frame_prev = -1; #endif @@ -4137,7 +4594,7 @@ bool x_pv_game::Ctrl() { if (wait_load) break; - state_old = 18; + state_old = 19; } break; case 18: { std::vector object_hrc; @@ -4229,9 +4686,10 @@ bool x_pv_game::Ctrl() { } prj::sort_unique(object); + prj::sort_unique(material_list); - //if (material_list.size()) - // x_pv_game_split_auth_3d_material_list(this, object, material_list); + if (material_list.size()) + x_pv_game_split_auth_3d_material_list(this, object, material_list); state_old = 19; } break; @@ -4425,8 +4883,92 @@ bool x_pv_game::Ctrl() { break; Glitter::glt_particle_manager->FreeScenes(); + +#if BAKE_PV826 + if (pv_data[pv_index].pv_id == 826) { + data_struct* aft_data = &data_list[DATA_AFT]; + motion_database* aft_mot_db = &aft_data->data_ft.mot_db; + + char buf[0x200]; + sprintf_s(buf, sizeof(buf), "PV%03d", pv_data[pv_index].pv_id); + const motion_set_info* set_info = aft_mot_db->get_motion_set_by_name(buf); + if (set_info) { + std::string farc_file = "mot_" + set_info->name + ".farc"; + aft_data->load_file(this, "rom/rob/", farc_file.c_str(), mot_write_motion_set); + } + state_old = 23; + } + else { + state_old = 24; + DelTask(); + break; + } + } +#else DelTask(); } break; +#endif +#if BAKE_PV826 + case 23: { + if (pv_data[pv_index].pv_id == 826 && bake_pv826_set_info) { + int32_t free_thread_count = 0; + for (int32_t i = 0; i < bake_pv826_threads_count; i++) + if (!bake_pv826_mot_data[i].state.get()) + free_thread_count++; + + if (free_thread_count && bake_pv826_performer < 6) + for (auto& i : effchrpv_auth_3d_rob_mot_ids) { + if (!free_thread_count) + break; + else if (bake_pv826_performer != i.first) + continue; + + std::thread* thread = 0; + int32_t thread_index = -1; + for (int32_t j = 0; j < bake_pv826_threads_count; j++) + if (!bake_pv826_mot_data[j].state.get()) { + thread = &bake_pv826_thread[j]; + thread_index = j; + break; + } + + if (!thread) + break; + + mot_data_bake* bake = &bake_pv826_mot_data[thread_index]; + bake->performer = bake_pv826_performer + 1; + bake->data = &i.second; + bake->state.set(1); + + if (thread->joinable()) + thread->join(); + + *thread = std::thread(mot_write_motion, bake); + + wchar_t buf[0x80]; + swprintf_s(buf, sizeof(buf) / sizeof(wchar_t), + L"X PV GAME BAKE PV826 P%d", bake->performer); + SetThreadDescription((HANDLE)thread->native_handle(), buf); + + bake_pv826_performer++; + free_thread_count--; + } + + if (free_thread_count != 2) + break; + + for (int32_t i = 0; i < bake_pv826_threads_count; i++) + bake_pv826_thread[i].join(); + } + state_old = 24; + } + case 24: { + if (pv_data[pv_index].pv_id == 826) + mot_write_motion_set(this); + + DelTask(); + } break; +#endif } return false; } @@ -4702,345 +5244,11 @@ void x_pv_game::Load(int32_t pv_id, int32_t stage_id, chara_index charas[6], int //sound_work_play_se(1, "load01_2", 1.0f); } -#if BAKE_PV826 -mot_key_set_type mot_fit_keys_into_curve(std::vector& values_src, - std::vector& frames, std::vector& values) { - std::vector value; - int32_t type = interpolate_chs_reverse_sequence(values_src, value); - - frames.resize(0); - values.resize(0); - - switch (type) { - case 0: - default: - return MOT_KEY_SET_NONE; - case 1: - values.push_back(value[0].value); - return MOT_KEY_SET_STATIC; - case 2: - break; - } - - bool tangent = false; - for (kft3& i : value) - if (i.tangent1 != 0.0f || i.tangent2 != 0.0f) { - tangent = true; - break; - } - - if (!tangent) { - frames.reserve(value.size() + value.size() / 2); - values.reserve((value.size() + value.size() / 2)); - - for (kft3& i : value) { - frames.push_back((uint16_t)i.frame); - values.push_back(i.value); - if (i.value == 0.0f) { - frames.push_back((uint16_t)i.frame); - values.push_back(i.value); - } - } - return MOT_KEY_SET_HERMITE; - } - else { - frames.reserve(value.size() + value.size() / 2); - values.reserve((value.size() + value.size() / 2) * 2); - - for (kft3& i : value) { - frames.push_back((uint16_t)i.frame); - values.push_back(i.value); - values.push_back(i.tangent1); - - if (i.value == 0.0f) { - frames.push_back((uint16_t)i.frame); - values.push_back(i.value); - values.push_back(i.tangent1); - } - - if (i.tangent1 != i.tangent2) { - frames.push_back((uint16_t)i.frame); - values.push_back(i.value); - values.push_back(i.tangent2); - - if (i.value == 0.0f) { - frames.push_back((uint16_t)i.frame); - values.push_back(i.value); - values.push_back(i.tangent2); - } - } - } - return MOT_KEY_SET_HERMITE_TANGENT; - } -} - -static void fix_rotation(std::vector& vec) { - if (vec.size() < 2) - return; - - const float_t half_pi = (float_t)(M_PI / 2.0); - - int32_t curr_rot = 0; - float_t rot_fix = 0.0f; - float_t rot_prev = vec.data()[0]; - float_t* i_begin = vec.data() + 1; - float_t* i_end = vec.data() + vec.size(); - for (float_t* i = i_begin; i != i_end; i++) { - float_t rot = *i; - if (rot < -half_pi && rot_prev > half_pi && fabsf(rot - rot_prev) > half_pi) { - curr_rot++; - rot_fix = (float_t)(M_PI * 2.0 * (double_t)curr_rot); - } - else if (rot > half_pi && rot_prev < -half_pi && fabsf(rot - rot_prev) > half_pi) { - curr_rot--; - rot_fix = (float_t)(M_PI * 2.0 * (double_t)curr_rot); - } - - if (curr_rot) - *i = rot + rot_fix; - rot_prev = rot; - } -} - -bool mot_write_motion(void* data, const char* path, const char* file, uint32_t hash) { - x_pv_game* xpvgm = (x_pv_game*)data; - - data_struct* aft_data = &data_list[DATA_AFT]; - bone_database* aft_bone_data = &aft_data->data_ft.bone_data; - motion_database* aft_mot_db = &aft_data->data_ft.mot_db; - - char buf[0x200]; - sprintf_s(buf, sizeof(buf), "PV%03d", xpvgm->pv_id); - const motion_set_info* set_info = aft_mot_db->get_motion_set_by_name(buf); - if (!set_info) - return true; - - std::string mot_file = "mot_" + set_info->name + ".bin"; - - prj::shared_ptr alloc = prj::shared_ptr(new prj::stack_allocator); - - ::mot_set* mot_set = alloc->allocate<::mot_set>(); - { - farc f; - farc::load_file(&f, path, file, hash); - - farc_file* ff = f.read_file(mot_file.c_str()); - if (!ff) { - delete mot_set; - return true; - } - - mot_set->unpack_file(alloc, ff->data, ff->size, false); - } - - if (!mot_set->ready) { - delete mot_set; - return true; - } - - for (auto& i : xpvgm->effchrpv_auth_3d_rob_mot_ids) { - char buf[0x200]; - sprintf_s(buf, sizeof(buf), "PV826_OST_P%d_00", i.first + 1); - - int32_t motion_id = aft_mot_db->get_motion_id(buf); - - size_t motion_index = -1; - for (const motion_info& j : set_info->motion) - if (j.id == motion_id) { - motion_index = &j - set_info->motion.data(); - break; - } - - mot_data* mot_data = &mot_set->mot_data[motion_index]; - - uint16_t key_set_count = mot_data->key_set_count - 1; - if (!key_set_count) - continue; - - const char* name = bone_database_skeleton_type_to_string(BONE_DATABASE_SKELETON_COMMON); - std::string* bone_names = aft_mot_db->bone_name.data(); - const std::vector* bones = aft_bone_data->get_skeleton_bones(name); - if (!bones) - continue; - - x_pv_game_a3da_to_mot& a2m = i.second; - const mot_bone_info* bone_info = mot_data->bone_info_array; - for (size_t key_set_offset = 0, i = 0; key_set_offset < key_set_count; i++) { - motion_bone_index bone_index = (motion_bone_index)aft_bone_data->get_skeleton_bone_index( - name, bone_names[bone_info[i].index].c_str()); - if (bone_index == -1) { - i++; - bone_index = (motion_bone_index)aft_bone_data->get_skeleton_bone_index( - name, bone_names[bone_info[i].index].c_str()); - if (bone_index == -1) - break; - } - - const bone_database_bone* bone = &(*bones)[bone_index]; - - auto elem = a2m.bone_keys.find(bone_index); - if (elem != a2m.bone_keys.end()) { - x_pv_game_a3da_to_mot_keys& keys = elem->second; - - if (bone->type == BONE_DATABASE_BONE_ROTATION) { - fix_rotation(keys.x); - fix_rotation(keys.y); - fix_rotation(keys.z); - } - - mot_key_set_data& key_set_data_x = mot_data->key_set_array[key_set_offset]; - key_set_data_x.frames = 0; - key_set_data_x.values = 0; - size_t keys_x_count = 0; - key_set_data_x.type = mot_set::fit_keys_into_curve(keys.x, alloc, - key_set_data_x.frames, key_set_data_x.values, keys_x_count); - key_set_data_x.keys_count = (uint16_t)keys_x_count; - key_set_data_x.data_type = MOT_KEY_SET_DATA_F32; - - mot_key_set_data& key_set_data_y = mot_data->key_set_array[key_set_offset + 1]; - key_set_data_y.frames = 0; - key_set_data_y.values = 0; - size_t keys_y_count = 0; - key_set_data_y.type = mot_set::fit_keys_into_curve(keys.y, alloc, - key_set_data_y.frames, key_set_data_y.values, keys_y_count); - key_set_data_y.keys_count = (uint16_t)keys_y_count; - key_set_data_y.data_type = MOT_KEY_SET_DATA_F32; - - mot_key_set_data& key_set_data_z = mot_data->key_set_array[key_set_offset + 2]; - key_set_data_z.frames = 0; - key_set_data_z.values = 0; - size_t keys_z_count = 0; - key_set_data_z.type = mot_set::fit_keys_into_curve(keys.z, alloc, - key_set_data_z.frames, key_set_data_z.values, keys_z_count); - key_set_data_z.keys_count = (uint16_t)keys_z_count; - key_set_data_z.data_type = MOT_KEY_SET_DATA_F32; - } - - elem = a2m.sec_bone_keys.find(bone_index); - if (elem != a2m.sec_bone_keys.end()) { - x_pv_game_a3da_to_mot_keys& keys = elem->second; - - fix_rotation(keys.x); - fix_rotation(keys.y); - fix_rotation(keys.z); - - mot_key_set_data& key_set_data_x = mot_data->key_set_array[key_set_offset + 3]; - key_set_data_x.frames = 0; - key_set_data_x.values = 0; - size_t keys_x_count = 0; - key_set_data_x.type = mot_set::fit_keys_into_curve(keys.x, alloc, - key_set_data_x.frames, key_set_data_x.values, keys_x_count); - key_set_data_x.keys_count = (uint16_t)keys_x_count; - key_set_data_x.data_type = MOT_KEY_SET_DATA_F32; - - mot_key_set_data& key_set_data_y = mot_data->key_set_array[key_set_offset + 4]; - key_set_data_y.frames = 0; - key_set_data_y.values = 0; - size_t keys_y_count = 0; - key_set_data_y.type = mot_set::fit_keys_into_curve(keys.y, alloc, - key_set_data_y.frames, key_set_data_y.values, keys_x_count); - key_set_data_y.keys_count = (uint16_t)keys_y_count; - key_set_data_y.data_type = MOT_KEY_SET_DATA_F32; - - mot_key_set_data& key_set_data_z = mot_data->key_set_array[key_set_offset + 5]; - key_set_data_z.frames = 0; - key_set_data_z.values = 0; - size_t keys_z_count = 0; - key_set_data_z.type = mot_set::fit_keys_into_curve(keys.z, alloc, - key_set_data_z.frames, key_set_data_z.values, keys_z_count); - key_set_data_z.keys_count = (uint16_t)keys_z_count; - key_set_data_z.data_type = MOT_KEY_SET_DATA_F32; - } - - if (bone_index == MOTION_BONE_KL_AGO_WJ) { - mot_key_set_data& key_set_data_x = mot_data->key_set_array[key_set_offset]; - key_set_data_x.frames = 0; - key_set_data_x.values = alloc->allocate(1); - key_set_data_x.values[0] = 0.0491406508f; - key_set_data_x.type = MOT_KEY_SET_STATIC; - key_set_data_x.keys_count = 1; - key_set_data_x.data_type = MOT_KEY_SET_DATA_F32; - - mot_key_set_data& key_set_data_y = mot_data->key_set_array[key_set_offset + 1]; - key_set_data_y.frames = 0; - key_set_data_y.values = 0; - key_set_data_y.type = MOT_KEY_SET_NONE; - key_set_data_y.keys_count = 0; - key_set_data_y.data_type = MOT_KEY_SET_DATA_F32; - - mot_key_set_data& key_set_data_z = mot_data->key_set_array[key_set_offset + 2]; - key_set_data_z.frames = 0; - key_set_data_z.values = 0; - key_set_data_z.type = MOT_KEY_SET_NONE; - key_set_data_z.keys_count = 0; - key_set_data_z.data_type = MOT_KEY_SET_DATA_F32; - } - else if (bone_index == MOTION_BONE_N_KUBI_WJ_EX) { - mot_key_set_data& key_set_data_x = mot_data->key_set_array[key_set_offset]; - key_set_data_x.frames = 0; - key_set_data_x.values = 0; - key_set_data_x.type = MOT_KEY_SET_NONE; - key_set_data_x.keys_count = 1; - key_set_data_x.data_type = MOT_KEY_SET_DATA_F32; - - mot_key_set_data& key_set_data_y = mot_data->key_set_array[key_set_offset + 1]; - key_set_data_y.frames = 0; - key_set_data_y.values = 0; - key_set_data_y.values = alloc->allocate(1); - key_set_data_y.values[0] = 0.0331281610f; - key_set_data_y.type = MOT_KEY_SET_STATIC; - key_set_data_y.keys_count = 0; - key_set_data_y.data_type = MOT_KEY_SET_DATA_F32; - - mot_key_set_data& key_set_data_z = mot_data->key_set_array[key_set_offset + 2]; - key_set_data_z.frames = 0; - key_set_data_z.values = 0; - key_set_data_z.type = MOT_KEY_SET_NONE; - key_set_data_z.keys_count = 0; - key_set_data_z.data_type = MOT_KEY_SET_DATA_F32; - } - - if (bone->type >= BONE_DATABASE_BONE_POSITION_ROTATION) - key_set_offset += 6; - else - key_set_offset += 3; - } - } - - { - farc f; - - f.add_file(mot_file.c_str()); - farc_file* ff = &f.files.back(); - mot_set->pack_file(&ff->data, &ff->size); - - std::string mot_farc = "pv826\\mot_" + set_info->name; - f.write(mot_farc.c_str(), FARC_COMPRESS_FArC, false); - } - return true; -} -#endif - bool x_pv_game::Unload() { pv_osage_manager_array_set_not_reset_true(); if (pv_osage_manager_array_get_disp()) return false; -#if BAKE_PV826 - if (pv_data[pv_index].pv_id == 826) { - data_struct* aft_data = &data_list[DATA_AFT]; - motion_database* aft_mot_db = &aft_data->data_ft.mot_db; - - char buf[0x200]; - sprintf_s(buf, sizeof(buf), "PV%03d", pv_data[pv_index].pv_id); - const motion_set_info* set_info = aft_mot_db->get_motion_set_by_name(buf); - if (set_info) { - std::string farc_file = "mot_" + set_info->name + ".farc"; - aft_data->load_file(this, "rom/rob/", farc_file.c_str(), mot_write_motion); - } - } -#endif - for (int32_t& i : rob_chara_ids) skin_param_manager_reset(i); @@ -5843,6 +6051,9 @@ static bool x_pv_game_dsc_process(x_pv_game* a1, int64_t curr_time) { x_pv_game_change_field(a1, field, pv_data.dsc_data.time, curr_time); else x_pv_game_reset_field(a1); + + pv_data.effect.set_time(pv_data.dsc_data.time, false); + pv_data.chara_effect.set_time(pv_data.dsc_data.time); } break; case DSC_X_HIDE_FIELD: { diff --git a/src/ReDIVA/x_pv_game.hpp b/src/ReDIVA/x_pv_game.hpp index 899c64da..a0ad322c 100644 --- a/src/ReDIVA/x_pv_game.hpp +++ b/src/ReDIVA/x_pv_game.hpp @@ -292,6 +292,7 @@ struct x_pv_game_effect { void set_song_effect(int32_t index, int64_t time); void set_song_effect_time(int32_t index, int64_t time, bool glitter); void set_song_effect_time_inner(int32_t index, int64_t time, bool glitter); + void set_time(int64_t time, bool glitter); void stop(); void stop_song_effect(int32_t index, bool free_glitter); void unload(); @@ -336,6 +337,7 @@ struct x_pv_game_chara_effect { void reset(); void set_chara_effect(int32_t chara_id, int32_t index, int64_t time); void set_chara_effect_time(int32_t chara_id, int32_t index, int64_t time); + void set_time(int64_t time); void stop(); void stop_chara_effect(int32_t chara_id, int32_t index); void unload();