/* by korenkonder GitHub/GitLab: korenkonder */ #include "pv_param.hpp" #include "render.hpp" #include "render_context.hpp" #include "../KKdLib/io/file_stream.hpp" #include "../KKdLib/str_utils.hpp" extern render_context* rctx_ptr; namespace pv_param { struct file_data_struct { std::vector dof_default; std::vector cc_default; std::vector bloom_default; std::map> dof; std::map> cc; std::map> bloom; file_data_struct(); ~file_data_struct(); std::vector& get_bloom_data(std::string& file); std::vector& get_color_correction_data(std::string& file); std::vector& get_dof_data(std::string& file); bool load_bloom_file(std::string& file); bool load_color_correction_file(std::string& file); bool load_dof_file(std::string& file); void unload_bloom_file(std::string& file); void unload_color_correction_file(std::string& file); void unload_dof_file(std::string& file); }; struct light_data_struct { light_param_light_data light_default; std::string chara_light_file; std::string stage_light_file; std::map chara_light; std::map stage_light; light_data_struct(); ~light_data_struct(); void clear_data(); bool load_file(std::string& file, std::map& map); bool load_files(std::string& path); }; struct post_process_data_struct { dof dof_default; color_correction cc_default; bloom bloom_default; std::string dof_file; std::string cc_file; std::string bloom_file; std::vector dof; std::vector cc; std::vector bloom; post_process_data_struct(); ~post_process_data_struct(); void clear_data(); bool load_files(std::string& path); void set_dof(::dof& d); }; file_data_struct file_data; light_data_struct light_data; post_process_data_struct post_process_data; static char* get_next_item(char*& str); static bool load_text_file(void* data, const char* path, const char* file, uint32_t hash); bloom::bloom() { id = -1; color = 0.0f; brightpass = 0.0f; range = 0.0f; } dof::dof() { id = -1; focus = 0.0f; focus_range = 100.0f; fuzzing_range = 2.0f; ratio = 0.0f; quality = 1.0f; chara_id = -1; } chara_alpha::chara_alpha() { frame = -1.0f; duration = 1.0f; prev_alpha = 1.0f; alpha = 1.0f; type = 0; } color_correction::color_correction() { id = -1; hue = 1.0f; saturation = 1.0f; lightness = 1.0f; exposure = 1.0f; gamma = 1.0f; contrast = 1.0f; } void light_data_clear_data() { light_data.clear_data(); } light_param_light_data& light_data_get_chara_light_data(int32_t id) { auto elem = light_data.chara_light.find(id); if (elem != light_data.chara_light.end()) return elem->second; return light_data.light_default; } light_param_light_data& light_data_get_stage_light_data(int32_t id) { auto elem = light_data.stage_light.find(id); if (elem != light_data.stage_light.end()) return elem->second; return light_data.light_default; } bool light_data_load_files(int32_t pv_id, std::string&& mdata_dir) { char buf[0x100]; sprintf_s(buf, sizeof(buf), "pv%03d", pv_id); std::string path; path.assign("rom/pv_param/"); path.append(buf); if (mdata_dir.size()) { std::string temp_path; temp_path.assign(mdata_dir); temp_path.append(path); if (data_list[DATA_AFT].check_directory_exists(temp_path.c_str())) path.assign(temp_path); } if (data_list[DATA_AFT].check_directory_exists(path.c_str())) return light_data.load_files(path); return false; } void post_process_data_clear_data() { post_process_data.clear_data(); } pv_param::bloom& post_process_data_get_bloom_data(int32_t id) { for (pv_param::bloom& i : post_process_data.bloom) if (i.id == id) return i; return post_process_data.bloom_default; } pv_param::color_correction& post_process_data_get_color_correction_data(int32_t id) { for (pv_param::color_correction& i : post_process_data.cc) if (i.id == id) return i; return post_process_data.cc_default; } pv_param::dof& post_process_data_get_dof_data(int32_t id) { for (pv_param::dof& i : post_process_data.dof) if (i.id == id) return i; return post_process_data.dof_default; } bool post_process_data_load_files(int32_t pv_id, std::string&& mdata_dir) { char buf[0x100]; sprintf_s(buf, sizeof(buf), "pv%03d", pv_id); std::string path; path.assign("rom/pv_param/"); path.append(buf); if (mdata_dir.size()) { std::string temp_path; temp_path.assign(mdata_dir); temp_path.append(path); if (data_list[DATA_AFT].check_directory_exists(temp_path.c_str())) path.assign(temp_path); } if (data_list[DATA_AFT].check_directory_exists(path.c_str())) return post_process_data.load_files(path); return false; } void post_process_data_set_dof(::dof& d) { post_process_data.set_dof(d); } file_data_struct::file_data_struct() { } file_data_struct::~file_data_struct() { } std::vector& file_data_struct::get_bloom_data(std::string& file) { if (!file.size()) return bloom_default; auto elem = bloom.find(file); if (elem != bloom.end()) return elem->second; return bloom_default; } std::vector& file_data_struct::get_color_correction_data(std::string& file) { if (!file.size()) return cc_default; auto elem = cc.find(file); if (elem != cc.end()) return elem->second; return cc_default; } std::vector& file_data_struct::get_dof_data(std::string& file) { if (!file.size()) return dof_default; auto elem = dof.find(file); if (elem != dof.end()) return elem->second; return dof_default; } bool file_data_struct::load_bloom_file(std::string& file) { std::string data; if (!data_list[DATA_AFT].load_file(&data, file.c_str(), load_text_file)) return false; char* buf; char** lines; size_t count; if (!str_utils_text_file_parse(data.c_str(), data.size(), buf, lines, count)) return false; if (count <= 1 || str_utils_compare(get_next_item(lines[0]), "ID")) { free_def(buf); free_def(lines); return false; } lines++; count--; std::vector bloom; bloom.reserve(count); for (size_t i = 0; i < count; i++) { pv_param::bloom bloom_data; bloom_data.id = atoi(get_next_item(lines[i])); bloom_data.color.x = (float_t)atof(get_next_item(lines[i])); bloom_data.color.y = (float_t)atof(get_next_item(lines[i])); bloom_data.color.z = (float_t)atof(get_next_item(lines[i])); bloom_data.brightpass.x = (float_t)atof(get_next_item(lines[i])); bloom_data.brightpass.y = (float_t)atof(get_next_item(lines[i])); bloom_data.brightpass.z = (float_t)atof(get_next_item(lines[i])); bloom_data.range = (float_t)atof(get_next_item(lines[i])); bloom.push_back(bloom_data); } this->bloom.insert_or_assign(file, bloom); lines--; free_def(buf); free_def(lines); return true; } bool file_data_struct::load_color_correction_file(std::string& file) { std::string data; if (!data_list[DATA_AFT].load_file(&data, file.c_str(), load_text_file)) return false; char* buf; char** lines; size_t count; if (!str_utils_text_file_parse(data.c_str(), data.size(), buf, lines, count)) return false; if (count <= 1 || str_utils_compare(get_next_item(lines[0]), "ID")) { free_def(buf); free_def(lines); return false; } lines++; count--; std::vector cc; cc.reserve(count); for (size_t i = 0; i < count; i++) { pv_param::color_correction cc_data; cc_data.id = atoi(get_next_item(lines[i])); cc_data.hue = (float_t)atof(get_next_item(lines[i])); cc_data.saturation = (float_t)atof(get_next_item(lines[i])); cc_data.lightness = (float_t)atof(get_next_item(lines[i])); cc_data.exposure = (float_t)atof(get_next_item(lines[i])); cc_data.gamma.x = (float_t)atof(get_next_item(lines[i])); cc_data.gamma.y = (float_t)atof(get_next_item(lines[i])); cc_data.gamma.z = (float_t)atof(get_next_item(lines[i])); cc_data.contrast = (float_t)atof(get_next_item(lines[i])); cc.push_back(cc_data); } this->cc.insert_or_assign(file, cc); lines--; free_def(buf); free_def(lines); return true; } bool file_data_struct::load_dof_file(std::string& file) { std::string data; if (!data_list[DATA_AFT].load_file(&data, file.c_str(), load_text_file)) return false; char* buf; char** lines; size_t count; if (!str_utils_text_file_parse(data.c_str(), data.size(), buf, lines, count)) return false; if (count <= 1 || str_utils_compare(get_next_item(lines[0]), "ID")) { free_def(buf); free_def(lines); return false; } lines++; count--; std::vector dof; dof.reserve(count); for (size_t i = 0; i < count; i++) { pv_param::dof dof_data; dof_data.id = atoi(get_next_item(lines[i])); dof_data.focus = (float_t)atof(get_next_item(lines[i])); dof_data.focus_range = (float_t)atof(get_next_item(lines[i])); dof_data.fuzzing_range = (float_t)atof(get_next_item(lines[i])); dof_data.ratio = (float_t)atof(get_next_item(lines[i])); dof_data.quality = (float_t)atof(get_next_item(lines[i])); dof.push_back(dof_data); } this->dof.insert_or_assign(file, dof); lines--; free_def(buf); free_def(lines); return true; } void file_data_struct::unload_bloom_file(std::string& file) { auto elem = bloom.find(file); if (elem != bloom.end()) bloom.erase(elem); } void file_data_struct::unload_color_correction_file(std::string& file) { auto elem = cc.find(file); if (elem != cc.end()) cc.erase(elem); } void file_data_struct::unload_dof_file(std::string& file) { auto elem = dof.find(file); if (elem != dof.end()) dof.erase(elem); } light_data_struct::light_data_struct() { } light_data_struct::~light_data_struct() { } void light_data_struct::clear_data() { chara_light_file.clear(); chara_light_file.shrink_to_fit(); stage_light_file.clear(); stage_light_file.shrink_to_fit(); chara_light.clear(); stage_light.clear(); } bool light_data_struct::load_file(std::string& file, std::map& map) { std::string data; if (!data_list[DATA_AFT].load_file(&data, file.c_str(), load_text_file)) return false; char* buf; char** lines; size_t count; if (!str_utils_text_file_parse(data.c_str(), data.size(), buf, lines, count)) return false; if (count <= 1 || str_utils_compare(get_next_item(lines[0]), "Type")) { free_def(buf); free_def(lines); return false; } lines++; count--; for (size_t i = 0; i < count; i++) { light_param_light_data light; char* str = get_next_item(lines[i]); if (!str_utils_compare(str, "PARALLEL")) light.type = LIGHT_PARALLEL; else if (!str_utils_compare(str, "POINT")) light.type = LIGHT_POINT; else if (!str_utils_compare(str, "SPOT")) light.type = LIGHT_SPOT; else light.type = LIGHT_OFF; light.has_type = true; if (sscanf_s(get_next_item(lines[i]), "%g", &light.ambient.x) == 1) light.has_ambient = true; if (sscanf_s(get_next_item(lines[i]), "%g", &light.ambient.y) == 1) light.has_ambient = true; if (sscanf_s(get_next_item(lines[i]), "%g", &light.ambient.z) == 1) light.has_ambient = true; light.ambient.w = 1.0f; if (sscanf_s(get_next_item(lines[i]), "%g", &light.diffuse.x) == 1) light.has_diffuse = true; if (sscanf_s(get_next_item(lines[i]), "%g", &light.diffuse.y) == 1) light.has_diffuse = true; if (sscanf_s(get_next_item(lines[i]), "%g", &light.diffuse.z) == 1) light.has_diffuse = true; light.diffuse.w = 1.0f; if (sscanf_s(get_next_item(lines[i]), "%g", &light.specular.x) == 1) light.has_specular = true; if (sscanf_s(get_next_item(lines[i]), "%g", &light.specular.y) == 1) light.has_specular = true; if (sscanf_s(get_next_item(lines[i]), "%g", &light.specular.z) == 1) light.has_specular = true; if (sscanf_s(get_next_item(lines[i]), "%g", &light.specular.w) == 1) light.has_specular = true; if (sscanf_s(get_next_item(lines[i]), "%g", &light.position.x) == 1) light.has_position = true; if (sscanf_s(get_next_item(lines[i]), "%g", &light.position.y) == 1) light.has_position = true; if (sscanf_s(get_next_item(lines[i]), "%g", &light.position.z) == 1) light.has_position = true; if (sscanf_s(get_next_item(lines[i]), "%g", &light.tone_curve.start_point) == 1) light.has_tone_curve = true; if (sscanf_s(get_next_item(lines[i]), "%g", &light.tone_curve.end_point) == 1) light.has_tone_curve = true; if (sscanf_s(get_next_item(lines[i]), "%g", &light.tone_curve.coefficient) == 1) light.has_tone_curve = true; int32_t id; if (sscanf_s(get_next_item(lines[i]), "%d", &id) != 1) id = -1; map.insert_or_assign(id, light); } lines--; free_def(buf); free_def(lines); return true; } bool light_data_struct::load_files(std::string& path) { data_struct* aft_data = &data_list[DATA_AFT]; if (!aft_data->check_directory_exists(path.c_str())) return true; if (aft_data->check_file_exists(path.c_str(), "/chara_light.txt")) { chara_light_file.assign(path); chara_light_file.append("/chara_light.txt"); } else chara_light_file.clear(); if (aft_data->check_file_exists(path.c_str(), "/stage_light.txt")) { stage_light_file.assign(path); stage_light_file.append("/stage_light.txt"); } else stage_light_file.clear(); load_file(chara_light_file, chara_light); load_file(stage_light_file, stage_light); return true; } post_process_data_struct::post_process_data_struct() { } post_process_data_struct::~post_process_data_struct() { } void post_process_data_struct::clear_data() { if (dof_file.size()) { file_data.unload_dof_file(dof_file); dof_file.clear(); dof_file.shrink_to_fit(); } if (dof.size()) { dof.clear(); dof.shrink_to_fit(); } if (cc_file.size()) { file_data.unload_color_correction_file(cc_file); cc_file.clear(); cc_file.shrink_to_fit(); } if (cc.size()) { cc.clear(); cc.shrink_to_fit(); } if (bloom_file.size()) { file_data.unload_bloom_file(bloom_file); bloom_file.clear(); bloom_file.shrink_to_fit(); } if (bloom.size()) { bloom.clear(); bloom.shrink_to_fit(); } } bool post_process_data_struct::load_files(std::string& path) { data_struct* aft_data = &data_list[DATA_AFT]; if (!aft_data->check_directory_exists(path.c_str())) return false; if (aft_data->check_file_exists(path.c_str(), "/dof.txt")) { dof_file.assign(path); dof_file.append("/dof.txt"); } else dof_file.clear(); if (aft_data->check_file_exists(path.c_str(), "/cc.txt")) { cc_file.assign(path); cc_file.append("/cc.txt"); } else cc_file.clear(); if (aft_data->check_file_exists(path.c_str(), "/bloom.txt")) { bloom_file.assign(path); bloom_file.append("/bloom.txt"); } else bloom_file.clear(); if ((!dof_file.size() || file_data.load_dof_file(dof_file)) && (!cc_file.size() || file_data.load_color_correction_file(cc_file)) && (!bloom_file.size() || file_data.load_bloom_file(bloom_file))) { dof = file_data.get_dof_data(dof_file); cc = file_data.get_color_correction_data(cc_file); bloom = file_data.get_bloom_data(bloom_file); return true; } return false; } void post_process_data_struct::set_dof(::dof& d) { if (!d.ready) return; if (dof_file.size()) { file_data.unload_dof_file(dof_file); dof_file.clear(); } dof.resize(0); dof.reserve(d.data.size()); int32_t id = 0; for (dof_data& i : d.data) { pv_param::dof d; d.id = id++; if (i.flags & DOF_FOCUS) d.focus = i.focus; if (i.flags & DOF_FOCUS_RANGE) d.focus_range = i.focus_range; if (i.flags & DOF_FUZZING_RANGE) d.fuzzing_range = i.fuzzing_range; if (i.flags & DOF_RATIO) d.ratio = i.ratio; if (i.flags & DOF_QUALITY) d.quality = i.quality; if (i.flags & DOF_AUTO_FOCUS) d.chara_id = i.chara_id; dof.push_back(d); } } static char* get_next_item(char*& str) { char* orig_str = str; while (*str) if (*str == ',') { *str++ = 0; break; } else str++; return orig_str; } static bool load_text_file(void* data, const char* path, const char* file, uint32_t hash) { std::string s; s.assign(path); s.append(file); file_stream fs; fs.open(s.c_str(), "rb"); if (fs.check_not_null()) { *(std::string*)data = fs.read_string(fs.get_length()); fs.close(); return true; } return false; } } namespace pv_param_task { class PostProcessCtrl { public: float_t frame; float_t duration; PostProcessCtrl(); ~PostProcessCtrl(); virtual void Reset() = 0; virtual void Set() = 0; }; class PostProcessCtrlBloom : public PostProcessCtrl { public: struct Data { pv_param::bloom data; pv_param::bloom data_prev; Data(); } data; PostProcessCtrlBloom(); ~PostProcessCtrlBloom(); virtual void Reset() override; virtual void Set() override; }; class PostProcessCtrlCC : public PostProcessCtrl { public: struct Data { pv_param::color_correction data; pv_param::color_correction data_prev; Data(); } data; PostProcessCtrlCC(); ~PostProcessCtrlCC(); virtual void Reset() override; virtual void Set() override; void CalcToneTrans(float_t value, float_t& tone_trans_start, float_t& tone_trans_end); }; class PostProcessCtrlCharaAlpha : public PostProcessCtrl { public: struct Data { pv_param::chara_alpha data[ROB_CHARA_COUNT]; Data(); } data; PostProcessCtrlCharaAlpha(); ~PostProcessCtrlCharaAlpha(); virtual void Reset() override; virtual void Set() override; }; class PostProcessCtrlCharaItemAlpha : public PostProcessCtrlCharaAlpha { public: post_process_task_set_chara_item_alpha_callback callback[ROB_CHARA_COUNT]; void* callback_data[ROB_CHARA_COUNT]; PostProcessCtrlCharaItemAlpha(); ~PostProcessCtrlCharaItemAlpha(); virtual void Reset() override; virtual void Set() override; }; class PostProcessCtrlDof : public PostProcessCtrl { public: struct Data { pv_param::dof data; pv_param::dof data_prev; Data(); } data; PostProcessCtrlDof(); ~PostProcessCtrlDof(); virtual void Reset() override; virtual void Set() override; void SetData(pv_param::dof* dof, float_t duration); }; class PostProcessTask : public app::Task { public: PostProcessCtrlDof dof; PostProcessCtrlCC cc; PostProcessCtrlBloom bloom; PostProcessCtrlCharaAlpha chara_alpha; PostProcessCtrlCharaItemAlpha chara_item_alpha; PostProcessTask(); virtual ~PostProcessTask() override; virtual bool Init() override; virtual bool Ctrl() override; virtual bool Dest() override; }; PostProcessTask post_process_task; bool post_process_task_add_task() { return app::TaskWork::AddTask(&post_process_task, "PV POST PROCESS TASK"); } void post_process_task_set_bloom_data( pv_param::bloom& data, float_t duration) { PostProcessCtrlBloom& bloom = post_process_task.bloom; bloom.frame = 0.0f; bloom.duration = duration; bloom.data.data = data; } void post_process_task_set_color_correction_data( pv_param::color_correction& data, float_t duration) { PostProcessCtrlCC& cc = post_process_task.cc; cc.frame = 0.0f; cc.duration = duration; cc.data.data = data; } void post_process_task_set_dof_data( pv_param::dof& data, float_t duration) { PostProcessCtrlDof& dof = post_process_task.dof; dof.frame = 0.0f; dof.duration = duration; dof.data.data = data; } void post_process_task_set_chara_alpha( int32_t chara_id, int32_t type, float_t alpha, float_t duration) { PostProcessCtrlCharaAlpha& chara_alpha = post_process_task.chara_alpha; pv_param::chara_alpha& chara_alpha_data = chara_alpha.data.data[chara_id]; chara_alpha_data.type = type; chara_alpha_data.frame = 0.0f; chara_alpha_data.alpha = alpha; chara_alpha_data.duration = duration; } void post_process_task_set_chara_item_alpha( int32_t chara_id, int32_t type, float_t alpha, float_t duration, post_process_task_set_chara_item_alpha_callback callback, void* callback_data) { PostProcessCtrlCharaItemAlpha& chara_item_alpha = post_process_task.chara_item_alpha; pv_param::chara_alpha& chara_item_alpha_data = chara_item_alpha.data.data[chara_id]; chara_item_alpha_data.type = type; chara_item_alpha_data.frame = 0.0f; chara_item_alpha_data.alpha = alpha; chara_item_alpha_data.duration = duration; chara_item_alpha.callback[chara_id] = callback; chara_item_alpha.callback_data[chara_id] = callback_data; } bool post_process_task_del_task() { return post_process_task.DelTask(); } PostProcessCtrl::PostProcessCtrl() { frame = -1.0f; duration = -1.0f; } PostProcessCtrl::~PostProcessCtrl() { } PostProcessCtrlBloom::Data::Data() { } PostProcessCtrlBloom::PostProcessCtrlBloom() { } PostProcessCtrlBloom::~PostProcessCtrlBloom() { } void PostProcessCtrlBloom::Reset() { frame = -1.0f; } void PostProcessCtrlBloom::Set() { if (frame < 0.0f) return; vec3 value; if (fabsf(duration) <= 0.000001f) value = data.data.color; else if (duration < 0.0f) value = data.data_prev.color; else value = vec3::lerp(data.data_prev.color, data.data.color, frame / duration); rctx_ptr->render.set_intensity(value); frame += get_delta_frame(); if (frame > duration) { frame = -1.0f; duration = -1.0f; data.data_prev = data.data; } } PostProcessCtrlCC::Data::Data() { } PostProcessCtrlCC::PostProcessCtrlCC() { } PostProcessCtrlCC::~PostProcessCtrlCC() { } void PostProcessCtrlCC::Reset() { frame = -1.0f; } void PostProcessCtrlCC::Set() { if (frame < 0.0f) return; float_t saturation; float_t exposure; vec3 gamma; float_t contrast ; if (fabsf(duration) <= 0.000001f) { saturation = data.data.saturation; exposure = data.data.exposure; gamma = data.data.gamma; contrast = data.data.contrast; } else if (duration < 0.0f) { saturation = data.data_prev.saturation; exposure = data.data_prev.exposure; gamma = data.data_prev.gamma; contrast = data.data_prev.contrast; } else { float_t t = frame / duration; saturation = lerp_def(data.data_prev.saturation, data.data.saturation, t); exposure = lerp_def(data.data_prev.exposure, data.data.exposure, t); gamma = vec3::lerp(data.data_prev.gamma, data.data.gamma, t); contrast = lerp_def(data.data_prev.contrast, data.data.contrast, t); } rctx_ptr->render.set_saturate_coeff(saturation, 1, false); rctx_ptr->render.set_exposure(exposure * 2.0f); vec3 tone_trans_start; vec3 tone_trans_end; CalcToneTrans(contrast + gamma.x, tone_trans_start.x, tone_trans_end.x); CalcToneTrans(contrast + gamma.y, tone_trans_start.y, tone_trans_end.y); CalcToneTrans(contrast + gamma.z, tone_trans_start.z, tone_trans_end.z); rctx_ptr->render.set_tone_trans(tone_trans_start, tone_trans_end, 1); frame += get_delta_frame(); if (frame > duration) { frame = -1.0f; duration = -1.0f; data.data_prev = data.data; } } void PostProcessCtrlCC::CalcToneTrans(float_t value, float_t& tone_trans_start, float_t& tone_trans_end) { float_t pow = max_def(value, 0.125f) * 0.5f; if (fabsf(value - 2.0f) < 0.000001f) { tone_trans_start = 0.0f; tone_trans_end = 1.0f; } else if (value < 2.0f) { tone_trans_end = 1.0f; tone_trans_start = powf(0.075f, pow); } else if (value > 2.0f) { tone_trans_start = 0.0f; tone_trans_end = powf(0.95f, pow); } } PostProcessCtrlCharaAlpha::Data::Data() { } PostProcessCtrlCharaAlpha::PostProcessCtrlCharaAlpha() { } PostProcessCtrlCharaAlpha::~PostProcessCtrlCharaAlpha() { } void PostProcessCtrlCharaAlpha::Reset() { for (pv_param::chara_alpha& i : data.data) i = {}; } void PostProcessCtrlCharaAlpha::Set() { int32_t index = 0; for (pv_param::chara_alpha& i : data.data) { if (i.frame < 0.0f) { index++; continue; } float_t value; if (fabsf(i.duration) <= 0.000001f) value = i.alpha; else if (i.duration <= 0.0) value = i.prev_alpha; else value = lerp_def(i.prev_alpha, i.alpha, i.frame / i.duration); mdl::ObjFlags obj_flags; switch (i.type) { case 0: default: obj_flags = mdl::OBJ_ALPHA_ORDER_1; break; case 1: obj_flags = mdl::OBJ_ALPHA_ORDER_2; break; case 2: obj_flags = mdl::OBJ_ALPHA_ORDER_3; break; } rob_chara_array_set_alpha_obj_flags(index, value, obj_flags); i.frame += get_delta_frame(); if (i.frame > i.duration) { i.frame = -1.0f; i.prev_alpha = i.alpha; } index++; } } PostProcessCtrlCharaItemAlpha::PostProcessCtrlCharaItemAlpha() : callback(), callback_data() { } PostProcessCtrlCharaItemAlpha::~PostProcessCtrlCharaItemAlpha() { } void PostProcessCtrlCharaItemAlpha::Reset() { for (pv_param::chara_alpha& i : data.data) i = {}; for (post_process_task_set_chara_item_alpha_callback& i : callback) i = 0; for (void*& i : callback_data) i = 0; } void PostProcessCtrlCharaItemAlpha::Set() { int32_t index = 0; for (pv_param::chara_alpha& i : data.data) { if (i.frame < 0.0f) { index++; continue; } float_t value; if (fabsf(i.duration) <= 0.000001f) value = i.alpha; else if (i.duration <= 0.0) value = i.prev_alpha; else value = lerp_def(i.prev_alpha, i.alpha, i.frame / i.duration); if (callback) callback[index](callback_data[index], index, i.type, value); i.frame += get_delta_frame(); if (i.frame > i.duration) { i.frame = -1.0f; i.prev_alpha = i.alpha; } index++; } } PostProcessCtrlDof::Data::Data() { } PostProcessCtrlDof::PostProcessCtrlDof() { } PostProcessCtrlDof::~PostProcessCtrlDof() { } void PostProcessCtrlDof::Reset() { frame = -1.0f; } static void get_autofocus_data(float_t distance, float_t fov, float_t& focus, float_t& focus_range, float_t& fuzzing_range, float_t& ratio) { float_t v5 = tanf(fov * DEG_TO_RAD_FLOAT * 0.5f); float_t v6 = distance * 1000.0f; float_t v7 = 36.0f / (v5 * 2.0f); v7 *= v7; float_t _focus_range = (v6 * 0.36608f * v6) / (v7 - v6 * 0.36608f) * 0.001f; if (_focus_range >= 0.0f) { float_t _ratio = (v7 * 20000.0f) / (v6 * 220000.0f + v6 * 11.0f * v6) * 3.0048077f; float_t range; if (_ratio >= 1.0f) { range = (v6 * 3.6608f * v6) / (v7 - v6 * 3.6608f) * 0.001f; if (range < 0.2f) range = 0.2f; _ratio = 1.0f; } else range = 20.0f; if (_focus_range < 0.2f) _focus_range = 0.2f; float_t _fuzzing_range = range - _focus_range; if (_fuzzing_range < 0.01f) _fuzzing_range = 0.01f; focus = distance; focus_range = _focus_range; fuzzing_range = _fuzzing_range; ratio = _ratio; } else { focus = 0.0f; focus_range = 0.0f; fuzzing_range = 0.0f; ratio = 0.0f; } } #define DOF_FIX 1 void PostProcessCtrlDof::Set() { float_t focus; float_t focus_range; float_t fuzzing_range; float_t ratio; #if DOF_FIX float_t auto_focus; float_t auto_focus_range; #endif bool autofocus = data.data.chara_id != -1; #if DOF_FIX if (true) { #else if (autofocus) { #endif vec3 trans = 0.0f; rob_chara* rob_chr = rob_chara_array_get(autofocus ? data.data.chara_id : 0); if (rob_chr) { motion_blend_mot* mot = rob_chr->bone_data->motion_loaded.front(); ::bone_data* bone_data = mot->bone_data.bones.data(); mat4_get_translation(bone_data[MOTION_BONE_CL_KAO].node->mat, &trans); } camera* cam = rctx_ptr->camera; vec3 view_point; cam->get_view_point(view_point); float_t fov = (float_t)cam->get_fov(); float_t distance = vec3::distance(trans, view_point); get_autofocus_data(distance, fov, focus, focus_range, fuzzing_range, ratio); if (autofocus) { data.data.focus = focus; data.data.focus_range = focus_range; data.data.fuzzing_range = fuzzing_range; data.data.ratio = ratio; } #if DOF_FIX auto_focus = focus; auto_focus_range = focus_range; } #else } else if (frame < 0.0f) return; #endif if (fabsf(duration) <= 0.000001f || autofocus && duration < 0.0f) { focus = data.data.focus; focus_range = data.data.focus_range; fuzzing_range = data.data.fuzzing_range; ratio = data.data.ratio; } else if (duration < 0.0f) { focus = data.data_prev.focus; focus_range = data.data_prev.focus_range; fuzzing_range = data.data_prev.fuzzing_range; ratio = data.data_prev.ratio; } else { float_t t = frame / duration; focus = lerp_def(data.data_prev.focus, data.data.focus, t); focus_range = lerp_def(data.data_prev.focus_range, data.data.focus_range, t); fuzzing_range = lerp_def(data.data_prev.fuzzing_range, data.data.fuzzing_range, t); ratio = lerp_def(data.data_prev.ratio, data.data.ratio, t); } #if DOF_FIX bool ret = true; if (ratio > 0.0f) { if (focus == 0.0f && auto_focus >= 0.0f) { focus = auto_focus; ret = false; } if (focus_range == 0.0f && auto_focus_range >= 0.0f) { focus_range = auto_focus_range; ret = false; } } if (!autofocus && ret && frame < 0.0f) return; #endif dof_pv pv; dof_pv_get(&pv); pv.f2.focus = focus; pv.f2.focus_range = focus_range; pv.f2.fuzzing_range = fuzzing_range; pv.f2.ratio = ratio; dof_pv_set(&pv); frame += get_delta_frame(); if (frame > duration) { frame = -1.0f; duration = -1.0f; data.data_prev = data.data; } } void PostProcessCtrlDof::SetData(pv_param::dof* dof, float_t duration) { frame = 0.0f; this->duration = duration; data.data = *dof; if (fabsf(duration) > 0.000001f) { dof_pv pv; dof_pv_get(&pv); data.data_prev.focus = pv.f2.focus; data.data_prev.focus_range = pv.f2.focus_range; data.data_prev.fuzzing_range = pv.f2.fuzzing_range; data.data_prev.ratio = pv.f2.ratio; } else data.data_prev = data.data; } PostProcessTask::PostProcessTask() { } PostProcessTask::~PostProcessTask() { } bool PostProcessTask::Init() { dof.Reset(); cc.Reset(); bloom.Reset(); chara_alpha.Reset(); chara_item_alpha.Reset(); return true; } bool PostProcessTask::Ctrl() { dof.Set(); cc.Set(); bloom.Set(); chara_alpha.Set(); chara_item_alpha.Set(); return false; } bool PostProcessTask::Dest() { dof.Reset(); cc.Reset(); bloom.Reset(); chara_alpha.Reset(); chara_item_alpha.Reset(); return true; } }