diff --git a/res/ft_shaders.farc b/res/ft_shaders.farc index c97a9a1..43dd6f9 100644 Binary files a/res/ft_shaders.farc and b/res/ft_shaders.farc differ diff --git a/src/DivaGL/DivaGL.vcxproj b/src/DivaGL/DivaGL.vcxproj index 1864e27..2151428 100644 --- a/src/DivaGL/DivaGL.vcxproj +++ b/src/DivaGL/DivaGL.vcxproj @@ -166,6 +166,7 @@ del "$(SolutionDir)bin\$(TargetName).lib" + @@ -225,6 +226,7 @@ del "$(SolutionDir)bin\$(TargetName).lib" + diff --git a/src/DivaGL/Glitter/counter.cpp b/src/DivaGL/Glitter/counter.cpp index 4911611..2138a14 100644 --- a/src/DivaGL/Glitter/counter.cpp +++ b/src/DivaGL/Glitter/counter.cpp @@ -6,7 +6,7 @@ #include "glitter.hpp" namespace Glitter { - Counter* counter = (Counter*)0x0000000141199CB0; + Counter& counter = *(Counter*)0x0000000141199CB0; void Counter::Increment() { value++; diff --git a/src/DivaGL/Glitter/effect_group.cpp b/src/DivaGL/Glitter/effect_group.cpp index 28f0ffc..7674db5 100644 --- a/src/DivaGL/Glitter/effect_group.cpp +++ b/src/DivaGL/Glitter/effect_group.cpp @@ -4,7 +4,6 @@ */ #include "glitter.hpp" -#include "../../KKdLib/prj/algorithm.hpp" #include "../object.hpp" #include "../texture.hpp" diff --git a/src/DivaGL/Glitter/effect_inst.cpp b/src/DivaGL/Glitter/effect_inst.cpp index 50eb068..a41f055 100644 --- a/src/DivaGL/Glitter/effect_inst.cpp +++ b/src/DivaGL/Glitter/effect_inst.cpp @@ -63,7 +63,7 @@ namespace Glitter { ext_anim = 0; render_scene = {}; - Glitter::counter->Increment(); + Glitter::counter.Increment(); if (load_flags & 0x01) enum_or(flags, EFFECT_INST_FLAG_23); @@ -71,7 +71,7 @@ namespace Glitter { if (data.flags & EFFECT_USE_SEED) random = data.seed; else - random = Glitter::counter->GetValue(); + random = Glitter::counter.GetValue(); random_shared.value = random; if (!(eff->data.flags & EFFECT_LOCAL) && data.ext_anim) { diff --git a/src/DivaGL/Glitter/emitter_inst.cpp b/src/DivaGL/Glitter/emitter_inst.cpp index 2d40af5..58b54bd 100644 --- a/src/DivaGL/Glitter/emitter_inst.cpp +++ b/src/DivaGL/Glitter/emitter_inst.cpp @@ -168,7 +168,7 @@ namespace Glitter { switch (data.direction) { case DIRECTION_BILLBOARD: { if (eff_inst->data.flags & EFFECT_LOCAL) { - mat4_transpose(&camera_data->view, &dir_mat); + mat4_transpose(&camera_data.view, &dir_mat); mat4_clear_trans(&dir_mat, &dir_mat); mat4_mul(&dir_mat, &mat, &dir_mat); } @@ -177,7 +177,7 @@ namespace Glitter { mat4 inv_view_mat; mat3 inv_view_mat3; - mat4_transpose(&camera_data->view, &inv_view_mat); + mat4_transpose(&camera_data.view, &inv_view_mat); mat4_to_mat3(&inv_view_mat, &inv_view_mat3); mat3_invert(&inv_view_mat3, &inv_view_mat3); mat4_from_mat3(&inv_view_mat3, &inv_view_mat); @@ -191,7 +191,7 @@ namespace Glitter { mat4_rotate_x((float_t)-M_PI_2, &dir_mat); break; case DIRECTION_BILLBOARD_Y_AXIS: - mat4_rotate_y(camera_data->rotation.y, &dir_mat); + mat4_rotate_y(camera_data.rotation.y, &dir_mat); break; default: mult = false; @@ -287,7 +287,7 @@ namespace Glitter { switch (data.direction) { case DIRECTION_BILLBOARD: { mat3 inv_view_mat3; - mat4_transpose(&camera_data->view, &dir_mat); + mat4_transpose(&camera_data.view, &dir_mat); mat4_to_mat3(&dir_mat, &inv_view_mat3); mat3_invert(&inv_view_mat3, &inv_view_mat3); mat4_from_mat3(&inv_view_mat3, &dir_mat); @@ -301,7 +301,7 @@ namespace Glitter { mat4_rotate_x((float_t)-M_PI_2, &dir_mat); break; case DIRECTION_BILLBOARD_Y_AXIS: - mat4_rotate_y(camera_data->rotation.y, &dir_mat); + mat4_rotate_y(camera_data.rotation.y, &dir_mat); break; default: mult = false; diff --git a/src/DivaGL/Glitter/file_reader.cpp b/src/DivaGL/Glitter/file_reader.cpp index bce33ba..ef7bcec 100644 --- a/src/DivaGL/Glitter/file_reader.cpp +++ b/src/DivaGL/Glitter/file_reader.cpp @@ -662,7 +662,7 @@ namespace Glitter { ids[i] = texture_id(0x2A, GPM_VAL->texture_counter++); txp_set_load(st->data.data(), &eff_group->resources, (uint32_t*)ids); - free_def(ids); + _operator_delete(ids); uint32_t* resource_hashes = this->resource_hashes; diff --git a/src/DivaGL/Glitter/glitter.cpp b/src/DivaGL/Glitter/glitter.cpp index 25f87c9..42fed6e 100644 --- a/src/DivaGL/Glitter/glitter.cpp +++ b/src/DivaGL/Glitter/glitter.cpp @@ -11,21 +11,21 @@ namespace Glitter { const float_t min_emission = 0.01f; - void axis_angle_from_vectors(vec3* axis, float_t* angle, const vec3* vec1, const vec3* vec2) { - *axis = vec3::cross(*vec1, *vec2); - *angle = vec3::length(*axis); + void axis_angle_from_vectors(vec3& axis, float_t& angle, const vec3& vec1, const vec3& vec2) { + axis = vec3::cross(vec1, vec2); + angle = vec3::length(axis); - if (*angle >= 0.000001f) - *angle = asinf(clamp_def(*angle, -1.0f, 1.0f)); + if (angle >= 0.000001f) + angle = asinf(clamp_def(angle, -1.0f, 1.0f)); else { - *angle = 0.0f; - *axis = vec3::cross(vec3(0.0f, 1.0f, 0.0f), *vec1); - if (vec3::length(*axis) < 0.000001f) - *axis = vec3::cross(vec3(0.0f, 0.0f, 1.0f), *vec1); + angle = 0.0f; + axis = vec3::cross(vec3(0.0f, 1.0f, 0.0f), vec1); + if (vec3::length(axis) < 0.000001f) + axis = vec3::cross(vec3(0.0f, 0.0f, 1.0f), vec1); } - if (vec3::dot(*vec1, *vec2) < 0.0f) - *angle = (float_t)M_PI - *angle; + if (vec3::dot(vec1, vec2) < 0.0f) + angle = (float_t)M_PI - angle; } void CreateBuffer(size_t max_count, bool is_quad, diff --git a/src/DivaGL/Glitter/glitter.hpp b/src/DivaGL/Glitter/glitter.hpp index 1ef5a50..695ea95 100644 --- a/src/DivaGL/Glitter/glitter.hpp +++ b/src/DivaGL/Glitter/glitter.hpp @@ -1499,9 +1499,9 @@ namespace Glitter { extern GltParticleManager* glt_particle_manager; extern GltParticleManagerX* glt_particle_manager_x; extern RandomX random_x; - extern Counter* counter; + extern Counter& counter; - extern void axis_angle_from_vectors(vec3* axis, float_t* angle, const vec3* vec0, const vec3* vec1); + extern void axis_angle_from_vectors(vec3& axis, float_t& angle, const vec3& vec0, const vec3& vec1); extern void CreateBuffer(size_t max_count, bool is_quad, Buffer*& buffer, GLuint& vao, GL::ArrayBuffer& vbo, GL::ElementArrayBuffer& ebo); diff --git a/src/DivaGL/Glitter/locus_history.cpp b/src/DivaGL/Glitter/locus_history.cpp index f962b23..6c58c80 100644 --- a/src/DivaGL/Glitter/locus_history.cpp +++ b/src/DivaGL/Glitter/locus_history.cpp @@ -55,5 +55,4 @@ namespace Glitter { hist_data->translation = temp; } } - } diff --git a/src/DivaGL/Glitter/render_group.cpp b/src/DivaGL/Glitter/render_group.cpp index 443bbc8..c9546b2 100644 --- a/src/DivaGL/Glitter/render_group.cpp +++ b/src/DivaGL/Glitter/render_group.cpp @@ -24,7 +24,7 @@ namespace Glitter { vec3 axis; float_t angle; - axis_angle_from_vectors(&axis, &angle, &vec1, &vec2); + axis_angle_from_vectors(axis, angle, vec1, vec2); mat4_mul_rotation(&mat, &axis, angle, &mat); } else @@ -47,7 +47,7 @@ namespace Glitter { vec3 axis; float_t angle; - axis_angle_from_vectors(&axis, &angle, &vec1, &vec2); + axis_angle_from_vectors(axis, angle, vec1, vec2); mat4_mul_rotation(&mat, &axis, angle, &mat); } return mat; @@ -467,7 +467,7 @@ namespace Glitter { vec3 axis; float_t angle; - axis_angle_from_vectors(&axis, &angle, &vec1, &vec2); + axis_angle_from_vectors(axis, angle, vec1, vec2); mat4 mat = mat4_identity; mat4_mul_rotation(&mat, &axis, angle, &mat); @@ -487,7 +487,7 @@ namespace Glitter { vec3 axis; float_t angle; - axis_angle_from_vectors(&axis, &angle, &vec1, &vec2); + axis_angle_from_vectors(axis, angle, vec1, vec2); mat4 mat = mat4_identity; mat4_mul_rotation(&mat, &axis, angle, &mat); @@ -509,7 +509,7 @@ namespace Glitter { vec3 axis; float_t angle; - axis_angle_from_vectors(&axis, &angle, &vec1, &vec2); + axis_angle_from_vectors(axis, angle, vec1, vec2); mat4 mat = mat4_identity; mat4_mul_rotation(&mat, &axis, angle, &mat); @@ -529,7 +529,7 @@ namespace Glitter { vec3 axis; float_t angle; - axis_angle_from_vectors(&axis, &angle, &vec1, &vec2); + axis_angle_from_vectors(axis, angle, vec1, vec2); mat4 mat = mat4_identity; mat4_mul_rotation(&mat, &axis, angle, &mat); diff --git a/src/DivaGL/Glitter/render_scene.cpp b/src/DivaGL/Glitter/render_scene.cpp index f69d9c3..5bae7f6 100644 --- a/src/DivaGL/Glitter/render_scene.cpp +++ b/src/DivaGL/Glitter/render_scene.cpp @@ -9,6 +9,9 @@ #include "../shader_ft.hpp" #include "../wrap.hpp" +extern bool reflect_draw; +extern mat4 reflect_mat; + namespace Glitter { void RenderScene::CalcDisp() { disp_quad = 0; @@ -88,8 +91,8 @@ namespace Glitter { mat4 cam_view; mat4 cam_projection; - mat4_transpose(&camera_data->view, &cam_view); - mat4_transpose(&camera_data->projection, &cam_projection); + mat4_transpose(&camera_data.view, &cam_view); + mat4_transpose(&camera_data.projection, &cam_projection); mat4 mat; mat4_transpose(&rend_group->mat_draw, &mat); @@ -368,8 +371,8 @@ namespace Glitter { mat4 cam_view; mat4 cam_inv_view; - mat4_transpose(&camera_data->view, &cam_view); - mat4_transpose(&camera_data->inv_view, &cam_inv_view); + mat4_transpose(&camera_data.view, &cam_view); + mat4_transpose(&camera_data.inv_view, &cam_inv_view); vec3 x_vec = { 1.0f, 0.0f, 0.0f }; if (rend_group->flags & PARTICLE_LOCAL) { @@ -511,8 +514,8 @@ namespace Glitter { mat4 cam_view; mat4 cam_inv_view; - mat4_transpose(&camera_data->view, &cam_view); - mat4_transpose(&camera_data->inv_view, &cam_inv_view); + mat4_transpose(&camera_data.view, &cam_view); + mat4_transpose(&camera_data.inv_view, &cam_inv_view); mat4 model_mat; mat4 view_mat; @@ -571,7 +574,7 @@ namespace Glitter { mat4_rotate_z((float_t)-M_PI_2, &dir_mat); break; case DIRECTION_BILLBOARD_Y_AXIS: - mat4_rotate_y(camera_data->rotation.y, &dir_mat); + mat4_rotate_y(camera_data.rotation.y, &dir_mat); break; default: dir_mat = mat4_identity; @@ -717,7 +720,7 @@ namespace Glitter { if (fabsf(rend_group->z_offset) > 0.000001f) { use_z_offset = true; mat4_get_translation(model_mat, &dist_to_cam); - dist_to_cam = camera_data->view_point - dist_to_cam; + dist_to_cam = camera_data.view_point - dist_to_cam; if (rend_group->flags & PARTICLE_EMITTER_LOCAL) { mat4_normalize_rotation(model_mat, &z_offset_inv_mat); mat4_invert(&z_offset_inv_mat, &z_offset_inv_mat); @@ -1197,8 +1200,8 @@ namespace Glitter { mat4 cam_view; mat4 cam_inv_view; - mat4_transpose(&camera_data->view, &cam_view); - mat4_transpose(&camera_data->inv_view, &cam_inv_view); + mat4_transpose(&camera_data.view, &cam_view); + mat4_transpose(&camera_data.inv_view, &cam_inv_view); vec3 x_vec = { 1.0f, 0.0f, 0.0f }; if (rend_group->flags & PARTICLE_LOCAL) { @@ -1338,8 +1341,8 @@ namespace Glitter { mat4 cam_view; mat4 cam_inv_view; - mat4_transpose(&camera_data->view, &cam_view); - mat4_transpose(&camera_data->inv_view, &cam_inv_view); + mat4_transpose(&camera_data.view, &cam_view); + mat4_transpose(&camera_data.inv_view, &cam_inv_view); mat4 model_mat; mat4 view_mat; @@ -1387,7 +1390,7 @@ namespace Glitter { mat4_rotate_x((float_t)-M_PI_2, &dir_mat); break; case DIRECTION_BILLBOARD_Y_AXIS: - mat4_rotate_y(camera_data->rotation.y, &dir_mat); + mat4_rotate_y(camera_data.rotation.y, &dir_mat); break; default: dir_mat = mat4_identity; @@ -1532,7 +1535,7 @@ namespace Glitter { if (fabsf(rend_group->z_offset) > 0.000001f) { use_z_offset = true; mat4_get_translation(model_mat, &dist_to_cam); - dist_to_cam = camera_data->view_point - dist_to_cam; + dist_to_cam = camera_data.view_point - dist_to_cam; if (rend_group->flags & PARTICLE_EMITTER_LOCAL) { mat4_normalize_rotation(model_mat, &z_offset_inv_mat); mat4_invert(&z_offset_inv_mat, &z_offset_inv_mat); @@ -1804,8 +1807,10 @@ namespace Glitter { mat4 cam_view; mat4 cam_projection; - mat4_transpose(&camera_data->view, &cam_view); - mat4_transpose(&camera_data->projection, &cam_projection); + mat4_transpose(&camera_data.view, &cam_view); + if (reflect_draw) + mat4_mul(&reflect_mat, &cam_view, &cam_view); + mat4_transpose(&camera_data.projection, &cam_projection); mat4 mat; mat4_mul(&rend_group->mat_draw, &cam_view, &mat); @@ -1979,8 +1984,8 @@ namespace Glitter { mat4 cam_view; mat4 cam_inv_view; - mat4_transpose(&camera_data->view, &cam_view); - mat4_transpose(&camera_data->inv_view, &cam_inv_view); + mat4_transpose(&camera_data.view, &cam_view); + mat4_transpose(&camera_data.inv_view, &cam_inv_view); bool has_scale = false; bool emitter_local = false; @@ -2044,7 +2049,7 @@ namespace Glitter { mat4_rotate_x((float_t)-M_PI_2, &dir_mat); break; case DIRECTION_BILLBOARD_Y_AXIS: - mat4_rotate_y(camera_data->rotation.y, &dir_mat); + mat4_rotate_y(camera_data.rotation.y, &dir_mat); break; case DIRECTION_EMITTER_ROTATION: emitter_rotation = true; @@ -2096,6 +2101,8 @@ namespace Glitter { const bool object_culling = disp_manager.object_culling; if (local) disp_manager.object_culling = false; + extern bool reflect_full; + mdl::obj_reflect_enable = !local && reflect_full; disp_manager.set_texture_pattern(0, 0); RenderElementX* elem = rend_group->elements; @@ -2159,7 +2166,7 @@ namespace Glitter { elem->mat_draw = mat; mat4_transpose(&mat, &mat); - if (disp_manager.entry_obj_by_object_info(&mat, + if (disp_manager.entry_obj_by_object_info(mat, rend_group->object, &elem->color, 0, local)) disp++; @@ -2170,6 +2177,7 @@ namespace Glitter { rend_group->disp = disp; if (local) disp_manager.object_culling = object_culling; + mdl::obj_reflect_enable = false; } size_t RenderSceneX::GetCtrlCount(ParticleType type) { diff --git a/src/DivaGL/auth_2d.cpp b/src/DivaGL/auth_2d.cpp index f9ffa9b..352c85c 100644 --- a/src/DivaGL/auth_2d.cpp +++ b/src/DivaGL/auth_2d.cpp @@ -217,7 +217,7 @@ void aet_layout_data::put_sprite(int32_t spr_id, spr::SprAttr attr, args.prio = prio; if (pos) *(vec2*)&args.trans.x += *pos; - spr::put_sprite(&args); + spr::put_sprite(args); } void aet_layout_data::set_args(const aet_layout_data* layout, spr::SprArgs* args) { diff --git a/src/DivaGL/auth_3d.cpp b/src/DivaGL/auth_3d.cpp index 046a7df..393b327 100644 --- a/src/DivaGL/auth_3d.cpp +++ b/src/DivaGL/auth_3d.cpp @@ -6,7 +6,9 @@ #include "auth_3d.hpp" #include "../KKdLib/hash.hpp" #include "light_param/fog.hpp" +#include "light_param/light.hpp" #include "mdl/disp_manager.hpp" +#include "pv_game/firstread.hpp" #include "rob/rob.hpp" #include "canonical_properties.hpp" #include "file_handler.hpp" @@ -451,6 +453,7 @@ struct auth_3d { mat4* bone_mats; bool shadow; bool chara_item; + bool reflect; chara_index src_chara; chara_index dst_chara; int32_t pos; @@ -877,6 +880,14 @@ void auth_3d_id::set_pos(int32_t value) { } } +void auth_3d_id::set_reflect(bool value) { + if (id >= 0 && ((id & 0x7FFF) < AUTH_3D_DATA_COUNT)) { + auth_3d* auth = &auth_3d_data->data[id & 0x7FFF]; + if (auth->id == id) + auth->reflect = value; + } +} + void auth_3d_id::set_repeat(bool value) { if (id >= 0 && ((id & 0x7FFF) < AUTH_3D_DATA_COUNT)) { auth_3d* auth = &auth_3d_data->data[id & 0x7FFF]; @@ -966,6 +977,59 @@ int32_t auth_3d_data_get_auth_3d_id(uint32_t uid, object_info obj_info, return -1; } +HOOK(void, FASTCALL, auth_3d_parse, 0x00000001401C15B0, auth_3d* auth) { + originalauth_3d_parse(auth); + + extern bool reflect_full; + extern const firstread* firstread_ptr; + if (!reflect_full || !firstread_ptr || !firstread_ptr->auth_3d_array) + return; + + const firstread_auth_3d_array* auth_3d_array = firstread_ptr->auth_3d_array; + + for (uint32_t i = 0; i < auth_3d_array->num_auth_3d; i++) { + if (auth_3d_array->auth_3d_array[i].uid != auth->uid) + continue; + + const firstread_auth_3d* frg_auth_3d = &auth_3d_array->auth_3d_array[i]; + + auto obj_begin = auth->object.begin(); + auto obj_end = auth->object.end(); + const uint32_t num_object = frg_auth_3d->num_object; + for (uint32_t j = 0; j < num_object; j++) { + const uint64_t name_hash = hash_utf8_xxh3_64bits(frg_auth_3d->object_array[j].name); + for (auth_3d_object& k : auth->object) { + if (name_hash != hash_utf8_xxh3_64bits(k.name.c_str())) + continue; + + const firstread_auth_3d_object* frg_a3d_obj = &frg_auth_3d->object_array[j]; + k.uid_name.assign(frg_a3d_obj->uid_name); + k.object_info = object_database_get_object_info(frg_a3d_obj->uid_name); + + k.reflect = k.uid_name.find("_REFLECT") != -1; + k.refract = k.uid_name.find("_REFRACT") != -1; + break; + } + } + + auto obj_list_begin = auth->object_list.begin(); + auto obj_list_end = auth->object_list.end(); + const uint32_t num_object_list = frg_auth_3d->num_object_list; + for (uint32_t j = 0; j < num_object_list; j++) { + const uint64_t name_hash = hash_utf8_xxh3_64bits(frg_auth_3d->object_list_array[j].name); + for (auto obj_list = obj_list_begin; obj_list != obj_list_end; ) + if (name_hash == hash_utf8_xxh3_64bits((*obj_list)->name.c_str())) { + auth->object_list.erase(obj_list); + obj_list_end = auth->object_list.end(); + break; + } + else + obj_list++; + } + break; + } +} + HOOK(void, FASTCALL, auth_3d_curve_array_free, 0x00000001401C2E30, prj::vector* vec, auth_3d_curve* begin, auth_3d_curve* end) { while (begin != end) { @@ -1037,7 +1101,7 @@ HOOK(void, FASTCALL, auth_3d_m_object_hrc_disp, 0x00000001401D0760, auth_3d_m_ob if (i.mats.size()) disp_manager.entry_obj_by_object_info_object_skin( - i.object_info, 0, 0, auth->alpha, i.mats.data(), 0, 0, &i.model_transform.mat); + i.object_info, 0, 0, auth->alpha, i.mats.data(), 0, 0, i.model_transform.mat); } disp_manager.set_obj_flags(); @@ -1098,7 +1162,7 @@ HOOK(void, FASTCALL, auth_3d_object_hrc_disp, 0x00000001401D04A0, auth_3d_object if (oh->node_bone_mats.size()) disp_manager.entry_obj_by_object_info_object_skin( - oh->object_info, 0, 0, auth->alpha, oh->node_bone_mats.data(), 0, 0, &mat); + oh->object_info, 0, 0, auth->alpha, oh->node_bone_mats.data(), 0, 0, mat); disp_manager.set_obj_flags(); disp_manager.set_shadow_type(SHADOW_CHARA); @@ -1118,7 +1182,7 @@ HOOK(void, FASTCALL, auth_3d_object_disp, 0x00000001401D0970, auth_3d_object* o, if (!auth->visible) { if (auth->pos) - spr::put_rgb_cross(&o->model_transform.mat); + spr::put_rgb_cross(o->model_transform.mat); for (auth_3d_object*& i : o->children_object) implOfauth_3d_object_disp(i, auth); @@ -1196,7 +1260,7 @@ HOOK(void, FASTCALL, auth_3d_object_disp, 0x00000001401D0970, auth_3d_object* o, int32_t uid_name_length = (int32_t)o->uid_name.size(); if (uid_name_length <= 3) - disp_manager.entry_obj_by_object_info(&mat, o->object_info); + disp_manager.entry_obj_by_object_info(mat, o->object_info); else if (o->morph.curve) { float_t morph = o->morph.value; int32_t morph_int = (int32_t)morph; @@ -1211,9 +1275,9 @@ HOOK(void, FASTCALL, auth_3d_object_disp, 0x00000001401D0970, auth_3d_object* o, sprintf_s(buf, sizeof(buf), "%.*s%03d", uid_name_length - 3, uid_name, morph_int); object_info obj_info = object_database_get_object_info(buf); if (auth->alpha < 0.999f) - disp_manager.entry_obj_by_object_info(&mat, obj_info, auth->alpha); + disp_manager.entry_obj_by_object_info(mat, obj_info, auth->alpha); else - disp_manager.entry_obj_by_object_info(&mat, obj_info); + disp_manager.entry_obj_by_object_info(mat, obj_info); disp_manager.set_morph({}, 0.0f); } else { @@ -1224,24 +1288,24 @@ HOOK(void, FASTCALL, auth_3d_object_disp, 0x00000001401D0970, auth_3d_object* o, object_info obj_info = object_database_get_object_info(buf); if (obj_info.is_null()) obj_info = o->object_info; - disp_manager.entry_obj_by_object_info(&mat, obj_info); + disp_manager.entry_obj_by_object_info(mat, obj_info); } } else if (o->pattern.curve) { sprintf_s(buf, sizeof(buf), "%.*s%03d", uid_name_length - 3, uid_name, (int32_t)prj::roundf(o->pattern.value)); object_info obj_info = object_database_get_object_info(buf); - disp_manager.entry_obj_by_object_info(&mat, obj_info); + disp_manager.entry_obj_by_object_info(mat, obj_info); } else - disp_manager.entry_obj_by_object_info(&mat, o->object_info); + disp_manager.entry_obj_by_object_info(mat, o->object_info); disp_manager.set_texture_transform(); disp_manager.set_texture_pattern(); disp_manager.set_obj_flags(); if (auth->pos) - spr::put_rgb_cross(&o->model_transform.mat); + spr::put_rgb_cross(o->model_transform.mat); for (auth_3d_object*& i : o->children_object) implOfauth_3d_object_disp(i, auth); @@ -1254,7 +1318,10 @@ HOOK(void, FASTCALL, auth_3d__disp, 0x00000001401D1230, auth_3d* auth) { return; auth_3d_set_material_list(auth); + extern bool reflect_full; + mdl::obj_reflect_enable = reflect_full && auth->reflect; originalauth_3d__disp(auth); + mdl::obj_reflect_enable = false; disp_manager->set_material_list(); } @@ -1298,9 +1365,10 @@ void auth_3d_patch() { // Move both auth_3d_curve's value and type WRITE_MEMORY_STRING(0x00000001401B316A, "\x48\x8B\x43\x68\x48\x89" "\x47\x68\x48\x8B\xC7\x48\x8B\x5C\x24\x48\x48\x83\xC4\x30\x5F\xC3", 0x16); - // Null both auth_3d's shadow and chara_item + // Null auth_3d's shadow, chara_item and reflect WRITE_MEMORY_STRING(0x00000001401D7A78, "\x44\x89\xBF\x98\x00\x00\x00", 0x07); + INSTALL_HOOK(auth_3d_parse); INSTALL_HOOK(auth_3d_curve_array_free); INSTALL_HOOK(auth_3d_m_object_hrc_disp); INSTALL_HOOK(auth_3d_object_hrc_disp); diff --git a/src/DivaGL/auth_3d.hpp b/src/DivaGL/auth_3d.hpp index 975abd8..481f47a 100644 --- a/src/DivaGL/auth_3d.hpp +++ b/src/DivaGL/auth_3d.hpp @@ -59,6 +59,7 @@ struct auth_3d_id { void set_max_frame(float_t value); void set_paused(bool value); void set_pos(int32_t value); + void set_reflect(bool value); void set_repeat(bool value); void set_req_frame(float_t value); void set_shadow(bool value); diff --git a/src/DivaGL/camera.cpp b/src/DivaGL/camera.cpp index de69254..c5e6f9e 100644 --- a/src/DivaGL/camera.cpp +++ b/src/DivaGL/camera.cpp @@ -8,10 +8,10 @@ #include "resolution_mode.hpp" #include -camera_struct* camera_data = (camera_struct*)0x0000000140FBC2C0; +camera_struct& camera_data = *(camera_struct*)0x0000000140FBC2C0; -static void (FASTCALL* camera_struct__update_view)(camera_struct* cam) - = (void (FASTCALL*)(camera_struct * cam))0x00000001401F7690; +static void (FASTCALL* camera_struct__update_view)(camera_struct& cam) + = (void (FASTCALL*)(camera_struct & cam))0x00000001401F7690; HOOK(void, FASTCALL, camera_data_update_projection, 0x00000001401F8E90) { resolution_struct* res_wind = res_window_get(); @@ -22,15 +22,15 @@ HOOK(void, FASTCALL, camera_data_update_projection, 0x00000001401F8E90) { float_t render_half_width = (float_t)res_wind_int->width * 0.5f; float_t render_half_height = (float_t)res_wind_int->height * 0.5f; - float_t aet_depth = camera_data->aet_depth; + float_t aet_depth = camera_data.aet_depth; - float_t spr_2d_range = camera_data->min_distance / aet_depth; + float_t spr_2d_range = camera_data.min_distance / aet_depth; float_t spr_2d_range_x = spr_2d_range * sprite_half_width; float_t spr_2d_range_y = spr_2d_range * sprite_half_height; mat4 spr_2d_proj; mat4_frustrum(-spr_2d_range_x, spr_2d_range_x, spr_2d_range_y, -spr_2d_range_y, - camera_data->min_distance, 3000.0f, &spr_2d_proj); + camera_data.min_distance, 3000.0f, &spr_2d_proj); vec3 spr_2d_viewpoint = { sprite_half_width, sprite_half_height, aet_depth }; vec3 spr_2d_interest = { sprite_half_width, sprite_half_height, 0.0f }; @@ -39,17 +39,17 @@ HOOK(void, FASTCALL, camera_data_update_projection, 0x00000001401F8E90) { mat4_look_at(&spr_2d_viewpoint, &spr_2d_interest, &spr_2d_up, &spr_2d_view); mat4_mul(&spr_2d_view, &spr_2d_proj, &spr_2d_proj); - mat4_transpose(&spr_2d_proj, &camera_data->view_projection_aet_2d); + mat4_transpose(&spr_2d_proj, &camera_data.view_projection_aet_2d); - float_t aet_3d_depth = render_half_height / tanf(camera_data->aet_fov * 0.5f * DEG_TO_RAD_FLOAT); + float_t aet_3d_depth = render_half_height / tanf(camera_data.aet_fov * 0.5f * DEG_TO_RAD_FLOAT); - float_t spr_3d_range = camera_data->min_distance / aet_3d_depth; + float_t spr_3d_range = camera_data.min_distance / aet_3d_depth; float_t spr_3d_range_x = spr_3d_range * render_half_width; float_t spr_3d_range_y = spr_3d_range * render_half_height; mat4 spr_3d_proj; mat4_frustrum(-spr_3d_range_x, spr_3d_range_x, spr_3d_range_y, -spr_3d_range_y, - camera_data->min_distance, 3000.0f, &spr_3d_proj); + camera_data.min_distance, 3000.0f, &spr_3d_proj); vec3 spr_3d_viewpoint = { render_half_width, render_half_height, aet_3d_depth }; vec3 spr_3d_interest = { render_half_width, render_half_height, 0.0f }; @@ -58,21 +58,21 @@ HOOK(void, FASTCALL, camera_data_update_projection, 0x00000001401F8E90) { mat4_look_at(&spr_3d_viewpoint, &spr_3d_interest, &spr_3d_up, &spr_3d_view); mat4_mul(&spr_3d_view, &spr_3d_proj, &spr_3d_proj); - mat4_transpose(&spr_3d_proj, &camera_data->view_projection_aet_3d); + mat4_transpose(&spr_3d_proj, &camera_data.view_projection_aet_3d); - render_get()->calc_projection_matrix(&camera_data->projection, camera_data->fov, - (float_t)camera_data->aspect, camera_data->min_distance, camera_data->max_distance, - camera_data->proj_left_offset, camera_data->proj_right_offset, - camera_data->proj_bottom_offset, camera_data->proj_top_offset); - camera_data->fov_horizontal_rad = tanf(camera_data->fov * 0.5f * DEG_TO_RAD_FLOAT); + render_get()->calc_projection_matrix(&camera_data.projection, camera_data.fov, + (float_t)camera_data.aspect, camera_data.min_distance, camera_data.max_distance, + camera_data.proj_left_offset, camera_data.proj_right_offset, + camera_data.proj_bottom_offset, camera_data.proj_top_offset); + camera_data.fov_horizontal_rad = tanf(camera_data.fov * 0.5f * DEG_TO_RAD_FLOAT); } HOOK(void, FASTCALL, camera_update, 0x00000001401F8970) { implOfcamera_data_update_projection(); camera_struct__update_view(camera_data); - camera_data->fast_change_hist1 = camera_data->fast_change_hist0; - camera_data->fast_change_hist0 = camera_data->fast_change; - camera_data->fast_change = false; + camera_data.fast_change_hist1 = camera_data.fast_change_hist0; + camera_data.fast_change_hist0 = camera_data.fast_change; + camera_data.fast_change = false; } void camera_struct::get_view_point(vec3& value) { diff --git a/src/DivaGL/camera.hpp b/src/DivaGL/camera.hpp index fa8ca7e..75428b6 100644 --- a/src/DivaGL/camera.hpp +++ b/src/DivaGL/camera.hpp @@ -59,6 +59,6 @@ struct camera_struct { static void update_data(); }; -extern camera_struct* camera_data; +extern camera_struct& camera_data; extern void camera_patch(); diff --git a/src/DivaGL/data_test/rob_osage_test.cpp b/src/DivaGL/data_test/rob_osage_test.cpp index 5edc2ce..ac28ae1 100644 --- a/src/DivaGL/data_test/rob_osage_test.cpp +++ b/src/DivaGL/data_test/rob_osage_test.cpp @@ -998,7 +998,7 @@ void RobOsageTest::disp_coli() { etc.data.capsule.wire = false; etc.data.capsule.pos[0] = j[-1].pos; etc.data.capsule.pos[1] = j[ 0].pos; - disp_manager->entry_obj_etc(&mat4_identity, &etc); + disp_manager->entry_obj_etc(mat4_identity, etc); } } else if (cls && cls->rob.nodes.size() >= cls->rob.root_count) { @@ -1022,7 +1022,7 @@ void RobOsageTest::disp_coli() { mat4_translate(&pos, &mat); mat4_transpose(&mat, &mat); - disp_manager->entry_obj_etc(&mat, &etc); + disp_manager->entry_obj_etc(mat, etc); } } } @@ -1068,7 +1068,7 @@ void RobOsageTest::disp_coli_cls_list(ExNodeBlock* ex_node, SkinParam::Collision mat4_translate(&pos, &mat); mat4_transpose(&mat, &mat); - disp_manager->entry_obj_etc(&mat, &etc); + disp_manager->entry_obj_etc(mat, etc); } break; case SkinParam::CollisionTypeCapsule: { mdl::EtcObj etc(mdl::ETC_OBJ_CAPSULE); @@ -1086,7 +1086,7 @@ void RobOsageTest::disp_coli_cls_list(ExNodeBlock* ex_node, SkinParam::Collision mat4_transpose(&transform[i.node_idx[1]], &mat); mat4_transform_point(&mat, &i.pos[1], &etc.data.capsule.pos[1]); mat4_transpose(&mat, &mat); - disp_manager->entry_obj_etc(&mat4_identity, &etc); + disp_manager->entry_obj_etc(mat4_identity, etc); } break; case SkinParam::CollisionTypePlane: { mdl::EtcObj etc(mdl::ETC_OBJ_PLANE); @@ -1105,7 +1105,7 @@ void RobOsageTest::disp_coli_cls_list(ExNodeBlock* ex_node, SkinParam::Collision const vec3 up = { 0.0f, 1.0f, 0.0f }; vec3 axis; float_t angle; - Glitter::axis_angle_from_vectors(&axis, &angle, &up, &dir); + Glitter::axis_angle_from_vectors(axis, angle, up, dir); mat4 mat_rot = mat4_identity; mat4_mul_rotation(&mat_rot, &axis, angle, &mat_rot); @@ -1114,7 +1114,7 @@ void RobOsageTest::disp_coli_cls_list(ExNodeBlock* ex_node, SkinParam::Collision mat4_mul(&mat_rot, &mat, &mat); mat4_scale_rot(&mat, i.radius, &mat); mat4_transpose(&mat, &mat); - disp_manager->entry_obj_etc(&mat, &etc); + disp_manager->entry_obj_etc(mat, etc); } break; case SkinParam::CollisionTypeEllipse: { mdl::EtcObj etc(mdl::ETC_OBJ_SPHERE); @@ -1140,7 +1140,7 @@ void RobOsageTest::disp_coli_cls_list(ExNodeBlock* ex_node, SkinParam::Collision const vec3 up = { 0.0f, 1.0f, 0.0f }; vec3 axis; float_t angle; - Glitter::axis_angle_from_vectors(&axis, &angle, &up, &dir); + Glitter::axis_angle_from_vectors(axis, angle, up, dir); mat4 m = mat4_identity; mat4_mul_rotation(&m, &axis, angle, &m); @@ -1151,7 +1151,7 @@ void RobOsageTest::disp_coli_cls_list(ExNodeBlock* ex_node, SkinParam::Collision mat4_scale_rot(&mat, i.radius, scale_y, i.radius, &mat); mat4_transpose(&mat, &mat); - disp_manager->entry_obj_etc(&mat, &etc); + disp_manager->entry_obj_etc(mat, etc); } break; case SkinParam::CollisionTypeAABB: { mdl::EtcObj etc(mdl::ETC_OBJ_CUBE); @@ -1168,7 +1168,7 @@ void RobOsageTest::disp_coli_cls_list(ExNodeBlock* ex_node, SkinParam::Collision mat4_translate(&pos, &mat); mat4_transpose(&mat, &mat); - disp_manager->entry_obj_etc(&mat, &etc); + disp_manager->entry_obj_etc(mat, etc); } break; } } @@ -1193,9 +1193,9 @@ void RobOsageTest::disp_line() { mat4_scale_rot(&mat, 0.05f, &mat); mat4_transpose(&mat, &mat); if (i == ex_node) - spr::put_cross(&mat, color_red, color_green, color_blue); + spr::put_cross(mat, color_red, color_green, color_blue); else - spr::put_cross(&mat, color_dark_red, color_dark_green, color_dark_blue); + spr::put_cross(mat, color_dark_red, color_dark_green, color_dark_blue); const color4u8 line_color = i == ex_node ? color_white : color_dark_cyan; const color4u8 rect_color = i == ex_node ? color_red : color_dark_red; @@ -1212,7 +1212,7 @@ void RobOsageTest::disp_line() { mat4_transpose(i->rob.end_node.bone_node_mat, &mat); mat4_scale_rot(&mat, 0.05f, &mat); mat4_transpose(&mat, &mat); - spr::put_cross(&mat, color_dark_red, color_dark_green, color_dark_blue); + spr::put_cross(mat, color_dark_red, color_dark_green, color_dark_blue); } for (ExClothBlock*& i : itm_eq_obj->cloth_blocks) { @@ -1285,7 +1285,7 @@ void RobOsageTest::disp_line_cls_param(const mat4& transform, const vec3& pos) { mat4_transpose(&transform, &mat); mat4_scale_rot(&mat, 0.1f, &mat); mat4_transpose(&mat, &mat); - spr::put_cross(&mat, color_red, color_green, color_blue); + spr::put_cross(mat, color_red, color_green, color_blue); vec3 p; mat4_transform_point(&transform, &pos, &p); diff --git a/src/DivaGL/dllmain.cpp b/src/DivaGL/dllmain.cpp index 42cf64e..9c8a19f 100644 --- a/src/DivaGL/dllmain.cpp +++ b/src/DivaGL/dllmain.cpp @@ -18,6 +18,7 @@ size_t opengl32_handle; size_t dll_handle; bool cpu_caps_aes_ni; bool cpu_caps_f16c; +bool config_reflect_full = true; void FASTCALL divagl_main() { int32_t cpuid_data[4] = {}; diff --git a/src/DivaGL/effect.cpp b/src/DivaGL/effect.cpp index 6f36f30..688c6b9 100644 --- a/src/DivaGL/effect.cpp +++ b/src/DivaGL/effect.cpp @@ -554,7 +554,7 @@ void leaf_particle_draw() { shader_data.g_transform[1] = temp.row1; shader_data.g_transform[2] = temp.row2; shader_data.g_transform[3] = temp.row3; - camera_data->get_view_point(shader_data.g_view_pos); + camera_data.get_view_point(shader_data.g_view_pos); shader_data.g_color = stage_param_data_leaf_current->color; rctx->get_scene_light(&shader_data.g_light_env_stage_diffuse, &shader_data.g_light_env_stage_specular, @@ -662,7 +662,7 @@ void particle_draw() { shader_data.g_transform[1] = temp.row1; shader_data.g_transform[2] = temp.row2; shader_data.g_transform[3] = temp.row3; - camera_data->get_view_point(shader_data.g_view_pos); + camera_data.get_view_point(shader_data.g_view_pos); light_chara.get_diffuse(shader_data.g_light_env_chara_diffuse); light_chara.get_specular(shader_data.g_light_env_chara_specular); particle_scene_ubo.WriteMemory(shader_data); @@ -690,7 +690,7 @@ void snow_particle_draw() { gl_state_enable_depth_test(); gl_state_set_depth_mask(GL_FALSE); - float_t point_attenuation = powf(tanf((float_t)camera_data->fov + float_t point_attenuation = powf(tanf((float_t)camera_data.fov * 0.5f * DEG_TO_RAD_FLOAT) * 3.4f, 2.0f) * 0.1f; snow_particle_scene_shader_data snow_scene = {}; @@ -741,7 +741,7 @@ void snow_particle_draw() { snow_particle_scene_ubo.Bind(0); snow_particle_batch_ubo.Bind(1); - point_attenuation = powf(tanf((float_t)camera_data->fov + point_attenuation = powf(tanf((float_t)camera_data.fov * 0.5f * DEG_TO_RAD_FLOAT) * 3.4f, 2.0f) * 0.06f; snow_scene.g_state_point_attenuation = { 0.0f, 0.0f, point_attenuation, 0.0f }; @@ -794,7 +794,7 @@ HOOK(void, FASTCALL, EffectFogRing__dest, 0x0000000140348090, EffectFogRing* fog HOOK(void, FASTCALL, EffectFogRing__disp, 0x0000000140348120, EffectFogRing* fog_ring) { if (fog_ring->enable && fog_ring->display) - disp_manager->entry_obj_user(&mat4_identity, + disp_manager->entry_obj_user(mat4_identity, (mdl::UserArgsFunc)draw_fog_particle, fog_ring, mdl::OBJ_TYPE_USER); } @@ -1074,7 +1074,7 @@ HOOK(void, FASTCALL, EffectRipple__draw_static, 0x000000014035AA50, void* data) HOOK(void, FASTCALL, EffectRipple__disp_particles, 0x000000014035AD80, EffectRipple* effect_ripple, ripple_struct* data) { if (data->count > 0) - disp_manager->entry_obj_user(&mat4_identity, + disp_manager->entry_obj_user(mat4_identity, (mdl::UserArgsFunc)draw_ripple_particles, data, mdl::OBJ_TYPE_USER); } @@ -1329,7 +1329,7 @@ HOOK(void, FASTCALL, water_particle__disp, 0x0000000140364090, water_particle* w if (!water_ptcl->splash) return; - disp_manager->entry_obj_user(&mat4_identity, + disp_manager->entry_obj_user(mat4_identity, (mdl::UserArgsFunc)draw_water_particle, water_ptcl, mdl::OBJ_TYPE_TRANSLUCENT); EffectRipple* effect_ripple = effect_ripple_data_get(); @@ -1406,7 +1406,7 @@ void EffectFogRing::draw() { return; draw_state.set_fog_height(true); - RenderTexture& rt = render_manager->get_render_texture(8); + RenderTexture& rt = render_manager.get_render_texture(8); rt.Bind(); gl_state_set_viewport(0, 0, rt.color_texture->get_width_align_mip_level(), @@ -1416,7 +1416,7 @@ void EffectFogRing::draw() { if (disp_manager->get_obj_count(mdl::OBJ_TYPE_USER)) disp_manager->draw(mdl::OBJ_TYPE_USER); gl_state_bind_framebuffer(0); - render_manager->set_effect_texture(rt.color_texture); + render_manager.set_effect_texture(rt.color_texture); gl_state_get_error(); } @@ -1475,7 +1475,7 @@ void EffectRipple::draw() { RenderTexture* rt[3]; for (int32_t i = 0, j = 2; i < 3; i++, j++) - rt[i] = &render_manager->get_render_texture( + rt[i] = &render_manager.get_render_texture( use_float_ripplemap ? j : (j + 3)); if (update) { @@ -1522,8 +1522,8 @@ void EffectRipple::draw() { if (!use_float_ripplemap) v11 += 3; - render_manager->set_effect_texture( - render_manager->get_render_texture(v11).color_texture); + render_manager.set_effect_texture( + render_manager.get_render_texture(v11).color_texture); update = false; @@ -2016,7 +2016,7 @@ static void draw_ripple_particles(ripple_struct* data, mat4* mat) { int32_t size = (int32_t)(data->size + 0.5f); - RenderTexture& rt = render_manager->get_render_texture( + RenderTexture& rt = render_manager.get_render_texture( effect_ripple_data_get()->use_float_ripplemap ? 2 : 5); int32_t width = rt.GetWidth(); int32_t height = rt.GetHeight(); diff --git a/src/DivaGL/graphics/color_change_dw.cpp b/src/DivaGL/graphics/color_change_dw.cpp index e70cb41..e6651e5 100644 --- a/src/DivaGL/graphics/color_change_dw.cpp +++ b/src/DivaGL/graphics/color_change_dw.cpp @@ -145,7 +145,7 @@ HOOK(void, FASTCALL, ColorChangeDw__Draw, 0x00000001402C2170, ColorChangeDw* Thi args.texture = org_tex; if (This->auto_resize) args.SetSpriteSize({ 256.0f, 256.0f }); - spr::put_sprite(&args); + spr::put_sprite(args); } if (chg_tex) { @@ -156,7 +156,7 @@ HOOK(void, FASTCALL, ColorChangeDw__Draw, 0x00000001402C2170, ColorChangeDw* Thi args.SetSpriteSize({ 256.0f, 256.0f }); args.trans.x = 266.0f; } - spr::put_sprite(&args); + spr::put_sprite(args); } } diff --git a/src/DivaGL/hook.cpp b/src/DivaGL/hook.cpp index aed5f39..40f5d35 100644 --- a/src/DivaGL/hook.cpp +++ b/src/DivaGL/hook.cpp @@ -75,6 +75,7 @@ HOOK(int32_t, FASTCALL, data_init, 0x0000000140192FF0) { Glitter::Patch(); rctx = new render_context; + reflect_full_init(); int32_t ret = originaldata_init(); extern size_t diva_handle; @@ -98,6 +99,7 @@ HOOK(int32_t, FASTCALL, data_free, 0x000000140192490) { rctx->free(); int32_t ret = originaldata_free(); + reflect_full_free(); delete rctx; rctx = 0; return ret; @@ -156,20 +158,20 @@ HOOK(void, FASTCALL, rndr__Render__movie_texture_free, 0x00000001404B18F0, HOOK(void, FASTCALL, rndr__RenderManager__rndpass_pre_proc, 0x0000000140502C90) { gl_state_begin_event("rndpass_pre_proc"); - render_manager->render->pre_proc(); + render_manager.render->pre_proc(); Glitter::glt_particle_manager->CalcDisp(); Glitter::glt_particle_manager_x->CalcDisp(); gl_state_end_event(); } HOOK(void, FASTCALL, rndr__RenderManager__render_all, 0x0000000140502CA0) { - render_manager->render_all(); + render_manager.render_all(); } HOOK(void, FASTCALL, rndr__RenderManager__rndpass_post_proc, 0x0000000140502C70) { gl_state_begin_event("rndpass_post_proc"); - render_manager->render->post_proc(); - render_manager->field_31C = false; + render_manager.render->post_proc(); + render_manager.field_31C = false; gl_state_end_event(); } diff --git a/src/DivaGL/mdl/disp_manager.cpp b/src/DivaGL/mdl/disp_manager.cpp index 96bb126..f69ad0d 100644 --- a/src/DivaGL/mdl/disp_manager.cpp +++ b/src/DivaGL/mdl/disp_manager.cpp @@ -45,6 +45,9 @@ static void object_data_get_vertex_attrib_buffer_bindings(const mdl::ObjSubMeshA static void sub_140436760(mat4* view); +extern bool reflect_draw; +extern mat4 reflect_mat; + material_list_struct::material_list_struct() : blend_color(), has_blend_color(), emission(), has_emission() { hash = (uint64_t)-1; } @@ -79,6 +82,9 @@ namespace mdl { int32_t material_list_count; material_list_struct material_list_array[MATERIAL_LIST_COUNT]; + + bool obj_reflect_enable; + ObjSubMeshArgs::ObjSubMeshArgs() : sub_mesh(), mesh(), material(), textures(), mat_count(), mats(), vertex_buffer(), vertex_buffer_offset(), index_buffer(), set_blend_color(), chara_color(), self_shadow(), shadow(), morph_vertex_buffer(), morph_vertex_buffer_offset(), morph_weight(), texture_pattern_count(), @@ -213,23 +219,22 @@ namespace mdl { } - void ObjData::init_etc(const mat4* mat, mdl::EtcObj* etc) { + void ObjData::init_etc(const mat4& mat, const mdl::EtcObj& etc) { kind = mdl::OBJ_KIND_ETC; - mat4_transpose(mat, &this->mat); - args.etc = *etc; + mat4_transpose(&mat, &this->mat); + args.etc = etc; disp_manager->add_vertex_array(&args.etc, this->mat); } - void ObjData::init_sub_mesh(const mat4* mat, float_t radius, - const obj_sub_mesh* sub_mesh, const obj_mesh* mesh, const obj_material_data* material, - const prj::vector* textures, int32_t mat_count, const mat4* mats, - GLuint vertex_buffer, size_t vertex_buffer_offset, GLuint index_buffer, - const vec4& blend_color, const vec4& emission, GLuint morph_vertex_buffer, - size_t morph_vertex_buffer_offset, int32_t instances_count, mat4* instances_mat, - void(FASTCALL* func)(const ObjSubMeshArgs*), const ObjSubMeshArgs* func_data) { + void ObjData::init_sub_mesh(const mat4& mat, float_t radius, const obj_sub_mesh* sub_mesh, + const obj_mesh* mesh, const obj_material_data* material, const prj::vector* textures, + int32_t mat_count, const mat4* mats, GLuint vertex_buffer, size_t vertex_buffer_offset, + GLuint index_buffer, const vec4& blend_color, const vec4& emission, GLuint morph_vertex_buffer, + size_t morph_vertex_buffer_offset, + int32_t instances_count, const mat4* instances_mat, draw_func func, const ObjSubMeshArgs* func_data) { kind = mdl::OBJ_KIND_NORMAL; - mat4_transpose(mat, &this->mat); + mat4_transpose(&mat, &this->mat); this->radius = radius; mdl::ObjSubMeshArgs* args = &this->args.sub_mesh; @@ -284,15 +289,15 @@ namespace mdl { disp_manager->add_vertex_array(args); } - void ObjData::init_translucent(const mat4* mat, ObjTranslucentArgs* translucent) { + void ObjData::init_translucent(const mat4& mat, const ObjTranslucentArgs& translucent) { kind = mdl::OBJ_KIND_TRANSLUCENT; - mat4_transpose(mat, &this->mat); - args.translucent = *translucent; + mat4_transpose(&mat, &this->mat); + args.translucent = translucent; } - void ObjData::init_user(const mat4* mat, UserArgsFunc func, void* data) { + void ObjData::init_user(const mat4& mat, UserArgsFunc func, void* data) { kind = OBJ_KIND_USER; - mat4_transpose(mat, &this->mat); + mat4_transpose(&mat, &this->mat); args.user.func = func; args.user.data = data; } @@ -1549,7 +1554,7 @@ namespace mdl { const vec3 up = { 0.0f, 1.0f, 0.0f }; vec3 axis; float_t angle; - Glitter::axis_angle_from_vectors(&axis, &angle, &up, &dir); + Glitter::axis_angle_from_vectors(axis, angle, up, dir); mat4 m = mat4_identity; mat4_mul_rotation(&m, &axis, angle, &m); @@ -1570,7 +1575,7 @@ namespace mdl { const vec3 up = { 0.0f, 1.0f, 0.0f }; vec3 axis; float_t angle; - Glitter::axis_angle_from_vectors(&axis, &angle, &up, &dir); + Glitter::axis_angle_from_vectors(axis, angle, up, dir); mat4 m = mat4_identity; mat4_mul_rotation(&m, &axis, angle, &m); @@ -1923,7 +1928,7 @@ namespace mdl { mat4 mat; mat4_translate(&i, &mat); mat4_transpose(&mat, &mat); - entry_obj_etc(&mat, &etc); + entry_obj_etc(mat, etc); } if (show_mat_center && type == OBJ_TYPE_TRANSLUCENT) @@ -1938,7 +1943,7 @@ namespace mdl { mat4 mat; mat4_translate(&i, &mat); mat4_transpose(&mat, &mat); - entry_obj_etc(&mat, &etc); + entry_obj_etc(mat, etc); } } @@ -1972,7 +1977,7 @@ namespace mdl { } void DispManager::draw(ObjType type, int32_t depth_mask, bool reflect_texture_mask, int32_t alpha) { - if (type < 0 || type >= mdl::OBJ_TYPE_LOCAL_MAX || get_obj_count(type) < 1) + if (type < 0 || type >= OBJ_TYPE_REFLECT_MAX || get_obj_count(type) < 1) return; int32_t alpha_test = 0; @@ -1997,6 +2002,7 @@ namespace mdl { func = draw_sub_mesh_translucent; else gl_state_set_depth_mask(GL_FALSE); + alpha_test = 1; min_alpha = 0.0f; alpha_threshold = 0.0f; @@ -2022,48 +2028,79 @@ namespace mdl { func = draw_sub_mesh_translucent; gl_state_set_color_mask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); draw_state.shader_index = SHADER_FT_SIL; + alpha_test = 1; min_alpha = 0.0f; alpha_threshold = 0.99999994f; break; case OBJ_TYPE_REFLECT_CHARA_OPAQUE: gl_state_set_cull_face_mode(GL_FRONT); - if (reflect) - func = draw_sub_mesh_reflect; - else if (render_manager->reflect_type == STAGE_DATA_REFLECT_REFLECT_MAP) - func = draw_sub_mesh_reflect_reflect_map; + + if (!reflect_draw) { + if (reflect) + func = draw_sub_mesh_reflect; + else if (render_manager.reflect_type == STAGE_DATA_REFLECT_REFLECT_MAP) + func = draw_sub_mesh_reflect_reflect_map; + } break; case OBJ_TYPE_REFLECT_CHARA_TRANSLUCENT: gl_state_set_cull_face_mode(GL_FRONT); - if (reflect) - func = draw_sub_mesh_reflect; - else if (render_manager->reflect_type == STAGE_DATA_REFLECT_REFLECT_MAP) - func = draw_sub_mesh_reflect_reflect_map; + min_alpha = 0.0f; + + if (!reflect_draw) { + if (reflect) + func = draw_sub_mesh_reflect; + else if (render_manager.reflect_type == STAGE_DATA_REFLECT_REFLECT_MAP) + func = draw_sub_mesh_reflect_reflect_map; + } break; case OBJ_TYPE_REFLECT_CHARA_TRANSPARENT: gl_state_set_cull_face_mode(GL_FRONT); - if (reflect) - func = draw_sub_mesh_reflect; - else if (render_manager->reflect_type == STAGE_DATA_REFLECT_REFLECT_MAP) - func = draw_sub_mesh_reflect_reflect_map; + alpha_test = 1; min_alpha = 0.1f; alpha_threshold = 0.5f; + + if (!reflect_draw) { + if (reflect) + func = draw_sub_mesh_reflect; + else if (render_manager.reflect_type == STAGE_DATA_REFLECT_REFLECT_MAP) + func = draw_sub_mesh_reflect_reflect_map; + } break; case OBJ_TYPE_REFLECT_OPAQUE: alpha_test = 1; alpha_threshold = 0.5f; - if (!reflect_texture_mask) + + if (reflect_draw) + gl_state_set_cull_face_mode(GL_FRONT); + else if (!reflect_texture_mask) func = draw_sub_mesh_reflect_reflect_map; break; case OBJ_TYPE_REFLECT_TRANSLUCENT: + gl_state_set_depth_mask(GL_FALSE); + + min_alpha = 0.0f; + alpha_threshold = 0.0f; + + if (reflect_draw) + gl_state_set_cull_face_mode(GL_FRONT); + break; + case OBJ_TYPE_REFLECT_TRANSPARENT: + alpha_test = 1; + min_alpha = 0.1f; + alpha_threshold = 0.5f; + + if (reflect_draw) + gl_state_set_cull_face_mode(GL_FRONT); + break; case OBJ_TYPE_REFRACT_TRANSLUCENT: gl_state_set_depth_mask(GL_FALSE); + min_alpha = 0.0f; alpha_threshold = 0.0f; break; - case OBJ_TYPE_REFLECT_TRANSPARENT: case OBJ_TYPE_REFRACT_TRANSPARENT: alpha_test = 1; min_alpha = 0.1f; @@ -2071,9 +2108,9 @@ namespace mdl { break; case OBJ_TYPE_SSS: func = draw_sub_mesh_sss; - break; - case OBJ_TYPE_USER: - func = draw_sub_mesh_translucent; + + if (reflect_draw) + gl_state_set_cull_face_mode(GL_FRONT); break; case OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_1: case OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_2: @@ -2088,11 +2125,25 @@ namespace mdl { case OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_3: case OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2_LOCAL: gl_state_set_depth_mask(GL_FALSE); + alpha_test = 1; min_alpha = 0.0f; alpha_threshold = 0.0f; break; - default: + case OBJ_TYPE_USER: + func = draw_sub_mesh_translucent; + break; + case OBJ_TYPE_REFLECT_TRANSLUCENT_SORT_BY_RADIUS: + if (depth_mask) + func = draw_sub_mesh_translucent; + else + gl_state_set_depth_mask(GL_FALSE); + + alpha_test = 1; + min_alpha = 0.0f; + alpha_threshold = 0.0f; + + gl_state_set_cull_face_mode(GL_FRONT); break; } rctx->set_batch_alpha_threshold(alpha_threshold); @@ -2141,8 +2192,6 @@ namespace mdl { switch (type) { case OBJ_TYPE_TRANSLUCENT: case OBJ_TYPE_TRANSLUCENT_SORT_BY_RADIUS: - case OBJ_TYPE_REFLECT_TRANSLUCENT: - case OBJ_TYPE_REFRACT_TRANSLUCENT: if (!depth_mask) gl_state_set_depth_mask(GL_TRUE); break; @@ -2156,16 +2205,36 @@ namespace mdl { case OBJ_TYPE_REFLECT_CHARA_TRANSPARENT: gl_state_set_cull_face_mode(GL_BACK); break; - case OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_1: - case OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_2: - case OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_3: - gl_state_set_cull_face_mode(GL_BACK); + case OBJ_TYPE_REFLECT_OPAQUE: + if (reflect_draw) + gl_state_set_cull_face_mode(GL_FRONT); + break; + case OBJ_TYPE_REFLECT_TRANSLUCENT: + if (reflect_draw) + gl_state_set_cull_face_mode(GL_FRONT); + gl_state_set_depth_mask(GL_TRUE); + break; + case OBJ_TYPE_REFLECT_TRANSPARENT: + if (reflect_draw) + gl_state_set_cull_face_mode(GL_FRONT); + break; + case OBJ_TYPE_REFRACT_TRANSLUCENT: + if (reflect_draw) + gl_state_set_cull_face_mode(GL_FRONT); + gl_state_set_depth_mask(GL_TRUE); + break; + case OBJ_TYPE_SSS: + if (reflect_draw) + gl_state_set_cull_face_mode(GL_BACK); break; case OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_1: case OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2: case OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_3: gl_state_set_depth_mask(GL_TRUE); break; + case OBJ_TYPE_REFLECT_TRANSLUCENT_SORT_BY_RADIUS: + gl_state_set_cull_face_mode(GL_BACK); + break; } uniform_value_reset(); @@ -2211,7 +2280,7 @@ namespace mdl { } static int32_t obj_axis_aligned_bounding_box_check_visibility( - obj_axis_aligned_bounding_box* aabb, const mat4* mat) { + obj_axis_aligned_bounding_box* aabb, const mat4& mat) { vec3 points[8]; points[0] = aabb->center + (aabb->size ^ vec3( 0.0f, 0.0f, 0.0f)); points[1] = aabb->center + (aabb->size ^ vec3(-0.0f, -0.0f, -0.0f)); @@ -2223,7 +2292,7 @@ namespace mdl { points[7] = aabb->center + (aabb->size ^ vec3(-0.0f, -0.0f, 0.0f)); mat4 view_mat; - mat4_mul(&camera_data->view, mat, &view_mat); + mat4_mul(&camera_data.view, &mat, &view_mat); mat4_transpose(&view_mat, &view_mat); for (int32_t i = 0; i < 8; i++) @@ -2231,17 +2300,17 @@ namespace mdl { vec4 v2[6]; *(vec3*)&v2[0] = { 0.0f, 0.0f, -1.0f }; - v2[0].w = -camera_data->min_distance; - *(vec3*)&v2[1] = camera_data->field_1E4; + v2[0].w = -camera_data.min_distance; + *(vec3*)&v2[1] = camera_data.field_1E4; v2[1].w = 0.0f; - *(vec3*)&v2[2] = camera_data->field_1F0; + *(vec3*)&v2[2] = camera_data.field_1F0; v2[2].w = 0.0f; - *(vec3*)&v2[3] = camera_data->field_1FC; + *(vec3*)&v2[3] = camera_data.field_1FC; v2[3].w = 0.0f; - *(vec3*)&v2[4] = camera_data->field_208; + *(vec3*)&v2[4] = camera_data.field_208; v2[4].w = 0.0f; *(vec3*)&v2[5] = { 0.0f, 0.0f, 1.0f }; - v2[5].w = camera_data->max_distance; + v2[5].w = camera_data.max_distance; for (int32_t i = 0; i < 6; i++) for (int32_t j = 0; j < 8; j++) { @@ -2255,82 +2324,90 @@ namespace mdl { return 1; } - static int32_t obj_bounding_sphere_check_visibility(obj_bounding_sphere* sphere, - CullingCheck* culling, const mat4* mat) { + static int32_t obj_bounding_sphere_check_visibility(const obj_bounding_sphere& sphere, + CullingCheck* culling, const mat4& mat) { if (disp_manager->culling_func) - return disp_manager->culling_func(sphere); + return disp_manager->culling_func(&sphere); vec3 center; mat4 _mat; - mat4_transpose(mat, &_mat); - mat4_transform_point(&_mat, &sphere->center, ¢er); - float_t radius = mat4_get_max_scale(&_mat) * sphere->radius; + mat4_transpose(&mat, &_mat); + mat4_transform_point(&_mat, &sphere.center, ¢er); + float_t radius = mat4_get_max_scale(&_mat) * sphere.radius; - mat4_transpose(&camera_data->view, &_mat); + mat4_transpose(&camera_data.view, &_mat); mat4_transform_point(&_mat, ¢er, ¢er); double_t min_depth = (double_t)center.z - (double_t)radius; double_t max_depth = (double_t)center.z + (double_t)radius; - if (-camera_data->min_distance < min_depth || -camera_data->max_distance > max_depth) + if (-camera_data.min_distance < min_depth || -camera_data.max_distance > max_depth) return 0; - float_t v5 = vec3::dot(camera_data->field_1E4, center); + float_t v5 = vec3::dot(camera_data.field_1E4, center); if (v5 < -radius) return 0; - float_t v6 = vec3::dot(camera_data->field_1F0, center); + float_t v6 = vec3::dot(camera_data.field_1F0, center); if (v6 < -radius) return 0; - float_t v7 = vec3::dot(camera_data->field_1FC, center); + float_t v7 = vec3::dot(camera_data.field_1FC, center); if (v7 < -radius) return 0; - float_t v8 = vec3::dot(camera_data->field_208, center); + float_t v8 = vec3::dot(camera_data.field_208, center); if (v8 < -radius) return 0; - if (-camera_data->min_distance >= max_depth && -camera_data->max_distance <= min_depth + if (-camera_data.min_distance >= max_depth && -camera_data.max_distance <= min_depth && v5 >= radius && v6 >= radius && v7 >= radius && v8 >= radius) return 1; return 2; } - bool DispManager::entry_obj(::obj* obj, obj_mesh_vertex_buffer* obj_vertex_buf, - obj_mesh_index_buffer* obj_index_buf, const mat4* mat, - prj::vector* textures, vec4* blend_color, mat4* bone_mat, ::obj* object_morph, - obj_mesh_vertex_buffer* obj_morph_vertex_buf, int32_t instances_count, mat4* instances_mat, - void(*func)(const mdl::ObjSubMeshArgs*), const ObjSubMeshArgs* func_data, - bool enable_bone_mat, bool local) { - if (!obj_vertex_buf || !obj_index_buf) + bool DispManager::entry_obj(const ::obj* obj, const mat4& mat, obj_mesh_vertex_buffer* obj_vert_buf, + obj_mesh_index_buffer* obj_index_buf, const prj::vector* textures, const vec4* blend_color, + const mat4* bone_mat, const ::obj* obj_morph, obj_mesh_vertex_buffer* obj_morph_vert_buf, + int32_t instances_count, const mat4* instances_mat, + draw_func func, const ObjSubMeshArgs* func_data, bool enable_bone_mat, bool local) { + if (!obj_vert_buf || !obj_index_buf) return false; camera_struct::update_data(); + mat4 _mat; + if (mdl::obj_reflect_enable) { + mat4_transpose(&mat, &_mat); + mat4_mul(&_mat, &reflect_mat, &_mat); + mat4_transpose(&_mat, &_mat); + } + if (!local && object_culling && !instances_count && !bone_mat && (!obj || !obj_bounding_sphere_check_visibility( - &obj->bounding_sphere, &culling, mat))) { + obj->bounding_sphere, &culling, mat) && !(mdl::obj_reflect_enable + && obj_bounding_sphere_check_visibility( + obj->bounding_sphere, &culling, _mat)))) { culling.culled.objects++; return false; } culling.passed.objects++; for (int32_t i = 0; i < obj->num_mesh; i++) { - obj_mesh* mesh = &obj->mesh_array[i]; - obj_mesh* mesh_morph = 0; - if (obj_vertex_buf && obj_morph_vertex_buf) { - if (obj_vertex_buf[i].get_size() != obj_morph_vertex_buf[i].get_size()) + const obj_mesh* mesh = &obj->mesh_array[i]; + const obj_mesh* mesh_morph = 0; + if (obj_vert_buf && obj_morph_vert_buf) { + if (obj_vert_buf[i].get_size() != obj_morph_vert_buf[i].get_size()) continue; - if (object_morph && i < object_morph->num_mesh) - mesh_morph = &object_morph->mesh_array[i]; + if (obj_morph && i < obj_morph->num_mesh) + mesh_morph = &obj_morph->mesh_array[i]; } if (!local && object_culling && !instances_count && !bone_mat && !obj_bounding_sphere_check_visibility( - &mesh->bounding_sphere, &culling, mat) + mesh->bounding_sphere, &culling, mat) && (!mesh_morph || !obj_bounding_sphere_check_visibility( - &mesh_morph->bounding_sphere, &culling, mat))) { + mesh_morph->bounding_sphere, &culling, mat))) { culling.culled.meshes++; continue; } @@ -2340,15 +2417,16 @@ namespace mdl { int32_t translucent_priority_count = 0; for (int32_t j = 0; j < mesh->num_submesh; j++) { - obj_sub_mesh* sub_mesh = &mesh->submesh_array[j]; - obj_sub_mesh* sub_mesh_morph = 0; + const obj_sub_mesh* sub_mesh = &mesh->submesh_array[j]; + const obj_sub_mesh* sub_mesh_morph = 0; if (sub_mesh->attrib.m.cloth) continue; if (!local && object_culling && !instances_count && !bone_mat) { int32_t v32 = obj_bounding_sphere_check_visibility( - &sub_mesh->bounding_sphere, &culling, mat); - if (v32 != 2 || (!mesh->attrib.m.billboard && !mesh->attrib.m.billboard_y_axis)) { + sub_mesh->bounding_sphere, &culling, mat); + if (v32 != 2 || (!mesh->attrib.m.billboard && !mesh->attrib.m.billboard_y_axis + && !mesh->attrib.m.disable_aabb_culling)) { if (v32 == 2) { if (disp_manager->culling_func) v32 = 1; @@ -2359,18 +2437,18 @@ namespace mdl { if (!v32) { if (!mesh_morph || j >= mesh_morph->num_submesh) { - culling.culled.submesh_array++; + culling.culled.sub_meshes++; continue; } sub_mesh_morph = &mesh_morph->submesh_array[j]; if (!sub_mesh_morph) { - culling.culled.submesh_array++; + culling.culled.sub_meshes++; continue; } v32 = obj_bounding_sphere_check_visibility( - &sub_mesh_morph->bounding_sphere, &culling, mat); + sub_mesh_morph->bounding_sphere, &culling, mat); if (v32 == 2) { if (disp_manager->culling_func) v32 = 1; @@ -2380,16 +2458,16 @@ namespace mdl { } if (!v32) { - culling.culled.submesh_array++; + culling.culled.sub_meshes++; continue; } } } } - culling.passed.submesh_array++; + culling.passed.sub_meshes++; int32_t num_bone_index = sub_mesh->num_bone_index; - uint16_t* bone_index = sub_mesh->bone_index_array; + const uint16_t* bone_index = sub_mesh->bone_index_array; mat4* mats; if (num_bone_index && enable_bone_mat) { @@ -2413,9 +2491,9 @@ namespace mdl { GLuint morph_vertex_buffer = 0; size_t morph_vertex_buffer_offset = 0; - if (obj_morph_vertex_buf) { - morph_vertex_buffer = obj_morph_vertex_buf[i].get_buffer(); - morph_vertex_buffer_offset = obj_morph_vertex_buf[i].get_offset(); + if (obj_morph_vert_buf) { + morph_vertex_buffer = obj_morph_vert_buf[i].get_buffer(); + morph_vertex_buffer_offset = obj_morph_vert_buf[i].get_offset(); } GLuint index_buffer = 0; @@ -2424,15 +2502,15 @@ namespace mdl { GLuint vertex_buffer = 0; size_t vertex_buffer_offset = 0; - if (obj_vertex_buf) { - vertex_buffer = obj_vertex_buf[i].get_buffer(); - vertex_buffer_offset = obj_vertex_buf[i].get_offset(); + if (obj_vert_buf) { + vertex_buffer = obj_vert_buf[i].get_buffer(); + vertex_buffer_offset = obj_vert_buf[i].get_offset(); } - if (!vertex_buffer || !index_buffer || obj_morph_vertex_buf && !morph_vertex_buffer) + if (!vertex_buffer || !index_buffer || obj_morph_vert_buf && !morph_vertex_buffer) continue; - uint64_t material_hash = hash_utf8_fnv1a64m(material->material.name); + const uint64_t material_hash = hash_utf8_fnv1a64m(material->material.name); material_list_struct* mat_list = 0; for (int32_t k = 0; k < material_list_count; k++) @@ -2515,13 +2593,13 @@ namespace mdl { continue; } - obj_material_attrib_member attrib = material->material.attrib.m; + const obj_material_attrib_member attrib = material->material.attrib.m; if (obj_flags & (mdl::OBJ_ALPHA_ORDER_1 | mdl::OBJ_ALPHA_ORDER_2 | mdl::OBJ_ALPHA_ORDER_3) && data->args.sub_mesh.blend_color.w < 1.0f) { if (!(obj_flags & mdl::OBJ_NO_TRANSLUCENCY)) { if (attrib.flag_28 || (attrib.punch_through || !(attrib.alpha_texture | attrib.alpha_material)) - && !sub_mesh->attrib.m.transparent) { + && !sub_mesh->attrib.m.translucent) { if (!attrib.punch_through) { if (obj_flags & mdl::OBJ_ALPHA_ORDER_1) entry_list(OBJ_TYPE_OPAQUE_ALPHA_ORDER_1, data); @@ -2557,7 +2635,7 @@ namespace mdl { else { if (attrib.flag_28 || data->args.sub_mesh.blend_color.w >= 1.0f && (attrib.punch_through || !(attrib.alpha_texture | attrib.alpha_material)) - && !sub_mesh->attrib.m.transparent) { + && !sub_mesh->attrib.m.translucent) { if (obj_flags & mdl::OBJ_SHADOW) entry_list((ObjType)(OBJ_TYPE_SHADOW_CHARA + shadow_type), data); @@ -2623,7 +2701,7 @@ namespace mdl { if (obj_flags & mdl::OBJ_CHARA_REFLECT) entry_list(OBJ_TYPE_REFLECT_CHARA_OPAQUE, data); if (obj_flags & mdl::OBJ_REFLECT) { - if (render_manager->reflect_type != STAGE_DATA_REFLECT_REFLECT_MAP) + if (render_manager.reflect_type != STAGE_DATA_REFLECT_REFLECT_MAP) entry_list(OBJ_TYPE_REFLECT_OPAQUE, data); else entry_list(OBJ_TYPE_REFLECT_TRANSLUCENT, data); @@ -2653,7 +2731,7 @@ namespace mdl { if (!data) continue; - data->init_translucent(mat, &translucent_args); + data->init_translucent(mat, translucent_args); if (obj_flags & mdl::OBJ_ALPHA_ORDER_1) entry_list(OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_1, data); else if (obj_flags & mdl::OBJ_ALPHA_ORDER_2) @@ -2665,27 +2743,289 @@ namespace mdl { entry_list(local ? OBJ_TYPE_TRANSLUCENT_LOCAL : OBJ_TYPE_TRANSLUCENT, data); } + + if (local || (obj_flags & mdl::OBJ_SHADOW_OBJECT) + || (obj_flags & (mdl::OBJ_ALPHA_ORDER_1 | mdl::OBJ_ALPHA_ORDER_2 | mdl::OBJ_ALPHA_ORDER_3) + && blend_color && blend_color->w < 1.0f)) + return true; + + mat4_transpose(&mat, &_mat); + mat4_mul(&_mat, &reflect_mat, &_mat); + mat4_transpose(&_mat, &_mat); + + bool camera_front = vec3::normalize(camera_data.view_point - camera_data.interest).z >= 0.0f; + + for (int32_t i = 0; i < obj->num_mesh; i++) { + const obj_mesh* mesh = &obj->mesh_array[i]; + const obj_mesh* mesh_morph = 0; + if (!mdl::obj_reflect_enable && !mesh->attrib.m.reflect || mesh->attrib.m.no_reflect + || camera_front && mesh->attrib.m.reflect_cam_back) + continue; + + if (obj_vert_buf && obj_morph_vert_buf) { + if (obj_vert_buf[i].get_size() != obj_morph_vert_buf[i].get_size()) + continue; + + if (obj_morph && i < obj_morph->num_mesh) + mesh_morph = &obj_morph->mesh_array[i]; + } + + if (object_culling && !instances_count && !bone_mat + && !obj_bounding_sphere_check_visibility( + mesh->bounding_sphere, &culling, _mat) + && (!mesh_morph || !obj_bounding_sphere_check_visibility( + mesh_morph->bounding_sphere, &culling, _mat))) { + culling.culled.meshes++; + continue; + } + culling.passed.meshes++; + + ObjSubMeshArgs* translucent_priority[40]; + int32_t translucent_priority_count = 0; + + for (int32_t j = 0; j < mesh->num_submesh; j++) { + const obj_sub_mesh* sub_mesh = &mesh->submesh_array[j]; + const obj_sub_mesh* sub_mesh_morph = 0; + if (sub_mesh->attrib.m.cloth || sub_mesh->attrib.m.no_reflect + || !mdl::obj_reflect_enable && !sub_mesh->attrib.m.reflect + || camera_front && sub_mesh->attrib.m.reflect_cam_back) + continue; + + if (object_culling && !instances_count && !bone_mat) { + int32_t v32 = obj_bounding_sphere_check_visibility( + sub_mesh->bounding_sphere, &culling, _mat); + if (v32 != 2 || (!mesh->attrib.m.billboard && !mesh->attrib.m.billboard_y_axis + && !mesh->attrib.m.disable_aabb_culling)) { + if (v32 == 2) { + if (culling_func) + v32 = 1; + else { + obj_axis_aligned_bounding_box aabb = *sub_mesh->axis_aligned_bounding_box; + mat4_transform_point(&reflect_mat, &aabb.center, &aabb.center); + mat4_transform_vector(&reflect_mat, &aabb.size, &aabb.size); + v32 = obj_axis_aligned_bounding_box_check_visibility(&aabb, mat); + } + } + + if (!v32) { + if (!mesh_morph || j >= mesh_morph->num_submesh) { + culling.culled.sub_meshes++; + continue; + } + + sub_mesh_morph = &mesh_morph->submesh_array[j]; + if (!sub_mesh_morph) { + culling.culled.sub_meshes++; + continue; + } + + int32_t v32 = obj_bounding_sphere_check_visibility( + sub_mesh_morph->bounding_sphere, &culling, _mat); + if (v32 == 2) { + if (culling_func) + v32 = 1; + else { + obj_axis_aligned_bounding_box aabb = *sub_mesh_morph->axis_aligned_bounding_box; + mat4_transform_point(&reflect_mat, &aabb.center, &aabb.center); + mat4_transform_vector(&reflect_mat, &aabb.size, &aabb.size); + v32 = obj_axis_aligned_bounding_box_check_visibility(&aabb, mat); + } + } + + if (!v32) { + culling.culled.sub_meshes++; + continue; + } + } + } + } + culling.passed.sub_meshes++; + + int32_t num_bone_index = sub_mesh->num_bone_index; + const uint16_t* bone_index = sub_mesh->bone_index_array; + + mat4* mats; + if (num_bone_index && enable_bone_mat) { + mats = alloc_mat4_array(num_bone_index); + if (bone_mat) + for (int32_t k = 0; k < num_bone_index; k++, bone_index++) + mat4_transpose(&bone_mat[*bone_index], &mats[k]); + else + for (int32_t k = 0; k < num_bone_index; k++) + mats[k] = mat4_identity; + } + else { + mats = 0; + num_bone_index = 0; + } + + obj_material_data* material = &obj->material_array[sub_mesh->material_index]; + ObjData* data = alloc_obj_data(OBJ_KIND_NORMAL); + if (!data) + continue; + + GLuint morph_vertex_buffer = 0; + size_t morph_vertex_buffer_offset = 0; + if (obj_morph_vert_buf) { + morph_vertex_buffer = obj_morph_vert_buf[i].get_buffer(); + morph_vertex_buffer_offset = obj_morph_vert_buf[i].get_offset(); + } + + GLuint index_buffer = 0; + if (obj_index_buf) + index_buffer = obj_index_buf[i].buffer; + + GLuint vertex_buffer = 0; + size_t vertex_buffer_offset = 0; + if (obj_vert_buf) { + vertex_buffer = obj_vert_buf[i].get_buffer(); + vertex_buffer_offset = obj_vert_buf[i].get_offset(); + } + + if (!vertex_buffer || !index_buffer || obj_morph_vert_buf && !morph_vertex_buffer) + continue; + + const uint64_t material_hash = hash_utf8_fnv1a64m(material->material.name); + + const material_list_struct* mat_list = 0; + for (int32_t k = 0; k < material_list_count; k++) + if (material_list_array[k].hash == material_hash) { + mat_list = &material_list_array[k]; + break; + } + + vec4 _blend_color = 1.0f; + vec4 _emission = { 0.0f, 0.0f, 0.0f, 1.0f }; + + if (mat_list) { + bool has_blend_color = false; + if (mat_list->has_blend_color.x) { + _blend_color.x = mat_list->blend_color.x; + has_blend_color = true; + } + + if (mat_list->has_blend_color.y) { + _blend_color.y = mat_list->blend_color.y; + has_blend_color = true; + } + + if (mat_list->has_blend_color.z) { + _blend_color.z = mat_list->blend_color.z; + has_blend_color = true; + } + + if (mat_list->has_blend_color.w) { + _blend_color.w = mat_list->blend_color.w; + has_blend_color = true; + } + + if (blend_color) { + if (!has_blend_color) + _blend_color = *blend_color; + else + _blend_color *= *blend_color; + } + + bool has_emission = false; + if (mat_list->has_emission.x) { + _emission.x = mat_list->emission.x; + has_emission = true; + } + + if (mat_list->has_emission.y) { + _emission.y = mat_list->emission.y; + has_emission = true; + } + + if (mat_list->has_emission.z) { + _emission.z = mat_list->emission.z; + has_emission = true; + } + + if (mat_list->has_emission.w) { + _emission.w = mat_list->emission.w; + has_emission = true; + } + + if (!has_emission) + _emission = material->material.color.emission; + } + else { + if (blend_color) + _blend_color = *blend_color; + _emission = material->material.color.emission; + } + + data->init_sub_mesh(mat, obj->bounding_sphere.radius, sub_mesh, mesh, material, textures, + num_bone_index, mats, vertex_buffer, vertex_buffer_offset, index_buffer, _blend_color, _emission, + morph_vertex_buffer, morph_vertex_buffer_offset, instances_count, instances_mat, func, func_data); + + const obj_material_attrib_member attrib = material->material.attrib.m; + if (!attrib.flag_28 && (data->args.sub_mesh.blend_color.w < 1.0f + || !attrib.punch_through && attrib.alpha_texture | attrib.alpha_material + || sub_mesh->attrib.m.translucent)) { + if (!attrib.translucent_priority) + if (mesh->attrib.m.translucent_sort_by_radius + || obj_flags & mdl::OBJ_TRANSLUCENT_SORT_BY_RADIUS) { + DispManager::entry_list(OBJ_TYPE_REFLECT_TRANSLUCENT_SORT_BY_RADIUS, data); + } + else + DispManager::entry_list(OBJ_TYPE_REFLECT_TRANSLUCENT, data); + else if (translucent_priority_count < 40) + translucent_priority[translucent_priority_count++] = &data->args.sub_mesh; + } + else { + if (!(obj_flags & mdl::OBJ_NO_TRANSLUCENCY)) + if (attrib.punch_through) + DispManager::entry_list(OBJ_TYPE_REFLECT_TRANSPARENT, data); + else + DispManager::entry_list(OBJ_TYPE_REFLECT_OPAQUE, data); + continue; + } + } + + if (translucent_priority_count <= 0) + continue; + + ObjTranslucentArgs translucent_args; + translucent_args.count = 0; + for (int32_t j = 62; j; j--) + for (int32_t k = 0; k < translucent_priority_count; k++) { + ObjSubMeshArgs* sub_mesh = translucent_priority[k]; + if (sub_mesh->material->material.attrib.m.translucent_priority != j) + continue; + + translucent_args.sub_mesh[translucent_args.count] = sub_mesh; + translucent_args.count++; + } + + ObjData* data = DispManager::alloc_obj_data(mdl::OBJ_KIND_TRANSLUCENT); + if (data) { + data->init_translucent(mat, translucent_args); + DispManager::entry_list(OBJ_TYPE_TRANSLUCENT, data); + } + } + return true; } - void DispManager::entry_obj_by_obj(const mat4* mat, - ::obj* obj, prj::vector* textures, obj_mesh_vertex_buffer* obj_vert_buf, + void DispManager::entry_obj_by_obj(const mat4& mat, + const ::obj* obj, prj::vector* textures, obj_mesh_vertex_buffer* obj_vert_buf, obj_mesh_index_buffer* obj_index_buf, mat4* bone_mat, float_t alpha) { if (!obj) return; - vec4 blend_color = { 1.0f, 1.0f, 1.0f, alpha }; - vec4* blend_color_ptr = alpha < 1.0f ? &blend_color : 0; + const vec4 blend_color(1.0f, 1.0f, 1.0f, alpha); - entry_obj(obj, obj_vert_buf, obj_index_buf, mat, textures, blend_color_ptr, - bone_mat, 0, 0, 0, 0, 0, 0, !!bone_mat); + entry_obj(obj, mat, obj_vert_buf, obj_index_buf, textures, + alpha < 1.0f ? &blend_color : 0, bone_mat, 0, 0, 0, 0, 0, 0, !!bone_mat); } #if SHARED_OBJECT_BUFFER #pragma warning(push) #pragma warning(disable: 6386) - void DispManager::entry_obj_by_obj(const mat4* mat, - ::obj* obj, prj::vector* textures, obj_mesh_vertex_buffer_aft* obj_vert_buf, + void DispManager::entry_obj_by_obj(const mat4& mat, + const ::obj* obj, prj::vector* textures, obj_mesh_vertex_buffer_aft* obj_vert_buf, obj_mesh_index_buffer* obj_index_buf, mat4* bone_mat, float_t alpha) { if (!obj) return; @@ -2709,23 +3049,23 @@ namespace mdl { blend_color.w = alpha; vec4* blend_color_ptr = alpha < 1.0f ? &blend_color : 0; - disp_manager->entry_obj(obj, _obj_vert_buf, obj_index_buf, mat, + entry_obj(obj, mat, _obj_vert_buf, obj_index_buf, textures, blend_color_ptr, bone_mat, 0, 0, 0, 0, 0, 0, 0, !!bone_mat); _operator_delete(_obj_vert_buf); } #pragma warning(pop) #endif - bool DispManager::entry_obj_by_object_info(const mat4* mat, object_info obj_info) { + bool DispManager::entry_obj_by_object_info(const mat4& mat, object_info obj_info) { return entry_obj_by_object_info(mat, obj_info, 0, 0, 0, 0, 0, 0, false); } - bool DispManager::entry_obj_by_object_info(const mat4* mat, object_info obj_info, mat4* bone_mat) { + bool DispManager::entry_obj_by_object_info(const mat4& mat, object_info obj_info, mat4* bone_mat) { vec4 blend_color = 1.0f; return entry_obj_by_object_info(mat, obj_info, &blend_color, bone_mat, 0, 0, 0, 0, true); } - bool DispManager::entry_obj_by_object_info(const mat4* mat, object_info obj_info, + bool DispManager::entry_obj_by_object_info(const mat4& mat, object_info obj_info, vec4* blend_color, mat4* bone_mat, int32_t instances_count, mat4* instances_mat, void(*func)(const ObjSubMeshArgs*), const ObjSubMeshArgs* func_data, bool enable_bone_mat, bool local) { @@ -2737,42 +3077,42 @@ namespace mdl { return false; prj::vector* textures = objset_info_storage_get_set_gentex(obj_info.set_id); - obj_mesh_vertex_buffer* obj_vertex_buffer = objset_info_storage_get_obj_mesh_vertex_buffer(obj_info, 0); + obj_mesh_vertex_buffer* obj_vert_buffer = objset_info_storage_get_obj_mesh_vertex_buffer(obj_info, 0); obj_mesh_index_buffer* obj_index_buffer = objset_info_storage_get_obj_mesh_index_buffer(obj_info, 0); ::obj* obj_morph = 0; - obj_mesh_vertex_buffer* obj_morph_vertex_buffer = 0; + obj_mesh_vertex_buffer* obj_morph_vert_buffer = 0; if (morph.object.set_id != (uint16_t)-1) { obj_morph = objset_info_storage_get_obj(morph.object); - obj_morph_vertex_buffer = objset_info_storage_get_obj_mesh_vertex_buffer(morph.object, 0); + obj_morph_vert_buffer = objset_info_storage_get_obj_mesh_vertex_buffer(morph.object, 0); } - return entry_obj(obj, obj_vertex_buffer, obj_index_buffer, - mat, textures, blend_color, bone_mat, obj_morph, obj_morph_vertex_buffer, + return entry_obj(obj, mat, obj_vert_buffer, obj_index_buffer, + textures, blend_color, bone_mat, obj_morph, obj_morph_vert_buffer, instances_count, instances_mat, func, func_data, enable_bone_mat, local); } - bool DispManager::entry_obj_by_object_info(const mat4* mat, + bool DispManager::entry_obj_by_object_info(const mat4& mat, object_info obj_info, float_t alpha, mat4* bone_mat) { vec4 blend_color = 1.0f; blend_color.w = alpha; return entry_obj_by_object_info(mat, obj_info, &blend_color, bone_mat, 0, 0, 0, 0, true); } - bool DispManager::entry_obj_by_object_info(const mat4* mat, object_info obj_info, + bool DispManager::entry_obj_by_object_info(const mat4& mat, object_info obj_info, float_t r, float_t g, float_t b, float_t a, mat4* bone_mat, bool local) { vec4 blend_color = { r, g, b, a }; return entry_obj_by_object_info(mat, obj_info, &blend_color, bone_mat, 0, 0, 0, 0, true, local); } - bool DispManager::entry_obj_by_object_info(const mat4* mat, object_info obj_info, + bool DispManager::entry_obj_by_object_info(const mat4& mat, object_info obj_info, vec4* blend_color, mat4* bone_mat, bool local) { return entry_obj_by_object_info(mat, obj_info, blend_color, 0, 0, 0, 0, 0, false, local); } void DispManager::entry_obj_by_object_info_object_skin(object_info obj_info, prj::vector* texture_pattern, texture_data_struct* texture_data, float_t alpha, - mat4* matrices, mat4* ex_data_matrices, const mat4* mat, const mat4* global_mat) { + mat4* matrices, mat4* ex_data_matrices, const mat4* mat, const mat4& global_mat) { obj_skin* skin = objset_info_storage_get_obj_skin(obj_info); if (!skin) return; @@ -2833,13 +3173,13 @@ namespace mdl { } } - void DispManager::entry_obj_etc(const mat4* mat, EtcObj* etc, bool local) { + void DispManager::entry_obj_etc(const mat4& mat, const EtcObj& etc, bool local) { ObjData* data = alloc_obj_data(mdl::OBJ_KIND_ETC); if (!data) return; data->init_etc(mat, etc); - if (etc->color.a == 0xFF) { + if (etc.color.a == 0xFF) { if (!local && (obj_flags & OBJ_SHADOW)) entry_list((mdl::ObjType)(OBJ_TYPE_SHADOW_CHARA + shadow_type), data); entry_list(local ? OBJ_TYPE_OPAQUE_LOCAL : OBJ_TYPE_OPAQUE, data); @@ -2848,7 +3188,7 @@ namespace mdl { entry_list(local ? OBJ_TYPE_TRANSLUCENT_LOCAL : OBJ_TYPE_TRANSLUCENT, data); } - void DispManager::entry_obj_user(const mat4* mat, UserArgsFunc func, void* data, ObjType type) { + void DispManager::entry_obj_user(const mat4& mat, UserArgsFunc func, void* data, ObjType type) { ObjData* _data = alloc_obj_data(OBJ_KIND_USER); if (_data) { _data->init_user(mat, func, data); @@ -2992,7 +3332,11 @@ namespace mdl { } mdl::ObjList& DispManager::get_obj_list(mdl::ObjType type) { - if (type >= OBJ_TYPE_MAX) + if (type >= OBJ_TYPE_LOCAL_MAX) +#pragma warning(suppress: 33010) +#pragma warning(suppress: 33011) + return rctx->obj_reflect[type - OBJ_TYPE_LOCAL_MAX]; + else if (type >= OBJ_TYPE_MAX) #pragma warning(suppress: 33010) #pragma warning(suppress: 33011) return rctx->obj_local[type - OBJ_TYPE_MAX]; @@ -3121,6 +3465,9 @@ namespace mdl { for (prj::list& i : rctx->obj_local) i.clear(); + for (prj::list& i : rctx->obj_reflect) + i.clear(); + buffer_reset(); } @@ -3128,7 +3475,7 @@ namespace mdl { chara_color = value; } - void DispManager::set_culling_finc(bool(FASTCALL* func)(obj_bounding_sphere*)) { + void DispManager::set_culling_func(bool(FASTCALL* func)(const obj_bounding_sphere*)) { culling_func = func; } @@ -3224,7 +3571,7 @@ namespace mdl { vec3 pos = 0.0f; sub_1405E8A20(shadow_ptr_get(), 0, &pos); disp_manager->set_shadow_type(SHADOW_CHARA); - disp_manager->entry_obj_by_object_info(&mat, object_info((uint16_t)id, (uint16_t)set_id)); + disp_manager->entry_obj_by_object_info(mat, object_info((uint16_t)id, (uint16_t)set_id)); disp_manager->set_obj_flags((mdl::ObjFlags)0); } @@ -3237,7 +3584,7 @@ namespace mdl { mat4 mat; mat4_translate(&aabb->center, &mat); mat4_transpose(&mat, &mat); - disp_manager->entry_obj_etc(&mat, &etc); + disp_manager->entry_obj_etc(mat, etc); } HOOK(void, FASTCALL, MeshDw__DrawObjBoundingSphere, 0x000000014031AFE0, obj_bounding_sphere* bounding_sphere, color4u8_bgra color) { @@ -3252,7 +3599,7 @@ namespace mdl { mat4 mat; mat4_translate(&bounding_sphere->center, &mat); mat4_transpose(&mat, &mat); - disp_manager->entry_obj_etc(&mat, &etc); + disp_manager->entry_obj_etc(mat, etc); } HOOK(void, FASTCALL, DispManager__entry_obj, 0x00000001404379E0, @@ -3264,20 +3611,20 @@ namespace mdl { abort(); } - HOOK(void, FASTCALL, DispManager__entry_obj_etc, 0x00000001404395C0, mdl::EtcObj* etc) { - disp_manager->entry_obj_etc(&mat4_identity, etc); + HOOK(void, FASTCALL, DispManager__entry_obj_etc, 0x00000001404395C0, const mdl::EtcObj& etc) { + disp_manager->entry_obj_etc(mat4_identity, etc); } #if SHARED_OBJECT_BUFFER HOOK(void, FASTCALL, DispManager__entry_obj_by_obj, 0x0000000140439A20, obj* obj_data, prj::vector* textures, obj_mesh_vertex_buffer_aft* obj_vert_buf, obj_mesh_index_buffer* obj_index_buf, mat4* bone_mat, float_t alpha) { - disp_manager->entry_obj_by_obj(rob_chara_item_equip_mat, obj_data, textures, obj_vert_buf, obj_index_buf, bone_mat, alpha); + disp_manager->entry_obj_by_obj(*rob_chara_item_equip_mat, obj_data, textures, obj_vert_buf, obj_index_buf, bone_mat, alpha); } #else HOOK(void, FASTCALL, DispManager__entry_obj_by_obj, 0x0000000140439A20, obj* obj_data, prj::vector* textures, obj_mesh_vertex_buffer* obj_vert_buf, obj_mesh_index_buffer* obj_index_buf, mat4* bone_mat, float_t alpha) { - disp_manager->entry_obj_by_obj(rob_chara_item_equip_mat, obj_data, textures, obj_vert_buf, obj_index_buf, bone_mat, alpha); + disp_manager->entry_obj_by_obj(*rob_chara_item_equip_mat, obj_data, textures, obj_vert_buf, obj_index_buf, bone_mat, alpha); } #endif @@ -3294,7 +3641,7 @@ namespace mdl { mat4 mat; mat4_translate(pos, &mat); mat4_transpose(&mat, &mat); - disp_manager->entry_obj_etc(&mat, &etc); + disp_manager->entry_obj_etc(mat, etc); } void disp_manager_patch() { diff --git a/src/DivaGL/mdl/disp_manager.hpp b/src/DivaGL/mdl/disp_manager.hpp index d8c3e78..9f7acfb 100644 --- a/src/DivaGL/mdl/disp_manager.hpp +++ b/src/DivaGL/mdl/disp_manager.hpp @@ -115,6 +115,8 @@ namespace mdl { OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_2_LOCAL, OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2_LOCAL, OBJ_TYPE_LOCAL_MAX, + OBJ_TYPE_REFLECT_TRANSLUCENT_SORT_BY_RADIUS = OBJ_TYPE_LOCAL_MAX, + OBJ_TYPE_REFLECT_MAX, }; } @@ -168,6 +170,10 @@ struct texture_data_struct { static_assert(sizeof(texture_data_struct) == 0x34, "\"texture_pattern_struct\" struct should have a size of 0x34"); namespace mdl { + struct ObjSubMeshArgs; + + typedef void(FASTCALL* draw_func)(const ObjSubMeshArgs* args); + struct ObjSubMeshArgs { const obj_sub_mesh* sub_mesh; const obj_mesh* mesh; @@ -199,7 +205,7 @@ namespace mdl { int32_t field_7C8; int32_t instances_count; const mat4* instances_mat; - void(FASTCALL* func)(const ObjSubMeshArgs*); + draw_func func; const ObjSubMeshArgs* func_data; ObjSubMeshArgs(); @@ -349,16 +355,15 @@ namespace mdl { ObjData(); ~ObjData(); - void init_etc(const mat4* mat, mdl::EtcObj* etc); - void init_sub_mesh(const mat4* mat, float_t radius, - const obj_sub_mesh* sub_mesh, const obj_mesh* mesh, const obj_material_data* material, - const prj::vector* textures, int32_t mat_count, const mat4* mats, - GLuint vertex_buffer, size_t vertex_buffer_offset, GLuint index_buffer, - const vec4& blend_color, const vec4& emission, GLuint morph_vertex_buffer, - size_t morph_vertex_buffer_offset, int32_t instances_count, mat4* instances_mat, - void(FASTCALL* func)(const ObjSubMeshArgs*), const ObjSubMeshArgs* func_data); - void init_translucent(const mat4* mat, ObjTranslucentArgs* translucent); - void init_user(const mat4* mat, UserArgsFunc func, void* data); + void init_etc(const mat4& mat, const mdl::EtcObj& etc); + void init_sub_mesh(const mat4& mat, float_t radius, const obj_sub_mesh* sub_mesh, + const obj_mesh* mesh, const obj_material_data* material, const prj::vector* textures, + int32_t mat_count, const mat4* mats, GLuint vertex_buffer, size_t vertex_buffer_offset, + GLuint index_buffer, const vec4& blend_color, const vec4& emission, GLuint morph_vertex_buffer, + size_t morph_vertex_buffer_offset, + int32_t instances_count, const mat4* instances_mat, draw_func func, const ObjSubMeshArgs* func_data); + void init_translucent(const mat4& mat, const ObjTranslucentArgs& translucent); + void init_user(const mat4& mat, UserArgsFunc func, void* data); }; typedef prj::list ObjList; @@ -367,7 +372,7 @@ namespace mdl { struct Info { int32_t objects; int32_t meshes; - int32_t submesh_array; + int32_t sub_meshes; int pad; }; @@ -439,7 +444,7 @@ namespace mdl { float_t wet_param; int32_t texture_transform_count; texture_transform_struct texture_transform_array[TEXTURE_TRANSFORM_COUNT]; - bool(FASTCALL* culling_func)(obj_bounding_sphere*); + bool(FASTCALL* culling_func)(const obj_bounding_sphere*); void add_vertex_array(ObjSubMeshArgs* args); void add_vertex_array(EtcObj* etc, mat4& mat); @@ -454,35 +459,34 @@ namespace mdl { void draw(mdl::ObjType type, int32_t depth_mask = 0, bool reflect_texture_mask = true, int32_t alpha = -1); /*void draw_show_vector(mdl::ObjType type, int32_t show_vector);*/ void entry_list(ObjType type, ObjData* data); - bool entry_obj(::obj* object, obj_mesh_vertex_buffer* obj_vertex_buf, - obj_mesh_index_buffer* obj_index_buf, const mat4* mat, - prj::vector* textures, vec4* blend_color, mat4* bone_mat, ::obj* object_morph, - obj_mesh_vertex_buffer* obj_morph_vertex_buf, int32_t instances_count, mat4* instances_mat, - void(*func)(const mdl::ObjSubMeshArgs*), const ObjSubMeshArgs* func_data, - bool enable_bone_mat, bool local = false); - void entry_obj_by_obj(const mat4* mat, - ::obj* obj, prj::vector* textures, obj_mesh_vertex_buffer* obj_vert_buf, + bool entry_obj(const ::obj* obj, const mat4& mat, obj_mesh_vertex_buffer* obj_vert_buf, + obj_mesh_index_buffer* obj_index_buf, const prj::vector* textures, const vec4* blend_color, + const mat4* bone_mat, const ::obj* obj_morph, obj_mesh_vertex_buffer* obj_morph_vert_buf, + int32_t instances_count, const mat4* instances_mat, + draw_func func, const ObjSubMeshArgs* func_data, bool enable_bone_mat, bool local = false); + void entry_obj_by_obj(const mat4& mat, + const ::obj* obj, prj::vector* textures, obj_mesh_vertex_buffer* obj_vert_buf, obj_mesh_index_buffer* obj_index_buf, mat4* bone_mat, float_t alpha); #if SHARED_OBJECT_BUFFER - void entry_obj_by_obj(const mat4* mat, - ::obj* obj, prj::vector* textures, obj_mesh_vertex_buffer_aft* obj_vert_buf, + void entry_obj_by_obj(const mat4& mat, + const ::obj* obj, prj::vector* textures, obj_mesh_vertex_buffer_aft* obj_vert_buf, obj_mesh_index_buffer* obj_index_buf, mat4* bone_mat, float_t alpha); #endif - bool entry_obj_by_object_info(const mat4* mat, object_info obj_info); - bool entry_obj_by_object_info(const mat4* mat, object_info obj_info, mat4* bone_mat); - bool entry_obj_by_object_info(const mat4* mat, object_info obj_info, + bool entry_obj_by_object_info(const mat4& mat, object_info obj_info); + bool entry_obj_by_object_info(const mat4& mat, object_info obj_info, mat4* bone_mat); + bool entry_obj_by_object_info(const mat4& mat, object_info obj_info, vec4* blend_color, mat4* bone_mat, int32_t instances_count, mat4* instances_mat, void(*func)(const ObjSubMeshArgs*), const ObjSubMeshArgs* func_data, bool enable_bone_mat, bool local = false); - bool entry_obj_by_object_info(const mat4* mat, object_info obj_info, float_t alpha, mat4* bone_mat = 0); - bool entry_obj_by_object_info(const mat4* mat, object_info obj_info, + bool entry_obj_by_object_info(const mat4& mat, object_info obj_info, float_t alpha, mat4* bone_mat = 0); + bool entry_obj_by_object_info(const mat4& mat, object_info obj_info, float_t r, float_t g, float_t b, float_t a, mat4* bone_mat = 0, bool local = false); - bool entry_obj_by_object_info(const mat4* mat, object_info obj_info, + bool entry_obj_by_object_info(const mat4& mat, object_info obj_info, vec4* blend_color, mat4* bone_mat = 0, bool local = false); void entry_obj_by_object_info_object_skin(object_info obj_info, prj::vector* texture_pattern, texture_data_struct* texture_data, float_t alpha, - mat4* matrices, mat4* ex_data_matrices, const mat4* mat, const mat4* global_mat); - void entry_obj_etc(const mat4* mat, EtcObj* etc, bool local = false); - void entry_obj_user(const mat4* mat, UserArgsFunc func, void* data, ObjType type); + mat4* matrices, mat4* ex_data_matrices, const mat4* mat, const mat4& global_mat); + void entry_obj_etc(const mat4& mat, const EtcObj& etc, bool local = false); + void entry_obj_user(const mat4& mat, UserArgsFunc func, void* data, ObjType type); GLuint get_vertex_array(const ObjSubMeshArgs* args); GLuint get_vertex_array(const mdl::EtcObj* etc); bool get_chara_color(); @@ -502,7 +506,7 @@ namespace mdl { void obj_sort(mat4* view, ObjType type, int32_t compare_func, bool a3 = false); void refresh(); void set_chara_color(bool value = false); - void set_culling_finc(bool(FASTCALL* func)(obj_bounding_sphere*) = 0); + void set_culling_func(bool(FASTCALL* func)(const obj_bounding_sphere*) = 0); void set_obj_flags(ObjFlags flags = (ObjFlags)0); void set_material_list(int32_t count = 0, const material_list_struct* value = 0); void set_morph(object_info object = {}, float_t weight = 0.0f); @@ -518,6 +522,8 @@ namespace mdl { static_assert(sizeof(mdl::DispManager) == 0x9D0, "\"mdl::DispManager\" struct should have a size of 0x9D0"); + extern bool obj_reflect_enable; + extern void disp_manager_patch(); } diff --git a/src/DivaGL/mdl/draw_object.cpp b/src/DivaGL/mdl/draw_object.cpp index 5159ae2..03c8656 100644 --- a/src/DivaGL/mdl/draw_object.cpp +++ b/src/DivaGL/mdl/draw_object.cpp @@ -295,7 +295,7 @@ namespace mdl { obj_material_attrib_member attrib = args->material->material.attrib.m; uniform->arr[U_ALPHA_TEST] = (!attrib.flag_28 && (args->blend_color.w < 1.0f || (attrib.alpha_texture || attrib.alpha_material) && !attrib.punch_through - || args->sub_mesh->attrib.m.transparent) + || args->sub_mesh->attrib.m.translucent) || attrib.punch_through) ? 1 : 0; uniform->arr[U_NPR_NORMAL] = 1; @@ -303,12 +303,12 @@ namespace mdl { const obj_material_data* material = args->material; switch (material->material.shader.index) { case SHADER_FT_CLOTH: - if (!render_manager->npr_param && material->material.color.ambient.w < 1.0f + if (!render_manager.npr_param && material->material.color.ambient.w < 1.0f && material->material.shader_info.m.aniso_direction == OBJ_MATERIAL_ANISO_DIRECTION_NORMAL) chara = true; break; case SHADER_FT_TIGHTS: - if (!render_manager->npr_param) + if (!render_manager.npr_param) chara = true; break; case SHADER_FT_GLASEYE: @@ -382,7 +382,7 @@ namespace mdl { obj_material_attrib_member attrib = args->material->material.attrib.m; if (!attrib.flag_28 && (args->blend_color.w < 1.0f || (attrib.alpha_texture || attrib.alpha_material) && !attrib.punch_through - || args->sub_mesh->attrib.m.transparent) + || args->sub_mesh->attrib.m.translucent) || attrib.punch_through) { uniform->arr[U_ALPHA_TEST] = 1; rctx->set_batch_alpha_threshold(0.5f); diff --git a/src/DivaGL/object.cpp b/src/DivaGL/object.cpp index 0be64e7..87f68bf 100644 --- a/src/DivaGL/object.cpp +++ b/src/DivaGL/object.cpp @@ -4,7 +4,9 @@ */ #include "object.hpp" +#include "../KKdLib/hash.hpp" #include "mdl/disp_manager.hpp" +#include "pv_game/firstread.hpp" #include "file_handler.hpp" #include "gl_state.hpp" #include "wrap.hpp" @@ -88,6 +90,8 @@ bool (FASTCALL* objset_info_storage_load_obj_set_check_not_read)(int32_t set) static BufObjMgr& bufobj_mgr = *(BufObjMgr*)0x00000001411A34D0; +static int32_t load_set_id; + static GLuint create_index_buffer(size_t size, const void* data); static GLuint create_vertex_buffer(size_t size, const void* data, bool dynamic = false); static void free_index_buffer(GLuint buffer); @@ -939,7 +943,7 @@ inline int32_t obj_material_texture_type_get_texture_index( } void obj_skin_set_matrix_buffer(obj_skin* s, mat4* matrices, - mat4* ex_data_matrices, mat4* matrix_buffer, const mat4* mat, const mat4* global_mat) { + mat4* ex_data_matrices, mat4* matrix_buffer, const mat4* mat, const mat4& global_mat) { if (!s->num_bone) return; @@ -953,7 +957,7 @@ void obj_skin_set_matrix_buffer(obj_skin* s, mat4* matrices, else mat4_mul(&matrices[*bone_id], mat, &temp); - mat4_mul(global_mat, &temp, &temp); + mat4_mul(&global_mat, &temp, &temp); mat4_mul(&temp, bone_matrix, matrix_buffer); } else @@ -964,7 +968,7 @@ void obj_skin_set_matrix_buffer(obj_skin* s, mat4* matrices, else temp = matrices[*bone_id]; - mat4_mul(global_mat, &temp, &temp); + mat4_mul(&global_mat, &temp, &temp); mat4_mul(&temp, bone_matrix, matrix_buffer); } } @@ -1041,6 +1045,172 @@ HOOK(obj_mesh_vertex_buffer*, FASTCALL, objset_info_storage_get_obj_mesh_vertex_ return 0; } +HOOK(obj_set*, FASTCALL, obj_set_parse_file, 0x000000014045CBC0, + prj::shared_ptr& alloc, __int64 set_file, int32_t& result) { + obj_set* set = originalobj_set_parse_file(alloc, set_file, result); + + extern bool reflect_full; + extern const firstread* firstread_ptr; + if (reflect_full && firstread_ptr && firstread_ptr->objset_array && load_set_id != -1) { + const firstread_objset_array* objset_array = firstread_ptr->objset_array; + if (objset_array->objset_id_array && objset_array->objset_array) { + const uint32_t num_objset = objset_array->num_objset; + for (uint32_t i = 0; i < num_objset; i++) { + if (objset_array->objset_id_array[i] != load_set_id || !objset_array->objset_array[i].data) + continue; + + const firstread_objset* frb_set = firstread_objset::read(alloc, + objset_array->objset_array[i].data, objset_array->objset_array[i].size); + if (!frb_set || !set->obj_data || !frb_set->obj_data) + break; + + const int32_t frb_obj_num = frb_set->obj_num; + for (int32_t j = 0; j < frb_obj_num; j++) { + const int32_t obj_num = set->obj_num; + for (int32_t k = 0; k < obj_num; k++) { + if (frb_set->obj_data[j].id != set->obj_id_data[k]) + continue; + + obj* obj = set->obj_data[k]; + const firstread_obj* frb_obj = &frb_set->obj_data[j]; + if (obj->mesh_array && frb_obj->mesh_array) { + const int32_t frb_num_mesh = frb_obj->num_mesh; + int32_t index_match = -1; + for (int32_t l = 0; l < frb_num_mesh; l++) { + const uint64_t name_hash = hash_utf8_xxh3_64bits(frb_obj->mesh_array[l].name); + const int32_t num_mesh = obj->num_mesh; + for (int32_t m = 0; m < num_mesh; m++) { + if (name_hash != hash_utf8_xxh3_64bits(obj->mesh_array[m].name)) + continue; + else if (frb_obj->mesh_array[l].index != (uint8_t)-1) { + if (++index_match != frb_obj->mesh_array[l].index) + continue; + } + + obj_mesh* mesh = &obj->mesh_array[m]; + const firstread_obj_mesh* frb_mesh = &frb_obj->mesh_array[l]; + if (frb_mesh->remove) { + mesh->flags = 0; + mesh->bounding_sphere = {}; + mesh->num_submesh = 0; + mesh->submesh_array = 0; + mesh->vertex_format = (obj_vertex_format)0; + mesh->size_vertex = 0; + mesh->num_vertex = 0; + for (int32_t n = 0; n < 20; n++) + mesh->vertex_array_ptr[n] = 0; + mesh->attrib = {}; + mesh->vertex_flags = 0; + break; + } + + if (mesh->submesh_array && mesh->num_submesh) { + const int32_t num_submesh = mesh->num_submesh; + for (int32_t n = 0; n < num_submesh; n++) { + obj_sub_mesh* submesh = &mesh->submesh_array[n]; + submesh->attrib.m.no_reflect = frb_mesh->attrib.m.no_reflect; + submesh->attrib.m.reflect = frb_mesh->attrib.m.reflect; + submesh->attrib.m.reflect_cam_back = frb_mesh->attrib.m.reflect_cam_back; + } + } + + if (mesh->submesh_array && frb_mesh->submesh_array + && mesh->num_submesh && mesh->num_submesh == frb_mesh->num_submesh) { + const int32_t num_submesh = mesh->num_submesh; + int32_t num_submesh_split = num_submesh; + for (int32_t n = 0; n < num_submesh; n++) { + const firstread_obj_sub_mesh* frb_submesh = &frb_mesh->submesh_array[n]; + if (frb_submesh->split) + num_submesh_split++; + } + + if (num_submesh < num_submesh_split) { + obj_sub_mesh* submesh_array = mesh->submesh_array; + mesh->num_submesh = num_submesh_split; + mesh->submesh_array = alloc->allocate(num_submesh_split); + for (int32_t n = 0, o = 0; n < num_submesh; n++, o++) { + const firstread_obj_sub_mesh* frb_submesh = &frb_mesh->submesh_array[n]; + mesh->submesh_array[o] = submesh_array[n]; + if (frb_submesh->split) + mesh->submesh_array[++o] = submesh_array[n]; + } + } + + for (int32_t n = 0, o = 0; n < num_submesh; n++, o++) { + obj_sub_mesh* submesh = &mesh->submesh_array[o]; + const firstread_obj_sub_mesh* frb_submesh = &frb_mesh->submesh_array[n]; + + if (frb_submesh->split) { + firstread_obj_sub_mesh_split* split = frb_submesh->split; + if (split->material_index[0] != -1) + submesh->material_index = split->material_index[0]; + if (split->num_index[0] && split->index_array[0]) { + submesh->bounding_sphere = split->bounding_sphere[0]; + submesh->index_format = split->index_format; + submesh->num_index = split->num_index[0]; + submesh->index_array = (void*)split->index_array[0]; + } + submesh->attrib = split->attrib[0]; + + obj_sub_mesh* submesh_before = &mesh->submesh_array[++o]; + if (split->material_index[1] != -1) + submesh_before->material_index = split->material_index[1]; + if (split->num_index[1] && split->index_array[1]) { + submesh_before->bounding_sphere = split->bounding_sphere[1]; + submesh_before->index_format = split->index_format; + submesh_before->num_index = split->num_index[1]; + submesh_before->index_array = (void*)split->index_array[1]; + } + submesh_before->attrib = split->attrib[1]; + continue; + } + else if (frb_submesh->num_index && frb_submesh->index_array) { + submesh->bounding_sphere = frb_submesh->bounding_sphere; + submesh->index_format = frb_submesh->index_format; + submesh->num_index = frb_submesh->num_index; + submesh->index_array = (void*)frb_submesh->index_array; + } + + submesh->attrib = frb_submesh->attrib; + } + } + + if (frb_mesh->vertex_format && frb_mesh->num_vertex) { + mesh->vertex_format = frb_mesh->vertex_format; + mesh->size_vertex = frb_mesh->size_vertex; + mesh->num_vertex = frb_mesh->num_vertex; + for (int32_t n = 0; n < 20; n++) + mesh->vertex_array_ptr[n] = frb_mesh->vertex_array_ptr[n]; + } + + mesh->attrib = frb_mesh->attrib; + break; + } + } + } + + if (frb_obj->num_material && frb_obj->material_array) { + obj->num_material = frb_obj->num_material; + obj->material_array = (obj_material_data*)frb_obj->material_array; + } + break; + } + } + break; + } + } + } + + return set; +} + +HOOK(bool, FASTCALL, _objset_info_storage_load_obj_set_check_not_read, 0x000000014045DA60, int32_t set) { + load_set_id = set; + bool ret = original_objset_info_storage_load_obj_set_check_not_read(set); + load_set_id = -1; + return ret; +} + HOOK(void, FASTCALL, obj_mesh_vertex_buffer__unload, 0x0000000140461870, obj_mesh_vertex_buffer* objvb) { objvb->unload(); } @@ -1057,6 +1227,8 @@ void object_patch() { INSTALL_HOOK(ObjsetInfo__vertex_buffer_free); INSTALL_HOOK(objset_info_storage_get_obj_mesh_index_buffer); INSTALL_HOOK(objset_info_storage_get_obj_mesh_vertex_buffer); + INSTALL_HOOK(obj_set_parse_file); + INSTALL_HOOK(_objset_info_storage_load_obj_set_check_not_read); INSTALL_HOOK(obj_mesh_vertex_buffer__unload); } diff --git a/src/DivaGL/object.hpp b/src/DivaGL/object.hpp index 82f7695..c987651 100644 --- a/src/DivaGL/object.hpp +++ b/src/DivaGL/object.hpp @@ -288,9 +288,12 @@ struct obj_material_data { struct obj_sub_mesh_attrib_member { uint32_t recieve_shadow : 1; uint32_t cast_shadow : 1; - uint32_t transparent : 1; + uint32_t translucent : 1; uint32_t cloth : 1; - uint32_t dummy : 28; + uint32_t no_reflect : 1; // Own stuff + uint32_t reflect : 1; // Own stuff + uint32_t reflect_cam_back : 1; // Own stuff + uint32_t dummy : 25; // 28 }; union obj_sub_mesh_attrib { @@ -309,7 +312,7 @@ struct obj_sub_mesh { obj_primitive_type primitive_type; obj_index_format index_format; int32_t num_index; - uint16_t* index_array; + void* index_array; obj_sub_mesh_attrib attrib; uint32_t reserved[4]; obj_axis_aligned_bounding_box* axis_aligned_bounding_box; @@ -325,7 +328,11 @@ struct obj_mesh_attrib_member { uint32_t billboard_y_axis : 1; uint32_t translucent_sort_by_radius : 1; uint32_t billboard : 1; - uint32_t dummy : 26; // 28 + uint32_t no_reflect : 1; // Own stuff + uint32_t reflect : 1; // Own stuff + uint32_t reflect_cam_back : 1; // Own stuff + uint32_t disable_aabb_culling : 1; // Own stuff + uint32_t dummy : 22; // 28 uint32_t compression : 2; // Own stuff }; @@ -611,6 +618,6 @@ extern int32_t obj_material_texture_type_get_texture_index( obj_material_texture_type type, int32_t base_index); extern void obj_skin_set_matrix_buffer(obj_skin* s, mat4* matrices, - mat4* ex_data_matrices, mat4* matrix_buffer, const mat4* mat, const mat4* global_mat); + mat4* ex_data_matrices, mat4* matrix_buffer, const mat4* mat, const mat4& global_mat); extern void object_patch(); diff --git a/src/DivaGL/print_work.cpp b/src/DivaGL/print_work.cpp index d947b9e..fc281d1 100644 --- a/src/DivaGL/print_work.cpp +++ b/src/DivaGL/print_work.cpp @@ -169,7 +169,7 @@ void PrintWork::DrawTextMesh(app::text_flags flags, sprite_text_mesh& mesh) { } args.SetVertexArray(mesh.vertices.data(), mesh.vertices.size()); args.id.index = mesh.sprite_id; - spr::put_sprite(&args); + spr::put_sprite(args); for (spr::SpriteVertex& i : mesh.vertices) { i.color.r = color.r; @@ -184,7 +184,7 @@ void PrintWork::DrawTextMesh(app::text_flags flags, sprite_text_mesh& mesh) { if (flags & app::TEXT_FLAG_FONT) args.shader = SHADER_FT_FONT; args.id.index = mesh.sprite_id; - spr::put_sprite(&args); + spr::put_sprite(args); } void PrintWork::FillRectangle(rectangle rect) { diff --git a/src/DivaGL/pv_game/firstread.cpp b/src/DivaGL/pv_game/firstread.cpp new file mode 100644 index 0000000..4b48d45 --- /dev/null +++ b/src/DivaGL/pv_game/firstread.cpp @@ -0,0 +1,313 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "../../KKdLib/f2/header.hpp" +#include "../../KKdLib/aes.hpp" +#include "../../KKdLib/deflate.hpp" +#include "firstread.hpp" + +enum { + FIRSTREAD_STR_ARRAY = 0, + FIRSTREAD_AUTH_3D, + FIRSTREAD_OBJSET, + FIRSTREAD_STAGE_DATA, + FIRSTREAD_MAX, +}; + +const firstread_str_array* firstread_str_array::read(const void* data, size_t size) { + if (!data || !size) + return 0; + + size_t d = (size_t)data; + firstread_str_array* str_array = (firstread_str_array*)data; + if (str_array->signature != reverse_endianness_uint32_t('strx')) + return 0; + + if (str_array->lang_array) { + str_array->lang_array = (firstread_str_array_lang*)(d + (size_t)str_array->lang_array); + + const uint32_t num_lang = str_array->num_lang; + for (uint32_t i = 0; i < num_lang; i++) { + firstread_str_array_lang* lang = (firstread_str_array_lang*)&str_array->lang_array[i]; + + if (lang->string_array) { + lang->string_array = (firstread_str_array_string*)(d + (size_t)lang->string_array); + + const uint32_t num_string = lang->num_string; + for (uint32_t j = 0; j < num_string; j++) { + firstread_str_array_string* string = (firstread_str_array_string*)&lang->string_array[j]; + + if (string->str) + string->str = (const char*)(d + (size_t)string->str); + } + } + } + } + return str_array; +} + +const firstread_auth_3d_array* firstread_auth_3d_array::read(const void* data, size_t size) { + if (!data || !size) + return 0; + + size_t d = (size_t)data; + firstread_auth_3d_array* auth_3d_array = (firstread_auth_3d_array*)data; + if (auth_3d_array->signature != reverse_endianness_uint32_t('a3dx')) + return 0; + + if (auth_3d_array->auth_3d_array) { + auth_3d_array->auth_3d_array = (firstread_auth_3d*)(d + (size_t)auth_3d_array->auth_3d_array); + + const uint32_t num_auth_3d = auth_3d_array->num_auth_3d; + for (uint32_t i = 0; i < num_auth_3d; i++) { + firstread_auth_3d* a3d = (firstread_auth_3d*)&auth_3d_array->auth_3d_array[i]; + + if (a3d->object_array) { + a3d->object_array = (firstread_auth_3d_object*)(d + (size_t)a3d->object_array); + + const uint32_t num_object = a3d->num_object; + for (uint32_t j = 0; j < num_object; j++) { + firstread_auth_3d_object* obj = (firstread_auth_3d_object*)&a3d->object_array[j]; + + if (obj->name) + obj->name = (const char*)(d + (size_t)obj->name); + + if (obj->uid_name) + obj->uid_name = (const char*)(d + (size_t)obj->uid_name); + } + } + + if (a3d->object_list_array) { + a3d->object_list_array = (firstread_auth_3d_object_list*)(d + (size_t)a3d->object_list_array); + + const uint32_t num_object_list = a3d->num_object_list; + for (uint32_t j = 0; j < num_object_list; j++) { + firstread_auth_3d_object_list* obj_list = (firstread_auth_3d_object_list*)&a3d->object_list_array[j]; + + if (obj_list->name) + obj_list->name = (const char*)(d + (size_t)obj_list->name); + } + } + } + } + return auth_3d_array; +} + +const firstread_objset* firstread_objset::read( + prj::shared_ptr& alloc, const void* data, size_t size) { + if (!data || !size) + return 0; + + f2_header* head = (f2_header*)alloc->allocate(size); + if (!head) + return 0; + + memcpy(head, data, size); + + bool reset_flags = head->attrib.get_gzip() || head->attrib.get_xor_data(); + + if (head->attrib.get_crc()) { + if (!head->validate_crc()) + return 0; + + if (reset_flags) + head->reset_crc(); + } + + if (head->attrib.get_xor_data()) + head->remove_xor(); + + const deflate::allocator allocator = { + (void*)&alloc, + [](void* data, size_t size) { + return (*(prj::shared_ptr*)data)->allocate(size); + }, + [](void* data, void* ptr) { + + } + }; + + if (head->attrib.get_aes()) { + uint8_t* section_data = head->get_section_data(); + uint32_t section_size = head->get_section_size(); + if (section_data) { + static const uint32_t key_iv_size = 0x30; + if (section_size < key_iv_size) + return 0; + + section_size -= key_iv_size; + + if (section_size == align_val(section_size, 0x20)) { + const uint32_t data_size = head->get_data_size(); + uint8_t* key = section_data + data_size - key_iv_size; + uint8_t* iv = section_data + data_size + 0x20 - key_iv_size; + + aes256_ctx aes; + aes256_init_ctx_iv(&aes, key, iv); + aes256_cbc_decrypt_buffer(&aes, section_data, section_size); + head->attrib.set_aes(false); + } + } + } + + void* dec = 0; + if (head->attrib.get_gzip()) { + uint8_t* section_data = head->get_section_data(); + uint32_t section_size = head->get_section_size(); + if (!head->custom || !section_data || !section_size) + return 0; + + dec = 0; + size_t dec_len = head->custom; + if (deflate::decompress(section_data, section_size, dec, dec_len, deflate::MODE_GZIP, allocator) < 0 + || !dec_len || dec_len < head->custom) + return 0; + + if (reset_flags) + head->attrib.set_gzip(false); + } + else { + dec = alloc->allocate(head->custom); + if (dec) { + memset(dec, 0, head->custom); + memcpy(dec, head->get_section_data(), min_def(head->custom, head->get_section_size())); + } + } + + if (!dec) + return 0; + + size_t d = (size_t)dec; + firstread_objset* objset = (firstread_objset*)dec; + if (objset->signature != reverse_endianness_uint32_t('objx')) + return 0; + + if (objset->obj_data) { + objset->obj_data = (firstread_obj*)(d + (size_t)objset->obj_data); + + const uint32_t obj_num = objset->obj_num; + for (uint32_t i = 0; i < obj_num; i++) { + firstread_obj* obj = (firstread_obj*)&objset->obj_data[i]; + + if (obj->mesh_array) { + obj->mesh_array = (firstread_obj_mesh*)(d + (size_t)obj->mesh_array); + + const uint32_t num_mesh = obj->num_mesh; + for (uint32_t j = 0; j < num_mesh; j++) { + firstread_obj_mesh* mesh = (firstread_obj_mesh*)&obj->mesh_array[j]; + + if (mesh->submesh_array) { + mesh->submesh_array = (firstread_obj_sub_mesh*)(d + (size_t)mesh->submesh_array); + + const uint32_t num_submesh = mesh->num_submesh; + for (uint32_t j = 0; j < num_submesh; j++) { + firstread_obj_sub_mesh* sub_mesh = (firstread_obj_sub_mesh*)&mesh->submesh_array[j]; + + if (sub_mesh->index_array) + sub_mesh->index_array = (void*)(d + (size_t)sub_mesh->index_array); + + if (sub_mesh->split) { + sub_mesh->split = (firstread_obj_sub_mesh_split*)(d + (size_t)sub_mesh->split); + + firstread_obj_sub_mesh_split* split = sub_mesh->split; + if (split->index_array[0]) + split->index_array[0] = (void*)(d + (size_t)split->index_array[0]); + if (split->index_array[1]) + split->index_array[1] = (void*)(d + (size_t)split->index_array[1]); + } + } + } + + for (void*& k : mesh->vertex_array_ptr) + if (k) + k = (void*)(d + (size_t)k); + } + } + + if (obj->material_array) + obj->material_array = (obj_material_data*)(d + (size_t)obj->material_array); + } + } + return objset; +} + +const firstread_objset_array* firstread_objset_array::read(const void* data, size_t size) { + if (!data || !size) + return 0; + + size_t d = (size_t)data; + firstread_objset_array* objset_array = (firstread_objset_array*)data; + if (objset_array->signature != reverse_endianness_uint32_t('osdx')) + return 0; + + if (objset_array->objset_id_array) + objset_array->objset_id_array = (int32_t*)(d + (size_t)objset_array->objset_id_array); + + if (objset_array->objset_array) { + objset_array->objset_array = (firstread_objset_data*)(d + (size_t)objset_array->objset_array); + + const uint32_t num_objset = objset_array->num_objset; + for (uint32_t i = 0; i < num_objset; i++) { + firstread_objset_data* objset = (firstread_objset_data*)&objset_array->objset_array[i]; + + if (objset->data) + objset->data = (void*)(d + (size_t)objset->data); + } + } + return objset_array; +} + +const firstread_stage_data_array* firstread_stage_data_array::read(const void* data, size_t size) { + if (!data || !size) + return 0; + + size_t d = (size_t)data; + firstread_stage_data_array* stage_data_array = (firstread_stage_data_array*)data; + if (stage_data_array->signature != reverse_endianness_uint32_t('stgx')) + return 0; + + if (stage_data_array->stage_data_array) { + stage_data_array->stage_data_array = (firstread_stage_data*)(d + (size_t)stage_data_array->stage_data_array); + + const uint32_t num_stage_data = stage_data_array->num_stage_data; + for (uint32_t i = 0; i < num_stage_data; i++) { + firstread_stage_data* stage_data = (firstread_stage_data*)&stage_data_array->stage_data_array[i]; + + if (stage_data->name) + stage_data->name = (const char*)(d + (size_t)stage_data->name); + + if (stage_data->reflect) + stage_data->reflect = (stage_data_reflect*)(d + (size_t)stage_data->reflect); + } + } + return stage_data_array; +} + +const firstread* firstread::read(const void* data, size_t size) { + if (!data || !size) + return 0; + + size_t d = (size_t)data; + firstread* fr = (firstread*)data; + if (fr->signature != reverse_endianness_uint32_t('frbx')) + return 0; + + if (fr->str_array) + fr->str_array = firstread_str_array::read( + (void*)(d + (size_t)fr->str_array), fr->str_array_size); + + if (fr->auth_3d_array) + fr->auth_3d_array = firstread_auth_3d_array::read( + (void*)(d + (size_t)fr->auth_3d_array), fr->auth_3d_array_size); + + if (fr->objset_array) + fr->objset_array = firstread_objset_array::read( + (void*)(d + (size_t)fr->objset_array), fr->objset_array_size); + + if (fr->stage_data_array) + fr->stage_data_array = firstread_stage_data_array::read( + (void*)(d + (size_t)fr->stage_data_array), fr->stage_data_array_size); + return fr; +} diff --git a/src/DivaGL/pv_game/firstread.hpp b/src/DivaGL/pv_game/firstread.hpp new file mode 100644 index 0000000..da5f4a1 --- /dev/null +++ b/src/DivaGL/pv_game/firstread.hpp @@ -0,0 +1,153 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../KKdLib/vec.hpp" +#include "../object.hpp" +#include "../stage.hpp" +#include "../types.hpp" + +struct firstread_str_array_string { + int32_t id; + const char* str; +}; + +struct firstread_str_array_lang { + int32_t lang_id; + uint32_t num_string; + const firstread_str_array_string* string_array; +}; + +struct firstread_str_array { + uint32_t signature; + uint32_t num_lang; + const firstread_str_array_lang* lang_array; + + static const firstread_str_array* read(const void* data, size_t size); +}; + +struct firstread_auth_3d_object { + const char* name; + const char* uid_name; +}; + +struct firstread_auth_3d_object_list { + const char* name; + bool remove; +}; + +struct firstread_auth_3d { + int32_t uid; + uint32_t num_object; + uint32_t num_object_list; + const firstread_auth_3d_object* object_array; + const firstread_auth_3d_object_list* object_list_array; +}; + +struct firstread_auth_3d_array { + uint32_t signature; + uint32_t num_auth_3d; + const firstread_auth_3d* auth_3d_array; + + static const firstread_auth_3d_array* read(const void* data, size_t size); +}; + +struct firstread_obj_sub_mesh_split { + obj_bounding_sphere bounding_sphere[2]; + int32_t material_index[2]; + obj_index_format index_format; + int32_t num_index[2]; + const void* index_array[2]; + obj_sub_mesh_attrib attrib[2]; +}; + +struct firstread_obj_sub_mesh { + obj_bounding_sphere bounding_sphere; + obj_index_format index_format; + int32_t num_index; + const void* index_array; + obj_sub_mesh_attrib attrib; + firstread_obj_sub_mesh_split* split; +}; + +struct firstread_obj_mesh { + firstread_obj_sub_mesh* submesh_array; + int32_t num_submesh; + obj_vertex_format vertex_format; + uint32_t size_vertex; + int32_t num_vertex; + union { + obj_mesh_vertex_array vertex_array; + void* vertex_array_ptr[20]; + }; + obj_mesh_attrib attrib; + bool remove; + uint8_t index; + uint8_t pad[2]; + char name[0x40]; +}; + +struct firstread_obj { + int32_t id; + uint16_t num_mesh; + uint16_t num_material; + firstread_obj_mesh* mesh_array; + const obj_material_data* material_array; +}; + +struct firstread_objset { + uint32_t signature; + int32_t obj_num; + const firstread_obj* obj_data; + + static const firstread_objset* read( + prj::shared_ptr& alloc, const void* data, size_t size); +}; + +struct firstread_objset_data { + const void* data; + size_t size; +}; + +struct firstread_objset_array { + uint32_t signature; + uint32_t num_objset; + const int32_t* objset_id_array; + const firstread_objset_data* objset_array; + + static const firstread_objset_array* read(const void* data, size_t size); +}; + +struct firstread_stage_data { + const char* name; + uint32_t pv_id; + uint8_t reflect_type; + uint8_t reflect_full; + const stage_data_reflect* reflect; +}; + +struct firstread_stage_data_array { + uint32_t signature; + uint32_t num_stage_data; + const firstread_stage_data* stage_data_array; + + static const firstread_stage_data_array* read(const void* data, size_t size); +}; + +struct firstread { + uint32_t signature; + uint32_t pad[0x03]; + const firstread_str_array* str_array; + size_t str_array_size; + const firstread_auth_3d_array* auth_3d_array; + size_t auth_3d_array_size; + const firstread_objset_array* objset_array; + size_t objset_array_size; + const firstread_stage_data_array* stage_data_array; + size_t stage_data_array_size; + + static const firstread* read(const void* data, size_t size); +}; diff --git a/src/DivaGL/pv_game/pv_game.cpp b/src/DivaGL/pv_game/pv_game.cpp index 2b76fbc..ccb40c5 100644 --- a/src/DivaGL/pv_game/pv_game.cpp +++ b/src/DivaGL/pv_game/pv_game.cpp @@ -11,6 +11,7 @@ #include "../auth_3d.hpp" #include "../print_work.hpp" #include "dsc.hpp" +#include "firstread.hpp" #include "pvpp.hpp" #include "pvsr.hpp" #include @@ -620,26 +621,30 @@ public: void stop_current_pv(); }; -struct x_pv_game_str_array { - prj::unordered_map> strings; +struct x_pv_game_firstread { + prj::unordered_map> str_array_strings; p_file_handler file_handler; + const firstread* firstread; int32_t lang_sel; bool init; - x_pv_game_str_array(); - ~x_pv_game_str_array(); + x_pv_game_firstread(); + ~x_pv_game_firstread(); - const char* get_string(int32_t id); + const char* get_str_array_string(int32_t id); void read(); }; TaskPvGame& task_pv_game = *(TaskPvGame*)0x000000014CC95270; TaskPvGameX* task_pv_game_x; -x_pv_game_str_array* x_pv_game_str_array_ptr; +const firstread* firstread_ptr; +x_pv_game_firstread* x_pv_game_firstread_ptr; pv_disp2d& pv_disp2d_data = *(pv_disp2d*)0x0000000140C938E0; size_t pv_game_ptr = 0x0000000140CDD8D0; pv_game_parent& pv_game_parent_data = *(pv_game_parent*)0x0000000140D0B510; +bool reflect_full = false; + bool pv_game_load_state_4_tail_impl() { if (task_pv_game_x->use) { bool wait_load = false; @@ -827,15 +832,15 @@ HOOK(bool, FASTCALL, pv_game_pv_data__load, 0x000000014011B7E0, size_t _this, void pv_game_init() { if (!task_pv_game_x) task_pv_game_x = new (_operator_new(sizeof(TaskPvGameX))) TaskPvGameX; - if (!x_pv_game_str_array_ptr) - x_pv_game_str_array_ptr = new (_operator_new(sizeof(x_pv_game_str_array))) x_pv_game_str_array; + if (!x_pv_game_firstread_ptr) + x_pv_game_firstread_ptr = new (_operator_new(sizeof(x_pv_game_firstread))) x_pv_game_firstread; } void pv_game_free() { - if (x_pv_game_str_array_ptr) { - x_pv_game_str_array_ptr->~x_pv_game_str_array(); - _operator_delete(x_pv_game_str_array_ptr); - x_pv_game_str_array_ptr = 0; + if (x_pv_game_firstread_ptr) { + x_pv_game_firstread_ptr->~x_pv_game_firstread(); + _operator_delete(x_pv_game_firstread_ptr); + x_pv_game_firstread_ptr = 0; } if (task_pv_game_x) { @@ -1715,6 +1720,7 @@ void x_pv_game_effect::set_song_effect(int32_t index, int64_t time) { i.id.set_repeat(false); i.id.set_req_frame(0.0f); i.id.set_visibility(true); + i.id.set_reflect(reflect_full); } for (x_pv_game_song_effect_glitter& i : song_effect.glitter) { @@ -1979,7 +1985,7 @@ void x_pv_aet_disp_string::ctrl(const char* name, aet_obj_data* aet) { } static const char* sub_8133DDF8(int32_t id) { - return x_pv_game_str_array_ptr->get_string(id); + return x_pv_game_firstread_ptr->get_str_array_string(id); } const char* x_pv_str_array_pv::get_song_name(int32_t index) { @@ -3166,6 +3172,7 @@ void x_pv_game_stage::ctrl(float_t delta_time) { id.set_paused(false); id.set_visibility(false); id.set_frame_rate(&bpm_frame_rate_control); + id.set_reflect(reflect_full); eff_auth_3d.id = id; eff_auth_3d.name = stg_eff_auth_3d.name; @@ -3438,6 +3445,7 @@ void x_pv_game_stage::load_change_effect(int32_t curr_stage_effect, int32_t next id.set_paused(false); id.set_visibility(false); id.set_frame_rate(&bpm_frame_rate_control); + id.set_reflect(reflect_full); chg_eff_auth_3d.id = id; chg_eff_auth_3d.name = stg_chg_eff_auth_3d.name; @@ -3560,6 +3568,7 @@ void x_pv_game_stage::set_change_effect_frame_part_2(float_t frame) { id.set_paused(false); id.set_visibility(!!(flags & 0x01)); id.set_frame_rate(&bpm_frame_rate_control); + id.set_reflect(reflect_full); } for (x_pv_game_stage_effect_glitter& i : chg_eff.glitter) { @@ -3649,6 +3658,7 @@ void x_pv_game_stage::set_stage_effect_auth_3d_frame(int32_t stage_effect, float id.set_paused(false); id.set_visibility(true); id.set_frame_rate(&bpm_frame_rate_control); + id.set_reflect(reflect_full); } } @@ -3830,7 +3840,22 @@ TaskPvGameX::~TaskPvGameX() { bool TaskPvGameX::init() { use = true; - x_pv_game_str_array_ptr->read(); + x_pv_game_firstread_ptr->read(); + reflect_full = false; + extern bool config_reflect_full; + if (firstread_ptr && firstread_ptr->stage_data_array && config_reflect_full) { + const firstread_stage_data_array* stage_data_array = firstread_ptr->stage_data_array; + const uint32_t num_stage_data = stage_data_array->num_stage_data; + for (uint32_t i = 0; i < num_stage_data; i++) { + const firstread_stage_data* stage_data = &stage_data_array->stage_data_array[i]; + if (stage_data->pv_id == pv_id) { + if (stage_data->reflect_type == STAGE_DATA_REFLECT_REFLECT_MAP + && stage_data->reflect && stage_data->reflect_full) + reflect_full = true; + break; + } + } + } return true; } @@ -3909,12 +3934,45 @@ bool TaskPvGameX::ctrl() { bool TaskPvGameX::dest() { unload(); + reflect_full = false; use = false; return true; } void TaskPvGameX::disp() { data.disp(); + + static bool reflect_show; + if (reflect_full && reflect_show) { + extern RenderTexture* reflect_tex; + if (reflect_tex) { + const float_t width = 1280.0f; + const float_t height = 720.0f; + + const float_t reflection_quality = 1.0f; + + spr::put_sprite_rect({ 0.0f, 0.0f, width, height }, RESOLUTION_MODE_HD, + spr::SPR_PRIO_DEFAULT, { 0x00, 0x00, 0x00, 0xFF }, 0); + + spr::SprArgs args; + args.resolution_mode_screen = RESOLUTION_MODE_HD; + args.resolution_mode_sprite = RESOLUTION_MODE_HD; + args.SetSpriteSize({ width, height }); + args.SetTexturePosSize(0.0f, + (float_t)reflect_tex->GetHeight() - (float_t)reflect_tex->GetHeight() * reflection_quality, + (float_t)reflect_tex->GetWidth() * reflection_quality, + (float_t)reflect_tex->GetHeight() * reflection_quality); + args.texture = reflect_tex->color_texture; + args.color = color4u8_bgra(0xFF, 0xFF, 0xFF, 0x3F); + args.scale.x = 1.0f; + args.scale.y = -1.0f; + args.center.x = width * 0.5f; + args.center.y = height * 0.5f; + args.trans.x = width * 0.5f; + args.trans.y = height * 0.5f; + spr::put_sprite(args); + } + } } void TaskPvGameX::load(int32_t pv_id, int32_t modules[6]) { @@ -4076,17 +4134,19 @@ void TaskPvGameX::stop_current_pv() { data.stop(); } -x_pv_game_str_array::x_pv_game_str_array() : init() { +x_pv_game_firstread::x_pv_game_firstread() : init(), firstread() { lang_sel = 0; } -x_pv_game_str_array::~x_pv_game_str_array() { - +x_pv_game_firstread::~x_pv_game_firstread() { + firstread = 0; + firstread_ptr = 0; + file_handler.reset(); } -const char* x_pv_game_str_array::get_string(int32_t id) { - auto lang_elem = strings.find(lang_sel); - if (lang_elem != strings.end()) { +const char* x_pv_game_firstread::get_str_array_string(int32_t id) { + auto lang_elem = str_array_strings.find(lang_sel); + if (lang_elem != str_array_strings.end()) { auto elem = lang_elem->second.find(id); if (elem != lang_elem->second.end()) return elem->second; @@ -4094,11 +4154,11 @@ const char* x_pv_game_str_array::get_string(int32_t id) { return 0; } -void x_pv_game_str_array::read() { +void x_pv_game_firstread::read() { if (init) return; - file_handler.read_file_path("rom/str_array_x.bin", prj::HeapCMallocSystem); + file_handler.read_file_path("rom/firstread_x.bin", prj::HeapCMallocSystem); file_handler.read_now(); if (!file_handler.get_data() || !file_handler.get_size()) { @@ -4106,24 +4166,22 @@ void x_pv_game_str_array::read() { return; } - size_t data = (size_t)file_handler.get_data(); - if (*(uint32_t*)data != reverse_endianness_uint32_t('strx')) { - init = true; - return; + firstread = firstread::read(file_handler.get_data(), file_handler.get_size()); + firstread_ptr = firstread; + + if (firstread->str_array) { + const firstread_str_array* str_array = firstread->str_array; + const uint32_t lang_count = str_array->num_lang; + for (uint32_t i = 0; i < lang_count; i++) { + const firstread_str_array_lang* lang_data = &str_array->lang_array[i]; + + prj::unordered_map& strings = str_array_strings[lang_data->lang_id]; + const uint32_t num_string = lang_data->num_string; + for (uint32_t j = 0; j < num_string; j++) { + const firstread_str_array_string* string_data = &lang_data->string_array[j]; + strings[string_data->id] = string_data->str; + } + } } - - uint32_t lang_count = *(uint32_t*)(data + 0x04); - size_t lang_data = data + *(uint32_t*)(data + 0x08); - for (uint32_t i = lang_count; i; i--, lang_data += 0x0C) { - int32_t lang_id = *(int32_t*)lang_data; - uint32_t strings_count = *(uint32_t*)(lang_data + 0x04); - uint32_t strings_offset = *(uint32_t*)(lang_data + 0x08); - - prj::unordered_map& strings = this->strings[lang_id]; - size_t strings_data = data + strings_offset; - for (uint32_t j = strings_count; j; j--, strings_data += 0x08) - strings[*(int32_t*)strings_data] = (const char*)(data + *(uint32_t*)(strings_data + 0x04)); - } - init = true; } diff --git a/src/DivaGL/render.cpp b/src/DivaGL/render.cpp index 857803e..cdced59 100644 --- a/src/DivaGL/render.cpp +++ b/src/DivaGL/render.cpp @@ -227,9 +227,9 @@ namespace rndr { rctx->sun_quad_ubo.Bind(0); mat4 view; - mat4_transpose(&camera_data->view, &view); + mat4_transpose(&camera_data.view, &view); mat4 projection; - mat4_transpose(&camera_data->projection, &projection); + mat4_transpose(&camera_data.projection, &projection); ExposureCharaData* chara_data = exposure_chara_data; int32_t query_index = (this->exposure_query_index + 1) % 3; @@ -339,16 +339,16 @@ namespace rndr { return; mat4 view; - mat4_transpose(&camera_data->view, &view); + mat4_transpose(&camera_data.view, &view); mat4 projection; - mat4_transpose(&camera_data->projection, &projection); + mat4_transpose(&camera_data.projection, &projection); mat4 view_projection; mat4 inverse_view_projection_matrix; - mat4_transpose(&camera_data->view_projection, &view_projection); + mat4_transpose(&camera_data.view_projection, &view_projection); mat4_invert(&view_projection, &inverse_view_projection_matrix); - float_t v5 = tanf(camera_data->fov * 0.5f * DEG_TO_RAD_FLOAT); + float_t v5 = tanf(camera_data.fov * 0.5f * DEG_TO_RAD_FLOAT); light_set* set = &light_set_data[LIGHT_SET_MAIN]; light_data* data = &set->lights[LIGHT_SUN]; @@ -820,16 +820,16 @@ namespace rndr { view_point_prev = view_point; interest_prev = interest; - view_point = camera_data->view_point; - interest = camera_data->interest; + view_point = camera_data.view_point; + interest = camera_data.interest; stage_index_prev = stage_index; stage_index = task_stage_get_current_stage_index(); cam_view_projection_prev = cam_view_projection; - cam_view_projection = camera_data->view_projection; + cam_view_projection = camera_data.view_projection; - reset_exposure = camera_data->fast_change_hist1 && !camera_data->fast_change_hist0; + reset_exposure = camera_data.fast_change_hist1 && !camera_data.fast_change_hist0; if (reset_exposure) { float_t view_point_dist = vec3::distance(view_point, view_point_prev); @@ -1354,8 +1354,8 @@ namespace rndr { mat4 v42; mat4 v43; - mat4_mul(&camera_data->view, &v44, &v42); - mat4_mul(&camera_data->projection, &v42, &v43); + mat4_mul(&camera_data.view, &v44, &v42); + mat4_mul(&camera_data.projection, &v42, &v43); mat4_transpose(&v42, &v42); mat4_transpose(&v43, &v43); @@ -1385,7 +1385,7 @@ namespace rndr { v17 = 0.0f; float_t v18 = (float_t)height / (float_t)width; - float_t v20 = tanf(camera_data->fov * 0.5f * DEG_TO_RAD_FLOAT); + float_t v20 = tanf(camera_data.fov * 0.5f * DEG_TO_RAD_FLOAT); float_t v21 = 0.25f / sqrtf(powf(v20 * 3.4f, 2.0f) * (v41.z * v41.z)); float_t v22; if (v21 < 0.055f) diff --git a/src/DivaGL/render_context.cpp b/src/DivaGL/render_context.cpp index d43584d..7d1c95f 100644 --- a/src/DivaGL/render_context.cpp +++ b/src/DivaGL/render_context.cpp @@ -613,7 +613,7 @@ void render_context::ctrl(bool change_res) { return; if (screen_res_change) - render_manager->resize(screen_width, screen_height); + render_manager.resize(screen_width, screen_height); /*if (render_res_change) litproj_texture->Init(render_width, render_height, 0, GL_RGBA8, GL_DEPTH_COMPONENT32F);*/ @@ -629,7 +629,7 @@ void render_context::ctrl(bool change_res) { }; RenderTexture& render_buffer = render->rend_texture[0]; - RenderTexture& reflect_buffer = render_manager->get_render_texture(0); + RenderTexture& reflect_buffer = render_manager.get_render_texture(0); RenderTexture& shadow_buffer = shadow_ptr_get()->render_textures[1]; init_copy_buffer(reflect_buffer, this->reflect_buffer); init_copy_buffer(render_buffer, this->render_buffer); @@ -683,7 +683,7 @@ void render_context::init() { }; RenderTexture& render_buffer = render_get()->rend_texture[0]; - RenderTexture& reflect_buffer = render_manager->get_render_texture(0); + RenderTexture& reflect_buffer = render_manager.get_render_texture(0); RenderTexture& shadow_buffer = shadow_ptr_get()->render_textures[1]; init_copy_buffer(reflect_buffer, this->reflect_buffer); init_copy_buffer(render_buffer, this->render_buffer); diff --git a/src/DivaGL/render_context.hpp b/src/DivaGL/render_context.hpp index 5aa9930..c4237f8 100644 --- a/src/DivaGL/render_context.hpp +++ b/src/DivaGL/render_context.hpp @@ -451,6 +451,7 @@ struct render_context { int32_t screen_height; mdl::ObjList obj_local[mdl::OBJ_TYPE_LOCAL_MAX - mdl::OBJ_TYPE_MAX]; + mdl::ObjList obj_reflect[mdl::OBJ_TYPE_REFLECT_MAX - mdl::OBJ_TYPE_LOCAL_MAX]; render_context(); ~render_context(); diff --git a/src/DivaGL/render_manager.cpp b/src/DivaGL/render_manager.cpp index 71cb8d7..d4e8dcc 100644 --- a/src/DivaGL/render_manager.cpp +++ b/src/DivaGL/render_manager.cpp @@ -9,6 +9,7 @@ #include "light_param/fog.hpp" #include "light_param/light.hpp" #include "mdl/disp_manager.hpp" +#include "mdl/draw_object.hpp" #include "rob/rob.hpp" #include "clear_color.hpp" #include "effect.hpp" @@ -23,6 +24,29 @@ #include "texture.hpp" #include +struct reflect_full_struct { + RenderTexture reflect_texture; + RenderTexture reflect_buffer_texture; + RenderTexture reflect_contour_texture; + + reflect_full_struct(); + ~reflect_full_struct(); + + void free(); + void init(); +}; + +extern render_context* rctx; + +vec4 reflect_clip_plane; +bool reflect_draw = false; +mat4 reflect_mat; +reflect_full_struct* reflect_full_ptr; + +RenderTexture* litproj_shadow = (RenderTexture*)0x0000000141194DA0; +RenderTexture* litproj_texture = (RenderTexture*)0x0000000141194E00; +rndr::RenderManager& render_manager = *(rndr::RenderManager*)0x00000001411AD320; + static void draw_pass_shadow_begin_make_shadowmap(Shadow* shad, int32_t index, int32_t a3); static void draw_pass_shadow_end_make_shadowmap(Shadow* shad, int32_t index, int32_t a3); static void draw_pass_shadow_filter(RenderTexture* a1, RenderTexture* a2, @@ -36,22 +60,21 @@ static void draw_pass_sss_filter(sss_data* sss); static int32_t draw_pass_3d_get_translucent_count(); static void draw_pass_3d_shadow_reset(); static void draw_pass_3d_shadow_set(Shadow* shad); -extern void draw_pass_3d_translucent(mdl::ObjType opaque, mdl::ObjType transparent, mdl::ObjType translucent); +extern void draw_pass_3d_translucent(mdl::ObjType opaque, + mdl::ObjType transparent, mdl::ObjType translucent); static int32_t draw_pass_3d_translucent_count_layers(int32_t* alpha_array, mdl::ObjType opaque, mdl::ObjType transparent, mdl::ObjType translucent); static void draw_pass_3d_translucent_has_objects(bool* arr, mdl::ObjType type); +static void draw_pass_reflect_full(rndr::RenderManager& render_manager); + static void blur_filter_apply(RenderTexture* dst, RenderTexture* src, blur_filter_mode filter, const vec2 res_scale, const vec4 scale, const vec4 offset); static void render_manager_free_render_textures(); static void render_manager_init_render_textures(int32_t multisample); -extern render_context* rctx; - -RenderTexture* litproj_shadow = (RenderTexture*)0x0000000141194DA0; -RenderTexture* litproj_texture = (RenderTexture*)0x0000000141194E00; -rndr::RenderManager* render_manager = (rndr::RenderManager*)0x00000001411AD320; +static void set_reflect_mat(render_context* rctx); namespace rndr { struct RenderTextureData { @@ -420,6 +443,101 @@ namespace rndr { gl_state_begin_event("pass_ss_sss"); rndr::Render* rend = render; + extern bool reflect_full; + if (reflect_full && pass_sw[rndr::RND_PASSID_REFLECT] + && disp_manager->get_obj_count(mdl::OBJ_TYPE_SSS)) { + gl_state_begin_event("reflect"); + reflect_draw = true; + + rndr::Render* rend = render; + RenderTexture& refl_tex = reflect_full_ptr->reflect_texture; + //if (refl_tex.GetWidth() > 1280.0) + // sss->npr_contour = false; + + //if (sss->npr_contour) { + refl_tex.Bind(); + refl_tex.SetViewport(); + //} + //else { + // sss->textures[0].Bind(); + // gl_state_set_viewport(0, 0, 640, 360); + //} + + glClearColorDLL(sss->param.x, sss->param.y, sss->param.z, 0.0f); + glClearDLL(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + draw_pass_set_camera(); + for (int32_t i = LIGHT_SET_MAIN; i < LIGHT_SET_MAX; i++) + light_set_data[i].data_set((light_set_id)i); + + if (shadow) + draw_pass_3d_shadow_set(shadow_ptr); + else + draw_pass_3d_shadow_reset(); + + set_reflect_mat(rctx); + + draw_state.shader_index = SHADER_FT_SSS_SKIN; + gl_state_enable_depth_test(); + gl_state_set_depth_func(GL_LEQUAL); + gl_state_set_depth_mask(GL_TRUE); + disp_manager->draw(mdl::OBJ_TYPE_SSS); + gl_state_disable_depth_test(); + draw_state.shader_index = -1; + draw_pass_3d_shadow_reset(); + uniform->arr[U_NPR] = 0; + + if (npr_param == 1) { + if (sss->enable && sss->npr_contour) { + uniform->arr[U_NPR] = 1; + draw_pass_sss_contour(rend); + } + else if (npr) { + refl_tex.Bind(); + refl_tex.SetViewport(); + glClearDLL(GL_DEPTH_BUFFER_BIT); + draw_state.shader_index = SHADER_FT_SSS_SKIN; + gl_state_enable_depth_test(); + gl_state_set_depth_mask(GL_TRUE); + disp_manager->draw(mdl::OBJ_TYPE_SSS); + gl_state_disable_depth_test(); + draw_state.shader_index = -1; + gl_state_bind_framebuffer(0); + uniform->arr[U_NPR] = 1; + draw_pass_sss_contour(rend); + } + } + + if (!sss->npr_contour) { + sss->textures[0].Bind(); + gl_state_set_viewport(0, 0, 640, 360); + + filter_scene_shader_data filter_scene = {}; + filter_scene.g_transform = { 1.0f, 1.0f, 0.0f, 0.0f }; + filter_scene.g_texcoord = { 1.0f, 1.0f, 0.0f, 0.0f }; + rctx->filter_scene_ubo.WriteMemory(filter_scene); + + imgfilter_batch_shader_data imgfilter_batch = {}; + imgfilter_batch.g_color_scale = 1.0f; + imgfilter_batch.g_color_offset = 0.0f; + imgfilter_batch.g_texture_lod = 0.0f; + rctx->imgfilter_batch_ubo.WriteMemory(imgfilter_batch); + + uniform->arr[U_IMAGE_FILTER] = 5; + shaders_ft.set(SHADER_FT_IMGFILT); + rctx->filter_scene_ubo.Bind(0); + rctx->imgfilter_batch_ubo.Bind(1); + gl_state_active_bind_texture_2d(0, refl_tex.GetColorTex()); + gl_state_bind_sampler(0, rctx->render_samplers[0]); + gl_state_bind_vertex_array(rctx->common_vao); + shaders_ft.draw_arrays(GL_TRIANGLE_STRIP, 0, 4); + } + + draw_pass_sss_filter(sss); + reflect_draw = false; + gl_state_end_event(); + } + //if (rend->render_width > 1280.0) // sss->npr_contour = false; @@ -507,8 +625,17 @@ namespace rndr { } void RenderManager::pass_reflect() { + extern bool reflect_full; + if (reflect_full) { + draw_pass_reflect_full(*this); + return; + } + + extern RenderTexture* reflect_tex; + reflect_tex = 0; + gl_state_begin_event("pass_reflect"); - RenderTexture& refl_tex = render_manager->get_render_texture(0); + RenderTexture& refl_tex = render_manager.get_render_texture(0); RenderTexture& refl_buf_tex = rctx->reflect_buffer; refl_tex.Bind(); if (disp_manager->get_obj_count(mdl::OBJ_TYPE_REFLECT_OPAQUE) @@ -578,7 +705,7 @@ namespace rndr { void RenderManager::pass_refract() { gl_state_begin_event("pass_refract"); - RenderTexture& refract_texture = render_manager->get_render_texture(1); + RenderTexture& refract_texture = render_manager.get_render_texture(1); refract_texture.Bind(); if (disp_manager->get_obj_count(mdl::OBJ_TYPE_REFRACT_OPAQUE) || disp_manager->get_obj_count(mdl::OBJ_TYPE_REFRACT_TRANSPARENT) @@ -730,7 +857,9 @@ namespace rndr { gl_state_active_bind_texture_2d(14, rctx->empty_texture_2d->glid); if (pass_sw[RND_PASSID_REFLECT] && reflect) { - RenderTexture& refl_tex = get_render_texture(0); + extern bool reflect_full; + RenderTexture& refl_tex = reflect_full && reflect_full_ptr + ? reflect_full_ptr->reflect_texture : get_render_texture(0); gl_state_active_bind_texture_2d(15, refl_tex.GetColorTex()); uniform->arr[U_WATER_REFLECT] = 1; } @@ -773,7 +902,7 @@ namespace rndr { gl_state_set_depth_mask(GL_TRUE); if (draw_pass_3d[DRAW_PASS_3D_TRANSPARENT]) disp_manager->draw(mdl::OBJ_TYPE_TRANSPARENT); - if (render_manager->field_120) + if (render_manager.field_120) disp_manager->draw(mdl::OBJ_TYPE_TYPE_7); render->calc_exposure_chara_data(); @@ -844,8 +973,8 @@ namespace rndr { if (Glitter::glt_particle_manager_x->CheckHasLocalEffect()) { // X gl_state_begin_event("local"); - float_t fov = camera_data->fov; - camera_data->fov = 32.2673416137695f; + float_t fov = camera_data.fov; + camera_data.fov = 32.2673416137695f; draw_pass_set_camera(); disp_manager->draw(mdl::OBJ_TYPE_OPAQUE_LOCAL); @@ -862,7 +991,7 @@ namespace rndr { gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); Glitter::glt_particle_manager_x->DispScenes(Glitter::DISP_LOCAL); gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - camera_data->fov = fov; + camera_data.fov = fov; gl_state_end_event(); @@ -968,8 +1097,16 @@ namespace rndr { } void RenderManager::pass_3d_contour() { - RenderTexture* rt = &render->rend_texture[0]; - RenderTexture* contour_rt = render->sss_contour_texture; + RenderTexture* rt; + RenderTexture* contour_rt; + if (reflect_draw) { + rt = &reflect_full_ptr->reflect_texture; + contour_rt = &reflect_full_ptr->reflect_buffer_texture; + } + else { + rt = &render->rend_texture[0]; + contour_rt = render->sss_contour_texture; + } gl_state_begin_event("`anonymous-namespace'::draw_npr_frame"); gl_state_enable_blend(); @@ -1059,15 +1196,15 @@ void image_filter_scale(RenderTexture* dst, texture* src, const vec4& scale) { void draw_pass_set_camera() { camera_struct::update_data(); - mat4_transpose(&camera_data->view, &rctx->view_mat); - mat4_transpose(&camera_data->projection, &rctx->proj_mat); - mat4_transpose(&camera_data->view_projection, &rctx->vp_mat); + mat4_transpose(&camera_data.view, &rctx->view_mat); + mat4_transpose(&camera_data.projection, &rctx->proj_mat); + mat4_transpose(&camera_data.view_projection, &rctx->vp_mat); vec3 view_point; - camera_data->get_view_point(view_point); + camera_data.get_view_point(view_point); rctx->set_scene_projection_view(rctx->view_mat, rctx->proj_mat, view_point); - float_t max_distance = camera_data->max_distance; - float_t min_distance = camera_data->min_distance; + float_t max_distance = camera_data.max_distance; + float_t min_distance = camera_data.min_distance; rctx->g_near_far = { (float_t)(max_distance / (max_distance - min_distance)), (float_t)(-(max_distance * min_distance) / (max_distance - min_distance)), @@ -1080,8 +1217,10 @@ HOOK(void, FASTCALL, render_manager_init_render_textures, 0x0000000140502560, in } HOOK(void, FASTCALL, render_manager_free_data, 0x0000000140502770) { + if (reflect_full_ptr) + reflect_full_ptr->free(); render_manager_free_render_textures(); - render_manager->render->free(); + render_manager.render->free(); shadow_ptr_free(); @@ -1093,8 +1232,6 @@ HOOK(void, FASTCALL, render_manager_free_render_textures, 0x00000001405027A0) { } HOOK(void, FASTCALL, render_manager_init_data, 0x0000000140502A2A, int32_t ssaa, int32_t hd_res, int32_t ss_alpha_mask, bool npr) { - rndr::RenderManager& render_manager = *::render_manager; - render_manager.reset(); render_manager.npr = npr; render_texture_counter_reset(); @@ -1119,9 +1256,25 @@ HOOK(void, FASTCALL, render_manager_init_data, 0x0000000140502A2A, int32_t ssaa, void(FASTCALL * sub_1403B6CC0)() = (void(FASTCALL*)())0x00000001403B6CC0; sub_1403B6CC0(); + extern bool config_reflect_full; + if (reflect_full_ptr && config_reflect_full) + reflect_full_ptr->init(); + glGetErrorDLL(); } +void reflect_full_init() { + if (!reflect_full_ptr) + reflect_full_ptr = new reflect_full_struct; +} + +void reflect_full_free() { + if (reflect_full_ptr) { + delete reflect_full_ptr; + reflect_full_ptr = 0; + } +} + void render_manager_patch() { WRITE_NOP_6(0x0000000140502A24); WRITE_MEMORY(0x0000000140502A3C, uint8_t, 0xC3); @@ -1132,6 +1285,66 @@ void render_manager_patch() { INSTALL_HOOK(render_manager_init_data); } +reflect_full_struct::reflect_full_struct() { + +} + +reflect_full_struct::~reflect_full_struct() { + free(); +} + +void reflect_full_struct::free() { + reflect_contour_texture.Free(); + + reflect_buffer_texture.Free(); + reflect_texture.Free(); +} + +void reflect_full_struct::init() { + rndr::Render* render = render_manager.render; + + reflect_texture.Init(render->render_width[0], render->render_height[0], + 0, GL_RGBA16F, GL_DEPTH_COMPONENT24); + reflect_buffer_texture.Init(render->render_width[0], render->render_height[0], + 0, GL_RGBA16F, GL_DEPTH_COMPONENT24); + + reflect_contour_texture.SetColorDepthTextures(reflect_texture.GetColorTex()); +} + +void get_reflect_mat() { + vec4 reflect_clip_plane; + const light_set* set = &light_set_data[LIGHT_SET_MAIN]; + const light_data* light_reflect = &set->lights[LIGHT_REFLECT]; + if (light_reflect->type == LIGHT_SPOT) { + const vec3 spot_direction = -light_reflect->spot_direction; + const vec3 position = *(vec3*)&light_reflect->position; + + float_t length = vec3::length(spot_direction); + if (length > 0.000001f) + *(vec3*)&reflect_clip_plane = spot_direction * (1.0f / length); + else + *(vec3*)&reflect_clip_plane = { 0.0f, 1.0f, 0.0f }; + + reflect_clip_plane.w = -vec3::dot(position, *(vec3*)&reflect_clip_plane); + } + else if (light_reflect->type == LIGHT_POINT) + reflect_clip_plane = { 0.0f, -1.0f, 0.0f, 9999.0f }; + else + reflect_clip_plane = { 0.0f, -1.0f, 0.0f, 0.0f }; + + const vec4 temp = 2.0f * reflect_clip_plane; + + reflect_mat = mat4_identity; + *(vec3*)&reflect_mat.row0 -= temp.x * *(vec3*)&reflect_clip_plane; + *(vec3*)&reflect_mat.row1 -= temp.y * *(vec3*)&reflect_clip_plane; + *(vec3*)&reflect_mat.row2 -= temp.z * *(vec3*)&reflect_clip_plane; + *(vec3*)&reflect_mat.row3 -= temp.w * *(vec3*)&reflect_clip_plane; + reflect_mat.row0.w = 0.0f; + reflect_mat.row1.w = 0.0f; + reflect_mat.row2.w = 0.0f; + reflect_mat.row3.w = 1.0f; +} + static void draw_pass_shadow_begin_make_shadowmap(Shadow* shad, int32_t index, int32_t a3) { shad->curr_render_textures[0]->Bind(); shad->curr_render_textures[0]->SetViewport(); @@ -1434,21 +1647,34 @@ static bool draw_pass_shadow_litproj_set_mat(bool set_mat) { } static void draw_pass_sss_contour(rndr::Render* rend) { - rend->sss_contour_texture->Bind(); - rend->sss_contour_texture->SetViewport(); + if (reflect_draw) + reflect_full_ptr->reflect_buffer_texture.Bind(); + else + rend->sss_contour_texture->Bind(); + gl_state_enable_depth_test(); gl_state_set_depth_func(GL_ALWAYS); gl_state_set_depth_mask(GL_TRUE); - gl_state_set_viewport(0, 0, rend->render_width[0], rend->render_height[0]); - gl_state_active_bind_texture_2d(0, rend->rend_texture[0].GetColorTex()); - gl_state_bind_sampler(0, rctx->render_samplers[1]); - gl_state_active_bind_texture_2d(1, rend->rend_texture[0].GetDepthTex()); - gl_state_bind_sampler(1, rctx->render_samplers[1]); + if (reflect_draw) { + RenderTexture& refl_tex = reflect_full_ptr->reflect_texture; + gl_state_set_viewport(0, 0, refl_tex.GetWidth(), refl_tex.GetHeight()); + gl_state_active_bind_texture_2d(0, refl_tex.GetColorTex()); + gl_state_bind_sampler(0, rctx->render_samplers[1]); + gl_state_active_bind_texture_2d(1, refl_tex.GetDepthTex()); + gl_state_bind_sampler(1, rctx->render_samplers[1]); + } + else { + gl_state_set_viewport(0, 0, rend->render_width[0], rend->render_height[0]); + gl_state_active_bind_texture_2d(0, rend->rend_texture[0].GetColorTex()); + gl_state_bind_sampler(0, rctx->render_samplers[1]); + gl_state_active_bind_texture_2d(1, rend->rend_texture[0].GetDepthTex()); + gl_state_bind_sampler(1, rctx->render_samplers[1]); + } gl_state_active_texture(0); - float_t v3 = 1.0f / tanf(camera_data->fov * 0.5f * DEG_TO_RAD_FLOAT); + float_t v3 = 1.0f / tanf(camera_data.fov * 0.5f * DEG_TO_RAD_FLOAT); - vec3 direction = camera_data->interest - camera_data->view_point; + vec3 direction = camera_data.interest - camera_data.view_point; float_t length = vec3::length(direction); float_t v7 = direction.y; if (length != 0.0f) @@ -1465,10 +1691,17 @@ static void draw_pass_sss_contour(rndr::Render* rend) { shaders_ft.set(SHADER_FT_CONTOUR); rctx->contour_coef_ubo.Bind(2); - render_get()->draw_quad( - rend->render_post_width[0], rend->render_post_height[0], - rend->render_post_width_scale, rend->render_post_height_scale, - 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + + if (reflect_draw) { + RenderTexture& refl_tex = reflect_full_ptr->reflect_texture; + render_get()->draw_quad(refl_tex.GetWidth(), refl_tex.GetHeight(), 1.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + } + else + render_get()->draw_quad( + rend->render_post_width[0], rend->render_post_height[0], + rend->render_post_width_scale, rend->render_post_height_scale, + 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); } static void draw_pass_sss_filter_calc_coef(double_t step, int32_t size, double_t a3, int32_t iterations, @@ -1511,8 +1744,8 @@ static void draw_pass_sss_filter_calc_coef(double_t step, int32_t size, double_t static void draw_pass_sss_filter(sss_data* sss) { const int32_t sss_count = 6; - vec3 interest = camera_data->interest; - vec3 view_point = camera_data->view_point; + vec3 interest = camera_data.interest; + vec3 view_point = camera_data.view_point; vec3 chara_position[2]; chara_position[0] = 0.0f; @@ -1543,7 +1776,7 @@ static void draw_pass_sss_filter(sss_data* sss) { interest = chara_position[0]; float_t v29 = max_def(vec3::distance(view_point, interest), 0.25f); - float_t v31 = max_def(tanf(camera_data->fov * 0.5f * DEG_TO_RAD_FLOAT) * 5.0f, 0.25f); + float_t v31 = max_def(tanf(camera_data.fov * 0.5f * DEG_TO_RAD_FLOAT) * 5.0f, 0.25f); float_t v33 = 0.6f; float_t v34 = (float_t)(1.0 / clamp_def(v31 * v29, 0.25f, 100.0f)); if (v34 < 0.145f) @@ -1557,7 +1790,9 @@ static void draw_pass_sss_filter(sss_data* sss) { rndr::Render* rend = render_get(); uniform->arr[U_REDUCE] = 0; shaders_ft.set(SHADER_FT_REDUCE); - RenderTexture& rt = rend->rend_texture[0]; + RenderTexture& rt = reflect_draw + ? reflect_full_ptr->reflect_texture + : rend->rend_texture[0]; gl_state_bind_texture_2d(rt.GetColorTex()); gl_state_bind_sampler(0, rctx->render_samplers[0]); render_get()->draw_quad(rt.GetWidth(), rt.GetHeight(), 1.0f, 1.0f, @@ -1582,7 +1817,7 @@ static void draw_pass_sss_filter(sss_data* sss) { draw_pass_sss_filter_calc_coef(1.0, sss_count, v34, 3, a5, a6, a7, a8, shader_data.g_coef); rctx->sss_filter_gaussian_coef_ubo.WriteMemory(shader_data); - sss->textures[1].Bind(); + sss->textures[reflect_draw ? 3 : 1].Bind(); gl_state_set_viewport(0, 0, 320, 180); uniform->arr[U_SSS_FILTER] = 3; shaders_ft.set(SHADER_FT_SSS_FILT); @@ -1717,7 +1952,8 @@ static void draw_pass_3d_shadow_set(Shadow* shad) { gl_state_bind_sampler(7, 0); } -static void draw_pass_3d_translucent(mdl::ObjType opaque, mdl::ObjType transparent, mdl::ObjType translucent) { +static void draw_pass_3d_translucent(mdl::ObjType opaque, + mdl::ObjType transparent, mdl::ObjType translucent) { if (disp_manager->get_obj_count(opaque) < 1 && disp_manager->get_obj_count(transparent) < 1 && disp_manager->get_obj_count(translucent) < 1) @@ -1731,11 +1967,11 @@ static void draw_pass_3d_translucent(mdl::ObjType opaque, mdl::ObjType transpare for (int32_t i = 0; i < count; i++) { int32_t alpha = alpha_array[i]; rend->transparency_copy(); - if (render_manager->draw_pass_3d[DRAW_PASS_3D_OPAQUE] && disp_manager->get_obj_count(opaque)) + if (render_manager.draw_pass_3d[DRAW_PASS_3D_OPAQUE] && disp_manager->get_obj_count(opaque)) disp_manager->draw(opaque, 0, true, alpha); - if (render_manager->draw_pass_3d[DRAW_PASS_3D_TRANSPARENT] && disp_manager->get_obj_count(transparent)) + if (render_manager.draw_pass_3d[DRAW_PASS_3D_TRANSPARENT] && disp_manager->get_obj_count(transparent)) disp_manager->draw(transparent, 0, true, alpha); - if (render_manager->draw_pass_3d[DRAW_PASS_3D_TRANSLUCENT] && disp_manager->get_obj_count(translucent)) { + if (render_manager.draw_pass_3d[DRAW_PASS_3D_TRANSLUCENT] && disp_manager->get_obj_count(translucent)) { gl_state_enable_blend(); disp_manager->draw(translucent, 0, true, alpha); gl_state_disable_blend(); @@ -1780,6 +2016,167 @@ static void draw_pass_3d_translucent_has_objects(bool* arr, mdl::ObjType type) { } } +RenderTexture* reflect_tex; + +static void draw_pass_reflect_full(rndr::RenderManager& render_manager) { + gl_state_begin_event("pass_reflect"); + RenderTexture& refl_tex = reflect_full_ptr->reflect_texture; + RenderTexture& refl_buf_tex = reflect_full_ptr->reflect_buffer_texture; + refl_tex.Bind(); + extern bool reflect_full; + if (disp_manager->get_obj_count(mdl::OBJ_TYPE_REFLECT_OPAQUE) + || disp_manager->get_obj_count(mdl::OBJ_TYPE_REFLECT_TRANSPARENT) + || disp_manager->get_obj_count(mdl::OBJ_TYPE_REFLECT_TRANSLUCENT_SORT_BY_RADIUS) + || disp_manager->get_obj_count(mdl::OBJ_TYPE_REFLECT_TRANSLUCENT)) { + reflect_tex = &refl_tex; + + refl_tex.SetViewport(); + + draw_pass_set_camera(); + if (!sss_data_get()->enable || !sss_data_get()->npr_contour) + glClearDLL(GL_DEPTH_BUFFER_BIT); + + gl_state_set_depth_func(GL_LEQUAL); + + for (int32_t i = LIGHT_SET_MAIN; i < LIGHT_SET_MAX; i++) + light_set_data[i].data_set((light_set_id)i); + for (int32_t i = FOG_DEPTH; i < FOG_MAX; i++) + fog_data[i].data_set((fog_id)i); + + glClearColorDLL(0.0f, 0.0f, 0.0f, 0.0f); + if (disp_manager->get_obj_count(mdl::OBJ_TYPE_SSS)) + glClearDLL(GL_COLOR_BUFFER_BIT); + else + glClearDLL(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + gl_state_enable_depth_test(); + gl_state_set_depth_func(GL_LEQUAL); + gl_state_set_depth_mask(GL_TRUE); + gl_state_set_cull_face_mode(GL_FRONT); + + reflect_draw = true; + draw_state.shader_index = -1; + + int32_t render_width = refl_tex.GetWidth(); + int32_t render_height = refl_tex.GetHeight(); + rctx->set_scene_framebuffer_size(render_width, render_height, render_width, render_height); + + if (render_manager.shadow) + draw_pass_3d_shadow_set(render_manager.shadow_ptr); + else + draw_pass_3d_shadow_reset(); + + if (render_manager.effect_texture) + gl_state_active_bind_texture_2d(14, render_manager.effect_texture->glid); + else + gl_state_active_bind_texture_2d(14, rctx->empty_texture_2d->glid); + + uniform->arr[U_WATER_REFLECT] = 0; + + sss_data_get()->set_texture(3); + + gl_state_bind_sampler(14, rctx->render_samplers[0]); + gl_state_bind_sampler(15, rctx->render_samplers[0]); + gl_state_bind_sampler(16, rctx->render_samplers[0]); + + uniform->arr[U_STAGE_AMBIENT] = render_manager.light_stage_ambient ? 1 : 0; + + set_reflect_mat(rctx); + + if (render_manager.alpha_z_sort) { + disp_manager->obj_sort(&rctx->view_mat, + mdl::OBJ_TYPE_REFLECT_TRANSLUCENT, 1, render_manager.field_31F); + disp_manager->obj_sort(&rctx->view_mat, + mdl::OBJ_TYPE_REFLECT_TRANSLUCENT_SORT_BY_RADIUS, 2); + } + + if (render_manager.opaque_z_sort) + disp_manager->obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_REFLECT_OPAQUE, 0); + + uniform->arr[U_REFLECT] = 1; + if (render_manager.draw_pass_3d[DRAW_PASS_3D_OPAQUE]) { + gl_state_enable_depth_test(); + gl_state_set_depth_mask(GL_TRUE); + disp_manager->draw(mdl::OBJ_TYPE_REFLECT_OPAQUE); + gl_state_disable_depth_test(); + } + + Glitter::glt_particle_manager_x->DispScenes(Glitter::DISP_OPAQUE); + + gl_state_enable_depth_test(); + gl_state_set_depth_mask(GL_TRUE); + if (render_manager.draw_pass_3d[DRAW_PASS_3D_TRANSPARENT]) + disp_manager->draw(mdl::OBJ_TYPE_REFLECT_TRANSPARENT); + + if (render_manager.npr_param == 1) + render_manager.pass_3d_contour(); + + gl_state_disable_depth_test(); + + gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); + Glitter::glt_particle_manager_x->DispScenes(Glitter::DISP_ALPHA); + gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + /*if (npr_param == 1) { + gl_state_set_color_mask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + }*/ + + gl_state_enable_depth_test(); + + if (render_manager.draw_pass_3d[DRAW_PASS_3D_TRANSLUCENT]) { + gl_state_enable_blend(); + gl_state_set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl_state_set_depth_mask(GL_FALSE); + disp_manager->draw(mdl::OBJ_TYPE_REFLECT_TRANSLUCENT_SORT_BY_RADIUS); + disp_manager->draw(mdl::OBJ_TYPE_REFLECT_TRANSLUCENT); + gl_state_disable_blend(); + } + + gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); // X + Glitter::glt_particle_manager_x->DispScenes(Glitter::DISP_TYPE_2); + gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + gl_state_disable_depth_test(); + + gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); + Glitter::glt_particle_manager_x->DispScenes(Glitter::DISP_NORMAL); + gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + gl_state_active_bind_texture_2d(14, 0); + gl_state_active_bind_texture_2d(15, 0); + + if (render_manager.shadow) + draw_pass_3d_shadow_reset(); + + rndr::Render* render = render_manager.render; + rctx->set_scene_framebuffer_size(render->render_width[0], + render->render_height[0], render->render_width[0], render->render_height[0]); + reflect_draw = false; + + gl_state_set_cull_face_mode(GL_BACK); + gl_state_disable_depth_test(); + uniform->arr[U_REFLECT] = 0; + + for (int32_t i = render_manager.reflect_blur_num, j = 0; i > 0; i--, j++) { + blur_filter_apply(&refl_buf_tex, &refl_tex, + render_manager.reflect_blur_filter, 1.0f, 1.0f, 0.0f); + image_filter_scale(&refl_tex, refl_buf_tex.color_texture); + } + } + else { + vec4 clear_color; + glGetFloatvDLL(GL_COLOR_CLEAR_VALUE, (GLfloat*)&clear_color); + glClearColorDLL(0.0f, 0.0f, 0.0f, 0.0f); + glClearDLL(GL_COLOR_BUFFER_BIT); + glClearColorDLL(clear_color.x, clear_color.y, clear_color.z, clear_color.w); + } + shader::unbind(); + gl_state_bind_framebuffer(0); + gl_state_end_event(); +} + static void blur_filter_apply(RenderTexture* dst, RenderTexture* src, blur_filter_mode filter, const vec2 res_scale, const vec4 scale, const vec4 offset) { if (!dst || !src) @@ -1818,8 +2215,6 @@ static void blur_filter_apply(RenderTexture* dst, RenderTexture* src, } static void render_manager_free_render_textures() { - rndr::RenderManager& render_manager = *::render_manager; - if (render_manager.multisample_renderbuffer) { glDeleteRenderbuffers(1, &render_manager.multisample_renderbuffer); render_manager.multisample_renderbuffer = 0; @@ -1835,8 +2230,6 @@ static void render_manager_free_render_textures() { } static void render_manager_init_render_textures(int32_t multisample) { - rndr::RenderManager& render_manager = *::render_manager; - if (multisample) { glGenFramebuffers(1, &render_manager.multisample_framebuffer); glGenRenderbuffers(1, &render_manager.multisample_renderbuffer); @@ -1874,3 +2267,31 @@ static void render_manager_init_render_textures(int32_t multisample) { } gl_state_bind_framebuffer(0); } + +static void set_reflect_mat(render_context* rctx) { + const vec3 clip_plane = *(vec3*)&rctx->data.buffer_scene_data.g_clip_plane; + const vec4 temp = 2.0f * rctx->data.buffer_scene_data.g_clip_plane; + + reflect_mat = mat4_identity; + *(vec3*)&reflect_mat.row0 -= temp.x * clip_plane; + *(vec3*)&reflect_mat.row1 -= temp.y * clip_plane; + *(vec3*)&reflect_mat.row2 -= temp.z * clip_plane; + *(vec3*)&reflect_mat.row3 -= temp.w * clip_plane; + reflect_mat.row0.w = 0.0f; + reflect_mat.row1.w = 0.0f; + reflect_mat.row2.w = 0.0f; + reflect_mat.row3.w = 1.0f; + + mat4 cam_view; + mat4 cam_projection; + mat4_transpose(&camera_data.view, &cam_view); + mat4_transpose(&camera_data.projection, &cam_projection); + + mat4_mul(&reflect_mat, &cam_view, &rctx->view_mat); + rctx->proj_mat = cam_projection; + mat4_mul(&rctx->view_mat, &rctx->proj_mat, &rctx->vp_mat); + + vec3 view_point = camera_data.view_point; + mat4_transform_point(&reflect_mat, &view_point, &view_point); + rctx->set_scene_projection_view(rctx->view_mat, rctx->proj_mat, view_point); +} diff --git a/src/DivaGL/render_manager.hpp b/src/DivaGL/render_manager.hpp index 10443ad..6097c18 100644 --- a/src/DivaGL/render_manager.hpp +++ b/src/DivaGL/render_manager.hpp @@ -135,10 +135,13 @@ namespace rndr { extern RenderTexture* litproj_shadow; extern RenderTexture* litproj_texture; -extern rndr::RenderManager* render_manager; +extern rndr::RenderManager& render_manager; extern void image_filter_scale(RenderTexture* dst, texture* src, const vec4& scale = 1.0f); extern void draw_pass_set_camera(); +extern void reflect_full_init(); +extern void reflect_full_free(); + extern void render_manager_patch(); diff --git a/src/DivaGL/renderer/dof.cpp b/src/DivaGL/renderer/dof.cpp index 01b359c..57bf332 100644 --- a/src/DivaGL/renderer/dof.cpp +++ b/src/DivaGL/renderer/dof.cpp @@ -45,7 +45,6 @@ namespace renderer { if (dof_debug_data->flags & DOF_DEBUG_AUTO_FOCUS) { size_t rob_chara_smth = get_rob_chara_smth(); - size_t rob_chr = 0; for (int32_t i = 0; i < ROB_CHARA_COUNT; i++) { rob_chara* rob_chr = rob_chara_array_get(rob_chara_smth, i); if (!rob_chr || !rob_chr->is_visible()) @@ -59,24 +58,24 @@ namespace renderer { mat4_get_translation(&mat, &chara_trans); mat4 view; - mat4_transpose(&camera_data->view, &view); + mat4_transpose(&camera_data.view, &view); focus = -vec3::dot(*(vec3*)&view.row2, chara_trans) - view.row2.w - 0.1f; break; } } - focus = max_def(focus, camera_data->min_distance); + focus = max_def(focus, camera_data.min_distance); apply_physical(rt, rt->GetColorTex(), rt->GetDepthTex(), - camera_data->min_distance, camera_data->max_distance, + camera_data.min_distance, camera_data.max_distance, focus, dof_debug_data->focal_length, - camera_data->fov * DEG_TO_RAD_FLOAT, + camera_data.fov * DEG_TO_RAD_FLOAT, dof_debug_data->f_number); } else { float_t fuzzing_range = max_def(dof_debug_data->f2.fuzzing_range, 0.01f); apply_f2(rt, rt->GetColorTex(), rt->GetDepthTex(), - camera_data->min_distance, camera_data->max_distance, - camera_data->fov * DEG_TO_RAD_FLOAT, + camera_data.min_distance, camera_data.max_distance, + camera_data.fov * DEG_TO_RAD_FLOAT, dof_debug_data->f2.focus, dof_debug_data->f2.focus_range, fuzzing_range, dof_debug_data->f2.ratio); } @@ -86,8 +85,8 @@ namespace renderer { float_t fuzzing_range = max_def(dof_pv_data->f2.fuzzing_range, 0.01f); if (dof_pv_data->f2.fuzzing_range >= 0.0099999998) apply_f2(rt, rt->GetColorTex(), rt->GetDepthTex(), - camera_data->min_distance, camera_data->max_distance, - camera_data->fov * DEG_TO_RAD_FLOAT, + camera_data.min_distance, camera_data.max_distance, + camera_data.fov * DEG_TO_RAD_FLOAT, dof_pv_data->f2.focus, dof_pv_data->f2.focus_range, fuzzing_range, dof_pv_data->f2.ratio); enum_or(dof_debug_data->flags, DOF_DEBUG_ENABLE_DOF); diff --git a/src/DivaGL/rob/rob.cpp b/src/DivaGL/rob/rob.cpp index 33c7946..248d216 100644 --- a/src/DivaGL/rob/rob.cpp +++ b/src/DivaGL/rob/rob.cpp @@ -262,7 +262,7 @@ void RobOsage::SetRot(float_t rot_y, float_t rot_z) { skin_param_ptr->rot.z = rot_z * DEG_TO_RAD_FLOAT; } -void rob_chara_item_equip_object::disp(const mat4* mat) { +void rob_chara_item_equip_object::disp(const mat4& mat) { if (obj_info.is_null()) return; @@ -277,7 +277,7 @@ void rob_chara_item_equip_object::disp(const mat4* mat) { disp_manager->entry_obj_by_object_info_object_skin(obj_info, &texture_pattern, &texture_data, alpha, mats, ex_data_bone_mats.data(), 0, mat); - rob_chara_item_equip_mat = mat; + rob_chara_item_equip_mat = &mat; for (ExNodeBlock*& i : node_blocks) i->__vftable->Disp(i); @@ -615,7 +615,7 @@ static void sub_140512C20(rob_chara_item_equip* rob_itm_equip) { int32_t tex_pat_count = (int32_t)rob_itm_equip->texture_pattern.size(); if (tex_pat_count) disp_manager->set_texture_pattern(tex_pat_count, rob_itm_equip->texture_pattern.data()); - disp_manager->entry_obj_by_object_info(&mat, rob_itm_equip->field_D0); + disp_manager->entry_obj_by_object_info(mat, rob_itm_equip->field_D0); if (tex_pat_count) disp_manager->set_texture_pattern(); } @@ -633,6 +633,8 @@ static float_t sub_140512F60(rob_chara_item_equip* rob_itm_equip) { HOOK(void, FASTCALL, rob_chara_item_equip_disp, 0x0000000140512950, rob_chara_item_equip* rob_item_equip, int32_t chara_id) { + extern bool reflect_full; + mdl::obj_reflect_enable = reflect_full; mdl::ObjFlags flags = (mdl::ObjFlags)0; if (chara_reflect) @@ -668,13 +670,13 @@ HOOK(void, FASTCALL, rob_chara_item_equip_disp, 0x0000000140512950, disp_manager.set_texture_color_coefficients(rob_item_equip->texture_color_coefficients); disp_manager.set_wet_param(rob_item_equip->wet); - render_manager->field_31C |= rob_item_equip->npr_flag; + render_manager.field_31C |= rob_item_equip->npr_flag; sub_140512C20(rob_item_equip); rob_chara_age_age_array_disp(chara_id, chara_reflect, rob_item_equip->chara_color); if (rob_item_equip->item_equip_range) for (int32_t i = rob_item_equip->first_item_equip_object; i < rob_item_equip->max_item_equip_object; i++) - rob_item_equip->item_equip_object[i].disp(&rob_item_equip->mat); + rob_item_equip->item_equip_object[i].disp(rob_item_equip->mat); else { for (int32_t i = ITEM_ATAMA; i < ITEM_MAX; i++) { mdl::ObjFlags chara_flags = (mdl::ObjFlags)0; @@ -693,7 +695,7 @@ HOOK(void, FASTCALL, rob_chara_item_equip_disp, 0x0000000140512950, enum_and(flags, ~mdl::OBJ_SHADOW); disp_manager.set_obj_flags((mdl::ObjFlags)(chara_flags | flags | mdl::OBJ_SSS)); - rob_item_equip->item_equip_object[i].disp(&rob_item_equip->mat); + rob_item_equip->item_equip_object[i].disp(rob_item_equip->mat); } } disp_manager.set_texture_color_coefficients(temp_texture_color_coeff); @@ -701,6 +703,8 @@ HOOK(void, FASTCALL, rob_chara_item_equip_disp, 0x0000000140512950, disp_manager.set_chara_color(); disp_manager.set_obj_flags(); disp_manager.set_shadow_type(); + + mdl::obj_reflect_enable = false; } HOOK(void, FASTCALL, rob_chara_set_chara_size, 0x0000000140516810, rob_chara* rob_chr, float_t value) { @@ -956,7 +960,7 @@ void rob_chara_age_age_object::disp(size_t chara_index, static prj::vector* (FASTCALL * rob_chara_age_age_object__get_obj_set_texture)(rob_chara_age_age_object * rob_age_age_obj) = (prj::vector*(FASTCALL*)(rob_chara_age_age_object * rob_age_age_obj))0x000000014045A8E0; - disp_manager->entry_obj_by_obj(&mat4_identity, &obj, + disp_manager->entry_obj_by_obj(mat4_identity, &obj, rob_chara_age_age_object__get_obj_set_texture(this), &obj_vert_buf, &obj_index_buf, 0, 1.0f); } @@ -992,8 +996,8 @@ void rob_chara_arm_adjust_x::reset() { static void rob_chara_age_age_disp(rob_chara_age_age* arr, int32_t chara_id, bool reflect, bool chara_color) { - bool npr = !!render_manager->npr_param; - mat4& view = camera_data->view; + bool npr = !!render_manager.npr_param; + mat4& view = camera_data.view; vec3 v11 = *(vec3*)&view.row2; arr[chara_id * 3 + 0].disp(chara_id, npr, reflect, v11, chara_color); arr[chara_id * 3 + 1].disp(chara_id, npr, reflect, v11, chara_color); diff --git a/src/DivaGL/rob/rob.hpp b/src/DivaGL/rob/rob.hpp index d1a3ac7..eff2c1d 100644 --- a/src/DivaGL/rob/rob.hpp +++ b/src/DivaGL/rob/rob.hpp @@ -1368,7 +1368,7 @@ struct rob_chara_item_equip_object { obj_skin* skin; rob_chara_item_equip* item_equip; - void disp(const mat4* mat); + void disp(const mat4& mat); int32_t get_bone_index(const char* name); bone_node* get_bone_node(int32_t bone_index); bone_node* get_bone_node(const char* name); diff --git a/src/DivaGL/shadow.cpp b/src/DivaGL/shadow.cpp index ba1af5b..04435af 100644 --- a/src/DivaGL/shadow.cpp +++ b/src/DivaGL/shadow.cpp @@ -19,9 +19,9 @@ void Shadow::ctrl() { for (int32_t i = 0; i < 2; i++) shadow_enable[i] = false; - if (render_manager->shadow) { - view_mat[0] = camera_data->view; - view_mat[1] = camera_data->inv_view; + if (render_manager.shadow) { + view_mat[0] = camera_data.view; + view_mat[1] = camera_data.inv_view; light_data& light_chara = light_set_data[LIGHT_SET_MAIN].lights[LIGHT_CHARA]; diff --git a/src/DivaGL/sprite.cpp b/src/DivaGL/sprite.cpp index e6454e1..cd68dbb 100644 --- a/src/DivaGL/sprite.cpp +++ b/src/DivaGL/sprite.cpp @@ -147,11 +147,11 @@ static const GLenum spr_blend_param[6][4] = { }; namespace spr { - void(FASTCALL* put_cross)(const mat4* mat, color4u8 color_x, color4u8 color_y, color4u8 color_z) - = (void(FASTCALL*)(const mat4 * mat, color4u8 color_x, color4u8 color_y, color4u8 color_z))0x00000001404BC920; - void(FASTCALL* put_rgb_cross)(const mat4* mat) = (void(FASTCALL*)(const mat4 * mat))0x00000001404BC8F0; - spr::SprArgs* (FASTCALL* put_sprite)(const spr::SprArgs* args) - = (spr::SprArgs * (FASTCALL*)(const spr::SprArgs * args))0x0000000140640740; + void(FASTCALL* put_cross)(const mat4& mat, color4u8 color_x, color4u8 color_y, color4u8 color_z) + = (void(FASTCALL*)(const mat4 & mat, color4u8 color_x, color4u8 color_y, color4u8 color_z))0x00000001404BC920; + void(FASTCALL* put_rgb_cross)(const mat4& mat) = (void(FASTCALL*)(const mat4 & mat))0x00000001404BC8F0; + spr::SprArgs* (FASTCALL* put_sprite)(const spr::SprArgs& args) + = (spr::SprArgs * (FASTCALL*)(const spr::SprArgs & args))0x0000000140640740; SprArgs::SprArgs() : kind(), attr(), blend(), index(), layer(), prio(), resolution_mode_screen(), resolution_mode_sprite(), texture(), @@ -235,13 +235,13 @@ namespace spr { vec2 proj_sprite_3d_line(vec3 vec, bool offset) { mat4 view; - mat4_transpose(&camera_data->view, &view); + mat4_transpose(&camera_data.view, &view); mat4_transform_point(&view, &vec, &vec); if (fabsf(vec.z) < 1.0e-10f) return 0.0f; - vec2 sc_vec = camera_data->depth * *(vec2*)&vec.x * (1.0f / vec.z); + vec2 sc_vec = camera_data.depth * *(vec2*)&vec.x * (1.0f / vec.z); resolution_struct* res_wind_int = res_window_internal_get(); sc_vec.x = (float_t)res_wind_int->width * 0.5f - sc_vec.x; @@ -274,7 +274,7 @@ namespace spr { args.color = color; args.SetSpriteSize({ p2.x - p1.x, p2.y - p1.y }); enum_or(args.attr, SPR_ATTR_MATRIX); - spr::put_sprite(&args); + spr::put_sprite(args); } void put_sprite_line_list(vec2* points, size_t count, resolution_mode mode, @@ -297,7 +297,7 @@ namespace spr { } args.SetVertexArray(vertex_array.data(), vertex_array.size()); - spr::put_sprite(&args); + spr::put_sprite(args); } void put_sprite_multi(rectangle rect, resolution_mode mode, spr::SprPrio prio, color4u8 color, int32_t layer) { @@ -313,7 +313,7 @@ namespace spr { args.color = color; args.SetSpriteSize(rect.size); enum_or(args.attr, SPR_ATTR_MATRIX); - spr::put_sprite(&args); + spr::put_sprite(args); } void put_sprite_rect(rectangle rect, resolution_mode mode, spr::SprPrio prio, color4u8 color, int32_t layer) { @@ -329,7 +329,7 @@ namespace spr { args.color = color; args.SetSpriteSize(rect.size); enum_or(args.attr, SPR_ATTR_MATRIX); - spr::put_sprite(&args); + spr::put_sprite(args); } void put_sprite_triangles(SpriteVertex* vert, size_t num, resolution_mode mode, @@ -345,7 +345,7 @@ namespace spr { args.id.info = sprite_database_get_spr_by_id(spr_id)->info; enum_or(args.attr, SPR_ATTR_MATRIX); args.SetVertexArray(vert, num); - spr::put_sprite(&args); + spr::put_sprite(args); } SpriteManager::RenderData::RenderData() { @@ -481,7 +481,7 @@ namespace spr { float_t sprite_half_width = (float_t)res_window_get()->width * 0.5f; float_t sprite_half_height = (float_t)res_window_get()->height * 0.5f; - float_t aet_depth = camera_data->aet_depth; + float_t aet_depth = camera_data.aet_depth; float_t aet_depth_1 = 1.0f / aet_depth; float_t v15a = sprite_half_height * aspect[i] * 0.2f * aet_depth_1; @@ -1441,8 +1441,8 @@ void sprite_manager_set_res(double_t aspect, int32_t width, int32_t height) { void sprite_manager_set_view_projection(bool aet_3d) { view_projection_aet = aet_3d - ? camera_data->view_projection_aet_3d - : camera_data->view_projection_aet_2d; + ? camera_data.view_projection_aet_3d + : camera_data.view_projection_aet_2d; } void sprite_manager_free() { diff --git a/src/DivaGL/sprite.hpp b/src/DivaGL/sprite.hpp index b11efaf..4996738 100644 --- a/src/DivaGL/sprite.hpp +++ b/src/DivaGL/sprite.hpp @@ -263,9 +263,9 @@ namespace spr { static_assert(sizeof(spr::SprArgs) == 0xE8, "\"spr::SprArgs\" struct should have a size of 0xE8"); - extern void(FASTCALL* put_cross)(const mat4* mat, color4u8 color_x, color4u8 color_y, color4u8 color_z); - extern void(FASTCALL* put_rgb_cross)(const mat4* mat); - extern spr::SprArgs* (FASTCALL* put_sprite)(const spr::SprArgs* args); + extern void(FASTCALL* put_cross)(const mat4& mat, color4u8 color_x, color4u8 color_y, color4u8 color_z); + extern void(FASTCALL* put_rgb_cross)(const mat4& mat); + extern spr::SprArgs* (FASTCALL* put_sprite)(const spr::SprArgs& args); vec2 proj_sprite_3d_line(vec3 vec, bool offset); diff --git a/src/DivaGL/stage.cpp b/src/DivaGL/stage.cpp index 49f381a..fb0564e 100644 --- a/src/DivaGL/stage.cpp +++ b/src/DivaGL/stage.cpp @@ -4,8 +4,9 @@ */ #include "stage.hpp" +#include "../KKdLib/hash.hpp" #include "../KKdLib/mat.hpp" -#include "../KKdLib/vec.hpp" +#include "pv_game/firstread.hpp" #include "object.hpp" #include "render_context.hpp" #include @@ -80,13 +81,54 @@ static_assert(sizeof(stage) == 0x68, "\"stage\" struct should have a size of 0x6 extern size_t(FASTCALL* stage_data_handler_get_stage_data_count)() = (size_t(FASTCALL*)())0x000000014064AFC0; static bool object_bounding_sphere_check_visibility_shadow(obj_bounding_sphere* sphere, mat4* mat); -static bool object_bounding_sphere_check_visibility_shadow_chara(obj_bounding_sphere* sphere); -static bool object_bounding_sphere_check_visibility_shadow_stage(obj_bounding_sphere* sphere); +static bool object_bounding_sphere_check_visibility_shadow_chara(const obj_bounding_sphere* sphere); +static bool object_bounding_sphere_check_visibility_shadow_stage(const obj_bounding_sphere* sphere); + +bool& chara_reflect = *(bool*)0x00000001411ADAFC; + +HOOK(void, FASTCALL, stage__set, 0x0000000140647710, stage* prev, stage* curr) { + originalstage__set(prev, curr); + + extern bool reflect_full; + extern const firstread* firstread_ptr; + if (reflect_full && firstread_ptr && firstread_ptr->stage_data_array && (!curr || prev != curr) && curr) { + const firstread_stage_data_array* stage_data_array = firstread_ptr->stage_data_array; + + ::stage_data* stage_data = curr->stage_data; + const uint64_t name_hash = hash_utf8_xxh3_64bits(stage_data->name); + const uint32_t num_stage_data = stage_data_array->num_stage_data; + for (uint32_t i = 0; i < num_stage_data; i++) { + if (hash_utf8_xxh3_64bits(stage_data_array->stage_data_array[i].name) != name_hash) + continue; + + const firstread_stage_data* frg_stage_data = &stage_data_array->stage_data_array[i]; + + chara_reflect = false; + render_manager.reflect_type = (stage_data_reflect_type)frg_stage_data->reflect_type; + + if (frg_stage_data->reflect) { + const stage_data_reflect* reflect = frg_stage_data->reflect; + render_manager.pass_sw[rndr::RND_PASSID_REFLECT] = true; + render_manager.reflect_blur_num = reflect->blur_num; + render_manager.reflect_blur_filter = (blur_filter_mode)reflect->blur_filter; + render_manager.reflect = true; + reflect_refract_resolution_mode mode = REFLECT_REFRACT_RESOLUTION_512x512; + if (frg_stage_data->reflect_type != STAGE_DATA_REFLECT_REFLECT_MAP) + mode = reflect->mode; + render_manager.tex_index[0] = mode; + } + break; + } + } +} HOOK(void, FASTCALL, stage__disp, 0x0000000140649560, stage* s) { if (s->state != 6 || !s->stage_display) return; + extern bool reflect_full; + mdl::obj_reflect_enable = reflect_full; + mdl::DispManager& disp_manager = *::disp_manager; mat4 mat; @@ -94,27 +136,27 @@ HOOK(void, FASTCALL, stage__disp, 0x0000000140649560, stage* s) { mat4_transpose(&mat, &mat); if (s->stage_data->object_ground.not_null() && s->ground) - disp_manager.entry_obj_by_object_info(&mat, s->stage_data->object_ground); + disp_manager.entry_obj_by_object_info(mat, s->stage_data->object_ground); if (s->stage_data->object_ring.not_null() && s->ring) - disp_manager.entry_obj_by_object_info(&mat, s->stage_data->object_ring); + disp_manager.entry_obj_by_object_info(mat, s->stage_data->object_ring); if (s->stage_data->object_reflect.not_null()) { disp_manager.set_obj_flags((mdl::ObjFlags)(mdl::OBJ_NO_TRANSLUCENCY | mdl::OBJ_REFLECT)); - disp_manager.entry_obj_by_object_info(&mat, s->stage_data->object_reflect); + disp_manager.entry_obj_by_object_info(mat, s->stage_data->object_reflect); disp_manager.set_obj_flags(); } if (s->stage_data->object_refract.not_null()) { disp_manager.set_obj_flags((mdl::ObjFlags)(mdl::OBJ_NO_TRANSLUCENCY | mdl::OBJ_REFRACT)); - disp_manager.entry_obj_by_object_info(&mat, s->stage_data->object_refract); + disp_manager.entry_obj_by_object_info(mat, s->stage_data->object_refract); disp_manager.set_obj_flags(); } if (s->stage_data->object_sky.not_null() && s->sky) { mat4 t = s->mat; mat4_mul(&mat, &t, &t); - disp_manager.entry_obj_by_object_info(&t, s->stage_data->object_sky); + disp_manager.entry_obj_by_object_info(t, s->stage_data->object_sky); } if (s->stage_data->lens_flare_texture != -1 && s->lens_flare) { @@ -131,14 +173,16 @@ HOOK(void, FASTCALL, stage__disp, 0x0000000140649560, stage* s) { rend->lens_shaft_inv_scale = s->stage_data->lens_shaft_inv_scale; } } + + mdl::obj_reflect_enable = false; } -static void stage__disp_shadow_object(object_info object, mat4* mat) { +static void stage__disp_shadow_object(object_info object, const mat4& mat) { mdl::DispManager& disp_manager = *::disp_manager; for (int32_t i = SHADOW_CHARA; i < SHADOW_MAX; i++) { disp_manager.set_shadow_type((shadow_type_enum)i); - disp_manager.set_culling_finc(i == SHADOW_CHARA + disp_manager.set_culling_func(i == SHADOW_CHARA ? object_bounding_sphere_check_visibility_shadow_chara : object_bounding_sphere_check_visibility_shadow_stage); disp_manager.set_obj_flags((mdl::ObjFlags)(mdl::OBJ_NO_TRANSLUCENCY | mdl::OBJ_SHADOW_OBJECT)); @@ -146,7 +190,7 @@ static void stage__disp_shadow_object(object_info object, mat4* mat) { } disp_manager.set_obj_flags(); - disp_manager.set_culling_finc(); + disp_manager.set_culling_func(); disp_manager.set_shadow_type(); } @@ -159,17 +203,18 @@ HOOK(void, FASTCALL, stage__disp_shadow, 0x00000001406497C0, stage* s) { mat4_rotate_y(s->rot_y, &mat); mat4_transpose(&mat, &mat); if (s->stage_data->object_shadow.not_null()) - stage__disp_shadow_object(s->stage_data->object_shadow, &mat); + stage__disp_shadow_object(s->stage_data->object_shadow, mat); } void stage_patch() { + INSTALL_HOOK(stage__set); INSTALL_HOOK(stage__disp); INSTALL_HOOK(stage__disp_shadow); } -static bool object_bounding_sphere_check_visibility_shadow(obj_bounding_sphere* sphere, mat4* mat) { +static bool object_bounding_sphere_check_visibility_shadow(const obj_bounding_sphere* sphere, mat4* mat) { mat4 view; - mat4_transpose(&camera_data->view, &view); + mat4_transpose(&camera_data.view, &view); vec3 center; mat4_transform_point(mat, &sphere->center, ¢er); @@ -188,14 +233,14 @@ static bool object_bounding_sphere_check_visibility_shadow(obj_bounding_sphere* return true; } -static bool object_bounding_sphere_check_visibility_shadow_chara(obj_bounding_sphere* sphere) { +static bool object_bounding_sphere_check_visibility_shadow_chara(const obj_bounding_sphere* sphere) { mat4 mat; Shadow* shad = shadow_ptr_get(); mat4_look_at(&shad->view_point[0], &shad->interest[0], &mat); return object_bounding_sphere_check_visibility_shadow(sphere, &mat); } -static bool object_bounding_sphere_check_visibility_shadow_stage(obj_bounding_sphere* sphere) { +static bool object_bounding_sphere_check_visibility_shadow_stage(const obj_bounding_sphere* sphere) { mat4 mat; Shadow* shad = shadow_ptr_get(); mat4_look_at(&shad->view_point[1], &shad->interest[1], &mat); diff --git a/src/DivaGL/types.hpp b/src/DivaGL/types.hpp index 2b08417..f9a704c 100644 --- a/src/DivaGL/types.hpp +++ b/src/DivaGL/types.hpp @@ -116,6 +116,11 @@ namespace prj { template class ptr_base { + public: + T* get() const { + return ptr; + } + private: T* ptr; ref_count* ref; @@ -127,6 +132,61 @@ namespace prj { template class shared_ptr : public ptr_base { public: + T* operator->() const { + return this->get(); + } + + operator bool() const { + return !!this->get(); + } + }; + + struct stack_allocator { + size_t size; + uint8_t* begin; + uint8_t* end; + uint8_t* capacity_end; + + inline void* allocate(size_t size) { + static void* (*prj__stack_allocator__allocate)(prj::stack_allocator * This, size_t size) + = (void* (*)(prj::stack_allocator * This, size_t size))0x000000014009B110; + return prj__stack_allocator__allocate(this, size); + } + + template + inline T* allocate() { + return new((T*)allocate(sizeof(T))) T; + } + + template + inline T* allocate(size_t size) { + if (!size) + return 0; + + T* arr = (T*)allocate(sizeof(T) * size); + for (size_t i = 0; i < size; i++) + new(&arr[i]) T(); + return arr; + } + + template + inline T* allocate(const T* src) { + if (!src) + return 0; + + return new((T*)allocate(sizeof(T))) T(*src); + } + + template + inline T* allocate(const T* src, size_t size) { + if (!src || !size) + return 0; + + T* dst = (T*)allocate(sizeof(T) * size); + for (size_t i = 0; i < size; i++) + new(&dst[i]) T(src[i]); + return dst; + } }; template