From 9ae9886c7bd7a6ec8f538ac5eca643a9bc38aa47 Mon Sep 17 00:00:00 2001 From: korenkonder Date: Fri, 14 Nov 2025 02:03:57 +0300 Subject: [PATCH] Reworked Vertex Array Cache --- src/CRE/auth_3d.cpp | 80 +++++++ src/CRE/mdl/disp_manager.cpp | 432 +++++++---------------------------- src/CRE/mdl/disp_manager.hpp | 22 +- src/CRE/mdl/draw_object.cpp | 4 +- src/CRE/object.cpp | 65 +++++- src/CRE/render_manager.cpp | 1 - src/CRE/rob/ex_block.cpp | 24 ++ src/CRE/rob/rob.cpp | 9 + 8 files changed, 268 insertions(+), 369 deletions(-) diff --git a/src/CRE/auth_3d.cpp b/src/CRE/auth_3d.cpp index 62a97831..58e04aa2 100644 --- a/src/CRE/auth_3d.cpp +++ b/src/CRE/auth_3d.cpp @@ -6677,6 +6677,86 @@ static void auth_3d_object_load(auth_3d* auth, auth_3d_object* o, o->object_info = obj_db->get_object_info(o->uid_name.c_str()); o->object_hash = hash_string_murmurhash(o->uid_name); + + if (!of->morph.size() || !o->morph.curve || o->morph.curve->curve.keys_vec.size() < 2) + return; + + auth_3d_object_curve* oc = &o->morph; + + float_t min_value = FLT_MAX; + float_t max_value = -FLT_MAX; + + float_t first_frame = oc->curve->curve.keys_vec.front().frame; + float_t last_frame = oc->curve->curve.keys_vec.back().frame; + for (float_t i = first_frame; i <= last_frame; i += 1.0f) { + oc->interpolate(i); + min_value = fminf(min_value, oc->value); + max_value = fmaxf(max_value, oc->value); + } + oc->interpolate(0.0f); + + int32_t min = (int32_t)prj::floorf(min_value); + int32_t max = (int32_t)prj::ceilf(max_value); + if (min >= max) + return; + + const char* uid_name = o->uid_name.c_str(); + int32_t uid_name_length = (int32_t)o->uid_name.size(); + + char buf[0x80]; + for (int32_t i = min; i < max; i++) { + sprintf_s(buf, sizeof(buf), "%.*s%03d", uid_name_length - 3, uid_name, i + 1); + object_info morph_obj_info = obj_db->get_object_info(buf); + if (morph_obj_info.is_null()) + morph_obj_info = o->object_info; + + sprintf_s(buf, sizeof(buf), "%.*s%03d", uid_name_length - 3, uid_name, i); + object_info obj_info = obj_db->get_object_info(buf); + + ::obj* obj = objset_info_storage_get_obj(obj_info); + if (!obj) + continue; + + obj_mesh_vertex_buffer* obj_vert_buf = objset_info_storage_get_obj_mesh_vertex_buffer(obj_info); + obj_mesh_index_buffer* obj_index_buf = objset_info_storage_get_obj_mesh_index_buffer(obj_info); + + obj_mesh_vertex_buffer* obj_morph_vert_buf = 0; + if (morph_obj_info.set_id != -1) + obj_morph_vert_buf = objset_info_storage_get_obj_mesh_vertex_buffer(morph_obj_info); + + for (int32_t i = 0; i < obj->num_mesh; i++) { + const obj_mesh* mesh = &obj->mesh_array[i]; + for (int32_t j = 0; j < mesh->num_submesh; j++) { + const obj_sub_mesh* sub_mesh = &mesh->submesh_array[j]; + if (sub_mesh->attrib.m.cloth) + continue; + + obj_material_data* material = &obj->material_array[sub_mesh->material_index]; + + 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)) + rctx_ptr->disp_manager->add_vertex_array(mesh, sub_mesh, material, vertex_buffer, + vertex_buffer_offset, index_buffer, morph_vertex_buffer, morph_vertex_buffer_offset); + } + } + } } static void auth_3d_object_store(auth_3d* auth, auth_3d_object* o, diff --git a/src/CRE/mdl/disp_manager.cpp b/src/CRE/mdl/disp_manager.cpp index c1b383d7..1bad6478 100644 --- a/src/CRE/mdl/disp_manager.cpp +++ b/src/CRE/mdl/disp_manager.cpp @@ -34,9 +34,6 @@ static const GLuint MORPH_TEXCOORD0_INDEX = 13; static const GLuint MORPH_TEXCOORD1_INDEX = 14; static const GLuint BONE_INDEX_INDEX = 15; -static void object_data_get_vertex_attrib_buffer_bindings(const mdl::ObjSubMeshArgs* args, - int32_t texcoord_array[2], GLuint vertex_attrib_buffer_binding[16]); - static void sub_140436760(const cam_data& cam); material_list_struct::material_list_struct() : blend_color(), has_blend_color(), emission(), has_emission() { @@ -354,7 +351,8 @@ namespace mdl { args->func = func; args->func_data = func_data; - disp_manager->add_vertex_array(args); + disp_manager->add_vertex_array(mesh, sub_mesh, material, vertex_buffer, + vertex_buffer_offset, index_buffer, morph_vertex_buffer, morph_vertex_buffer_offset); } void ObjData::init_translucent(const mat4& mat, const ObjTranslucentArgs& translucent) { @@ -371,31 +369,6 @@ namespace mdl { } EtcObjManager::EtcObjManager() : vao(), vbo_vertex_count(), ebo_index_count() { - vbo_vertex_count = 256; - ebo_index_count = 256; - - static const GLsizei buffer_size = sizeof(etc_obj_vertex_data); - - vbo.Create(gl_state, buffer_size * vbo_vertex_count); - ebo.Create(gl_state, sizeof(uint32_t) * ebo_index_count); - - glGenVertexArrays(1, &vao); - gl_state.bind_vertex_array(vao); - gl_state.bind_array_buffer(vbo, true); - gl_state.bind_element_array_buffer(ebo, true); - - set_default_vertex_attrib(); - - glEnableVertexAttribArray(POSITION_INDEX); - glVertexAttribPointer(POSITION_INDEX, 3, GL_FLOAT, GL_FALSE, buffer_size, - (void*)offsetof(etc_obj_vertex_data, position)); - glEnableVertexAttribArray(NORMAL_INDEX); - glVertexAttribPointer(NORMAL_INDEX, 3, GL_FLOAT, GL_FALSE, buffer_size, - (void*)offsetof(etc_obj_vertex_data, normal)); - - gl_state.bind_array_buffer(0); - gl_state.bind_vertex_array(0); - gl_state.bind_element_array_buffer(0); } @@ -1017,13 +990,23 @@ namespace mdl { static const GLsizei buffer_size = sizeof(etc_obj_vertex_data); if (vbo_vertex_count < vertex_buffer.size() / buffer_size) { + if (!vbo_vertex_count) + vbo_vertex_count = 256; + while (vbo_vertex_count < vertex_buffer.size() / buffer_size) vbo_vertex_count *= 2; + if (vao) { + glDeleteVertexArrays(1, &vao); + vao = 0; + } + vbo.Recreate(gl_state, buffer_size * vbo_vertex_count); - gl_state.bind_vertex_array(vao); + glGenVertexArrays(1, &vao); + gl_state.bind_vertex_array(vao, true); gl_state.bind_array_buffer(vbo, true); + gl_state.bind_element_array_buffer(ebo, true); set_default_vertex_attrib(); @@ -1036,11 +1019,15 @@ namespace mdl { gl_state.bind_array_buffer(0); gl_state.bind_vertex_array(0); + gl_state.bind_element_array_buffer(0); } vbo.WriteMemory(gl_state, 0, vertex_buffer.size(), vertex_buffer.data()); if (ebo_index_count < index_buffer.size()) { + if (!ebo_index_count) + ebo_index_count = 256; + while (ebo_index_count < index_buffer.size()) ebo_index_count *= 2; @@ -1059,24 +1046,6 @@ namespace mdl { gl_state.bind_element_array_buffer(0); } - void DispManager::vertex_array::reset_vertex_attrib() { - alive_time = 0; - vertex_buffer = 0; - vertex_buffer_offset = 0; - morph_vertex_buffer = 0; - morph_vertex_buffer_offset = 0; - - gl_state.bind_vertex_array(vertex_array, true); - for (int32_t i = 0; i < 16; i++) - if (vertex_attrib_array[i]) { - glDisableVertexAttribArray(i); - vertex_attrib_array[i] = false; - } - gl_state.bind_array_buffer(0, true); - gl_state.bind_element_array_buffer(0, true); - gl_state.bind_vertex_array(0); - } - DispManager::DispManager() : obj_flags(), shadow_type(), field_8(), field_C(), culling(), show_alpha_center(), show_mat_center(), texture_pattern_count(), texture_pattern_array(), wet_param(), texture_transform_count(), @@ -1103,16 +1072,11 @@ namespace mdl { free_def(buff); } - void DispManager::add_vertex_array(ObjSubMeshArgs* args) { - const obj_mesh* mesh = args->mesh; - const obj_sub_mesh* sub_mesh = args->sub_mesh; - const obj_material_data* material = args->material; - - GLuint vertex_buffer = args->vertex_buffer; - size_t vertex_buffer_offset = args->vertex_buffer_offset; - GLuint morph_vertex_buffer = args->morph_vertex_buffer; - size_t morph_vertex_buffer_offset = args->morph_vertex_buffer_offset; - GLuint index_buffer = args->index_buffer; + void DispManager::add_vertex_array(const obj_mesh* mesh, const obj_sub_mesh* sub_mesh, + const obj_material_data* material, GLuint vertex_buffer, size_t vertex_buffer_offset, + GLuint index_buffer, GLuint morph_vertex_buffer, size_t morph_vertex_buffer_offset) { + if (!vertex_buffer || !index_buffer) + return; int32_t texcoord_array[2] = { -1, -1 }; int32_t color_tex_index = 0; @@ -1131,96 +1095,52 @@ namespace mdl { color_tex_index++; } - GLuint vertex_attrib_buffer_binding[16] = {}; - object_data_get_vertex_attrib_buffer_bindings(args, - texcoord_array, vertex_attrib_buffer_binding); - uint32_t compression = mesh->attrib.m.compression; GLsizei size_vertex = (GLsizei)mesh->size_vertex; obj_vertex_format vertex_format = mesh->vertex_format; - DispManager::vertex_array* vertex_array = 0; for (DispManager::vertex_array& i : vertex_array_cache) - if (i.alive_time >= 0 && i.vertex_buffer == vertex_buffer + if (i.vertex_buffer == vertex_buffer && i.vertex_buffer_offset == vertex_buffer_offset && i.morph_vertex_buffer == morph_vertex_buffer && i.morph_vertex_buffer_offset == morph_vertex_buffer_offset && i.index_buffer == index_buffer && i.vertex_format == vertex_format && i.size_vertex == size_vertex && i.compression == compression - && !memcmp(i.vertex_attrib_buffer_binding, - vertex_attrib_buffer_binding, sizeof(vertex_attrib_buffer_binding)) && !memcmp(i.texcoord_array, texcoord_array, sizeof(texcoord_array))) - if (i.vertex_array) { - i.alive_time = 60; - return; - } - else { - vertex_array = &i; - break; - } + return; - if (!vertex_array) - for (DispManager::vertex_array& i : vertex_array_cache) - if (i.alive_time <= 0) { - vertex_array = &i; - break; - } + vertex_array_cache.push_back({}); + DispManager::vertex_array* vertex_array = &vertex_array_cache.back(); - if (!vertex_array) { - vertex_array_cache.push_back({}); - vertex_array = &vertex_array_cache.back(); - } - - bool new_vertex_array = false; - if (!vertex_array->vertex_array) { - glGenVertexArrays(1, &vertex_array->vertex_array); - - gl_state.bind_vertex_array(vertex_array->vertex_array, true); - set_default_vertex_attrib(); - new_vertex_array = true; - } + glGenVertexArrays(1, &vertex_array->vertex_array); vertex_array->vertex_buffer = vertex_buffer; vertex_array->vertex_buffer_offset = vertex_buffer_offset; vertex_array->morph_vertex_buffer = morph_vertex_buffer; vertex_array->morph_vertex_buffer_offset = morph_vertex_buffer_offset; vertex_array->index_buffer = index_buffer; - vertex_array->alive_time = 60; vertex_array->vertex_format = vertex_format; vertex_array->size_vertex = size_vertex; vertex_array->compression = compression; memcpy(&vertex_array->texcoord_array, texcoord_array, sizeof(texcoord_array)); - memcpy(&vertex_array->vertex_attrib_buffer_binding, - vertex_attrib_buffer_binding, sizeof(vertex_attrib_buffer_binding)); - if (!new_vertex_array) - gl_state.bind_vertex_array(vertex_array->vertex_array, true); + gl_state.bind_vertex_array(vertex_array->vertex_array, true); + set_default_vertex_attrib(); + gl_state.bind_array_buffer(vertex_buffer, true); if (index_buffer) gl_state.bind_element_array_buffer(index_buffer, true); size_t offset = vertex_buffer_offset; if (vertex_format & OBJ_VERTEX_POSITION) { - if (!vertex_array->vertex_attrib_array[POSITION_INDEX]) { - glEnableVertexAttribArray(POSITION_INDEX); - vertex_array->vertex_attrib_array[POSITION_INDEX] = true; - } - + glEnableVertexAttribArray(POSITION_INDEX); glVertexAttribPointer(POSITION_INDEX, 3, GL_FLOAT, GL_FALSE, size_vertex, (void*)offset); offset += 12; } - else if (vertex_array->vertex_attrib_array[POSITION_INDEX]) { - glDisableVertexAttribArray(POSITION_INDEX); - vertex_array->vertex_attrib_array[POSITION_INDEX] = false; - } if (vertex_format & OBJ_VERTEX_NORMAL) { - if (!vertex_array->vertex_attrib_array[NORMAL_INDEX]) { - glEnableVertexAttribArray(NORMAL_INDEX); - vertex_array->vertex_attrib_array[NORMAL_INDEX] = true; - } - + glEnableVertexAttribArray(NORMAL_INDEX); switch (compression) { case 0: default: @@ -1240,17 +1160,9 @@ namespace mdl { break; } } - else if (vertex_array->vertex_attrib_array[NORMAL_INDEX]) { - glDisableVertexAttribArray(NORMAL_INDEX); - vertex_array->vertex_attrib_array[NORMAL_INDEX] = false; - } if (vertex_format & OBJ_VERTEX_TANGENT) { - if (!vertex_array->vertex_attrib_array[TANGENT_INDEX]) { - glEnableVertexAttribArray(TANGENT_INDEX); - vertex_array->vertex_attrib_array[TANGENT_INDEX] = true; - } - + glEnableVertexAttribArray(TANGENT_INDEX); switch (compression) { case 0: default: @@ -1270,30 +1182,17 @@ namespace mdl { break; } } - else if (vertex_array->vertex_attrib_array[TANGENT_INDEX]) { - glDisableVertexAttribArray(TANGENT_INDEX); - vertex_array->vertex_attrib_array[TANGENT_INDEX] = false; - } if (!compression && (vertex_format & OBJ_VERTEX_BINORMAL)) offset += 12; for (int32_t i = 0; i < 2; i++) { int32_t texcoord_index = texcoord_array[i]; - if (texcoord_index < 0) { - if (vertex_array->vertex_attrib_array[TEXCOORD0_INDEX + i]) { - glDisableVertexAttribArray(TEXCOORD0_INDEX + i); - vertex_array->vertex_attrib_array[TEXCOORD0_INDEX + i] = false; - } + if (texcoord_index < 0) continue; - } if (vertex_format & (OBJ_VERTEX_TEXCOORD0 << texcoord_index)) { - if (!vertex_array->vertex_attrib_array[TEXCOORD0_INDEX + i]) { - glEnableVertexAttribArray(TEXCOORD0_INDEX + i); - vertex_array->vertex_attrib_array[TEXCOORD0_INDEX + i] = true; - } - + glEnableVertexAttribArray(TEXCOORD0_INDEX + i); switch (compression) { case 0: default: @@ -1335,11 +1234,7 @@ namespace mdl { } if (vertex_format & OBJ_VERTEX_COLOR0) { - if (!vertex_array->vertex_attrib_array[COLOR0_INDEX]) { - glEnableVertexAttribArray(COLOR0_INDEX); - vertex_array->vertex_attrib_array[COLOR0_INDEX] = true; - } - + glEnableVertexAttribArray(COLOR0_INDEX); switch (compression) { case 0: default: @@ -1355,20 +1250,12 @@ namespace mdl { break; } } - else if (vertex_array->vertex_attrib_array[COLOR0_INDEX]) { - glDisableVertexAttribArray(COLOR0_INDEX); - vertex_array->vertex_attrib_array[COLOR0_INDEX] = false; - } if (!compression && (vertex_format & OBJ_VERTEX_COLOR1)) offset += 16; if (vertex_format & OBJ_VERTEX_BONE_DATA) { - if (!vertex_array->vertex_attrib_array[BONE_WEIGHT_INDEX]) { - glEnableVertexAttribArray(BONE_WEIGHT_INDEX); - vertex_array->vertex_attrib_array[BONE_WEIGHT_INDEX] = true; - } - + glEnableVertexAttribArray(BONE_WEIGHT_INDEX); switch (compression) { case 0: default: @@ -1388,11 +1275,7 @@ namespace mdl { break; } - if (!vertex_array->vertex_attrib_array[BONE_INDEX_INDEX]) { - glEnableVertexAttribArray(BONE_INDEX_INDEX); - vertex_array->vertex_attrib_array[BONE_INDEX_INDEX] = true; - } - + glEnableVertexAttribArray(BONE_INDEX_INDEX); switch (compression) { case 0: case 1: @@ -1408,58 +1291,27 @@ namespace mdl { break; } } - else { - if (vertex_array->vertex_attrib_array[BONE_WEIGHT_INDEX]) { - glDisableVertexAttribArray(BONE_WEIGHT_INDEX); - vertex_array->vertex_attrib_array[BONE_WEIGHT_INDEX] = false; - } - - if (vertex_array->vertex_attrib_array[BONE_INDEX_INDEX]) { - glDisableVertexAttribArray(BONE_INDEX_INDEX); - vertex_array->vertex_attrib_array[BONE_INDEX_INDEX] = false; - } - } if (!compression && (vertex_format & OBJ_VERTEX_UNKNOWN)) { - if (!vertex_array->vertex_attrib_array[UNKNOWN_INDEX]) { - glEnableVertexAttribArray(UNKNOWN_INDEX); - vertex_array->vertex_attrib_array[UNKNOWN_INDEX] = true; - } - + glEnableVertexAttribArray(UNKNOWN_INDEX); glVertexAttribPointer(UNKNOWN_INDEX, 4, GL_FLOAT, GL_FALSE, size_vertex, (void*)offset); offset += 16; } - else if (vertex_array->vertex_attrib_array[UNKNOWN_INDEX]) { - glDisableVertexAttribArray(UNKNOWN_INDEX); - vertex_array->vertex_attrib_array[UNKNOWN_INDEX] = false; - } if (morph_vertex_buffer) { gl_state.bind_array_buffer(morph_vertex_buffer, true); size_t offset = morph_vertex_buffer_offset; if (vertex_format & OBJ_VERTEX_POSITION) { - if (!vertex_array->vertex_attrib_array[MORPH_POSITION_INDEX]) { - glEnableVertexAttribArray(MORPH_POSITION_INDEX); - vertex_array->vertex_attrib_array[MORPH_POSITION_INDEX] = true; - } - + glEnableVertexAttribArray(MORPH_POSITION_INDEX); glVertexAttribPointer(MORPH_POSITION_INDEX, 3, GL_FLOAT, GL_FALSE, size_vertex, (void*)offset); offset += 12; } - else if (vertex_array->vertex_attrib_array[MORPH_POSITION_INDEX]) { - glDisableVertexAttribArray(MORPH_POSITION_INDEX); - vertex_array->vertex_attrib_array[MORPH_POSITION_INDEX] = false; - } if (vertex_format & OBJ_VERTEX_NORMAL) { - if (!vertex_array->vertex_attrib_array[MORPH_NORMAL_INDEX]) { - glEnableVertexAttribArray(MORPH_NORMAL_INDEX); - vertex_array->vertex_attrib_array[MORPH_NORMAL_INDEX] = true; - } - + glEnableVertexAttribArray(MORPH_NORMAL_INDEX); switch (compression) { case 0: default: @@ -1474,22 +1326,14 @@ namespace mdl { break; case 2: glVertexAttribPointer(MORPH_NORMAL_INDEX, - 4, GL_INT_2_10_10_10_REV, GL_TRUE, size_vertex, (void*)offset); + 3, GL_INT_2_10_10_10_REV, GL_TRUE, size_vertex, (void*)offset); offset += 4; break; } } - else if (vertex_array->vertex_attrib_array[MORPH_NORMAL_INDEX]) { - glDisableVertexAttribArray(MORPH_NORMAL_INDEX); - vertex_array->vertex_attrib_array[MORPH_NORMAL_INDEX] = false; - } if (vertex_format & OBJ_VERTEX_TANGENT) { - if (!vertex_array->vertex_attrib_array[MORPH_TANGENT_INDEX]) { - glEnableVertexAttribArray(MORPH_TANGENT_INDEX); - vertex_array->vertex_attrib_array[MORPH_TANGENT_INDEX] = true; - } - + glEnableVertexAttribArray(MORPH_TANGENT_INDEX); switch (compression) { case 0: default: @@ -1509,20 +1353,12 @@ namespace mdl { break; } } - else if (vertex_array->vertex_attrib_array[MORPH_TANGENT_INDEX]) { - glDisableVertexAttribArray(MORPH_TANGENT_INDEX); - vertex_array->vertex_attrib_array[MORPH_TANGENT_INDEX] = false; - } if (!compression && (vertex_format & OBJ_VERTEX_BINORMAL)) offset += 12; if (vertex_format & OBJ_VERTEX_TEXCOORD0) { - if (!vertex_array->vertex_attrib_array[MORPH_TEXCOORD0_INDEX]) { - glEnableVertexAttribArray(MORPH_TEXCOORD0_INDEX); - vertex_array->vertex_attrib_array[MORPH_TEXCOORD0_INDEX] = true; - } - + glEnableVertexAttribArray(MORPH_TEXCOORD0_INDEX); switch (compression) { case 0: default: @@ -1538,17 +1374,9 @@ namespace mdl { break; } } - else if (vertex_array->vertex_attrib_array[MORPH_TEXCOORD0_INDEX]) { - glDisableVertexAttribArray(MORPH_TEXCOORD0_INDEX); - vertex_array->vertex_attrib_array[MORPH_TEXCOORD0_INDEX] = false; - } if (vertex_format & OBJ_VERTEX_TEXCOORD1) { - if (!vertex_array->vertex_attrib_array[MORPH_TEXCOORD1_INDEX]) { - glEnableVertexAttribArray(MORPH_TEXCOORD1_INDEX); - vertex_array->vertex_attrib_array[MORPH_TEXCOORD1_INDEX] = true; - } - + glEnableVertexAttribArray(MORPH_TEXCOORD1_INDEX); switch (compression) { case 0: default: @@ -1564,10 +1392,6 @@ namespace mdl { break; } } - else if (vertex_array->vertex_attrib_array[MORPH_TEXCOORD1_INDEX]) { - glDisableVertexAttribArray(MORPH_TEXCOORD1_INDEX); - vertex_array->vertex_attrib_array[MORPH_TEXCOORD1_INDEX] = false; - } switch (compression) { case 0: @@ -1587,11 +1411,7 @@ namespace mdl { } if (vertex_format & OBJ_VERTEX_COLOR0) { - if (!vertex_array->vertex_attrib_array[MORPH_COLOR_INDEX]) { - glEnableVertexAttribArray(MORPH_COLOR_INDEX); - vertex_array->vertex_attrib_array[MORPH_COLOR_INDEX] = true; - } - + glEnableVertexAttribArray(MORPH_COLOR_INDEX); switch (compression) { case 0: default: @@ -1607,10 +1427,6 @@ namespace mdl { break; } } - else if (vertex_array->vertex_attrib_array[MORPH_COLOR_INDEX]) { - glDisableVertexAttribArray(MORPH_COLOR_INDEX); - vertex_array->vertex_attrib_array[MORPH_COLOR_INDEX] = false; - } switch (compression) { case 0: @@ -1634,37 +1450,6 @@ namespace mdl { break; } } - else { - if (vertex_array->vertex_attrib_array[MORPH_POSITION_INDEX]) { - glDisableVertexAttribArray(MORPH_POSITION_INDEX); - vertex_array->vertex_attrib_array[MORPH_POSITION_INDEX] = false; - } - - if (vertex_array->vertex_attrib_array[MORPH_NORMAL_INDEX]) { - glDisableVertexAttribArray(MORPH_NORMAL_INDEX); - vertex_array->vertex_attrib_array[MORPH_NORMAL_INDEX] = false; - } - - if (vertex_array->vertex_attrib_array[MORPH_TANGENT_INDEX]) { - glDisableVertexAttribArray(MORPH_TANGENT_INDEX); - vertex_array->vertex_attrib_array[MORPH_TANGENT_INDEX] = false; - } - - if (vertex_array->vertex_attrib_array[MORPH_TEXCOORD0_INDEX]) { - glDisableVertexAttribArray(MORPH_TEXCOORD0_INDEX); - vertex_array->vertex_attrib_array[MORPH_TEXCOORD0_INDEX] = false; - } - - if (vertex_array->vertex_attrib_array[MORPH_TEXCOORD1_INDEX]) { - glDisableVertexAttribArray(MORPH_TEXCOORD1_INDEX); - vertex_array->vertex_attrib_array[MORPH_TEXCOORD1_INDEX] = false; - } - - if (vertex_array->vertex_attrib_array[MORPH_COLOR_INDEX]) { - glDisableVertexAttribArray(MORPH_COLOR_INDEX); - vertex_array->vertex_attrib_array[MORPH_COLOR_INDEX] = false; - } - } gl_state.bind_array_buffer(0); gl_state.bind_vertex_array(0); @@ -1866,27 +1651,6 @@ namespace mdl { } } - void DispManager::check_index_buffer(GLuint buffer) { - for (DispManager::vertex_array& i : vertex_array_cache) - if (i.alive_time > 0 && i.index_buffer == buffer) - i.reset_vertex_attrib(); - } - - void DispManager::check_vertex_arrays() { - for (DispManager::vertex_array& i : vertex_array_cache) - if (i.alive_time > 0 && --i.alive_time <= 0) { - i.vertex_buffer = 0; - i.morph_vertex_buffer = 0; - } - } - - void DispManager::check_vertex_buffer(GLuint buffer) { - for (DispManager::vertex_array& i : vertex_array_cache) - if (i.alive_time > 0 - && (i.vertex_buffer == buffer || i.morph_vertex_buffer == buffer)) - i.reset_vertex_attrib(); - } - void DispManager::draw(render_data_context& rend_data_ctx, ObjType type, const cam_data& cam, int32_t depth_mask, bool reflect_texture_mask, int32_t alpha) { if (type < 0 || type >= OBJ_TYPE_MAX || get_obj_count(type) < 1) @@ -3151,16 +2915,11 @@ namespace mdl { } } - GLuint DispManager::get_vertex_array(const ObjSubMeshArgs* args) { - const obj_mesh* mesh = args->mesh; - const obj_sub_mesh* sub_mesh = args->sub_mesh; - const obj_material_data* material = args->material; - - GLuint vertex_buffer = args->vertex_buffer; - size_t vertex_buffer_offset = args->vertex_buffer_offset; - GLuint morph_vertex_buffer = args->morph_vertex_buffer; - size_t morph_vertex_buffer_offset = args->morph_vertex_buffer_offset; - GLuint index_buffer = args->index_buffer; + GLuint DispManager::get_vertex_array(const obj_mesh* mesh, const obj_sub_mesh* sub_mesh, + const obj_material_data* material, GLuint vertex_buffer, size_t vertex_buffer_offset, + GLuint index_buffer, GLuint morph_vertex_buffer, size_t morph_vertex_buffer_offset) { + if (!vertex_buffer || !index_buffer) + return 0; int32_t texcoord_array[2] = { -1, -1 }; int32_t color_tex_index = 0; @@ -3179,23 +2938,17 @@ namespace mdl { color_tex_index++; } - GLuint vertex_attrib_buffer_binding[16] = {}; - object_data_get_vertex_attrib_buffer_bindings(args, - texcoord_array, vertex_attrib_buffer_binding); - uint32_t compression = mesh->attrib.m.compression; GLsizei size_vertex = (GLsizei)mesh->size_vertex; obj_vertex_format vertex_format = mesh->vertex_format; for (DispManager::vertex_array& i : vertex_array_cache) - if (i.alive_time > 0 && i.vertex_buffer == vertex_buffer + if (i.vertex_buffer == vertex_buffer && i.vertex_buffer_offset == vertex_buffer_offset && i.morph_vertex_buffer == morph_vertex_buffer && i.morph_vertex_buffer_offset == morph_vertex_buffer_offset && i.index_buffer == index_buffer && i.vertex_format == vertex_format && i.size_vertex == size_vertex && i.compression == compression - && !memcmp(i.vertex_attrib_buffer_binding, - vertex_attrib_buffer_binding, sizeof(vertex_attrib_buffer_binding)) && !memcmp(i.texcoord_array, texcoord_array, sizeof(texcoord_array))) return i.vertex_array; return 0; @@ -3217,7 +2970,7 @@ namespace mdl { object = morph.object; } - void DispManager::get_obj_center(const mat4& mat, const mdl::ObjSubMeshArgs* args, vec3& center) { + void DispManager::get_obj_center(const mat4& mat, const ObjSubMeshArgs* args, vec3& center) { const vec3 bounding_sphere_center = args->sub_mesh->bounding_sphere.center; if (args->mat_count <= 0 || !args->sub_mesh->num_bone_index) { mat4_transform_point(&mat, &bounding_sphere_center, ¢er); @@ -3403,6 +3156,32 @@ namespace mdl { buffer_reset(); } + void DispManager::remove_index_buffer(GLuint buffer) { + auto i_begin = vertex_array_cache.begin(); + auto i_end = vertex_array_cache.end(); + for (auto i = i_begin; i != i_end;) + if (i->index_buffer == buffer) { + glDeleteVertexArrays(1, &i->vertex_array); + i = vertex_array_cache.erase(i); + i_end = vertex_array_cache.end(); + } + else + i++; + } + + void DispManager::remove_vertex_buffer(GLuint buffer) { + auto i_begin = vertex_array_cache.begin(); + auto i_end = vertex_array_cache.end(); + for (auto i = i_begin; i != i_end;) + if (i->vertex_buffer == buffer || i->morph_vertex_buffer == buffer) { + glDeleteVertexArrays(1, &i->vertex_array); + i = vertex_array_cache.erase(i); + i_end = vertex_array_cache.end(); + } + else + i++; + } + void DispManager::set_chara_color(bool value) { chara_color = value; } @@ -3938,59 +3717,6 @@ namespace mdl { } } -static void object_data_get_vertex_attrib_buffer_bindings(const mdl::ObjSubMeshArgs* args, - int32_t texcoord_array[2], GLuint vertex_attrib_buffer_binding[16]) { - const obj_mesh* mesh = args->mesh; - const obj_sub_mesh* sub_mesh = args->sub_mesh; - - GLuint vertex_buffer = args->vertex_buffer; - GLuint morph_vertex_buffer = args->morph_vertex_buffer; - - uint32_t compression = mesh->attrib.m.compression; - GLsizei size_vertex = (GLsizei)mesh->size_vertex; - obj_vertex_format vertex_format = mesh->vertex_format; - - if (vertex_format & OBJ_VERTEX_POSITION) - vertex_attrib_buffer_binding[POSITION_INDEX] = vertex_buffer; - if (vertex_format & OBJ_VERTEX_NORMAL) - vertex_attrib_buffer_binding[NORMAL_INDEX] = vertex_buffer; - if (vertex_format & OBJ_VERTEX_TANGENT) - vertex_attrib_buffer_binding[TANGENT_INDEX] = vertex_buffer; - - for (int32_t i = 0; i < 2; i++) { - int32_t texcoord_index = texcoord_array[i]; - if (texcoord_index >= 0) - if (vertex_format & (OBJ_VERTEX_TEXCOORD0 << texcoord_index)) - vertex_attrib_buffer_binding[TEXCOORD0_INDEX + i] = vertex_buffer; - } - - if (vertex_format & OBJ_VERTEX_COLOR0) - vertex_attrib_buffer_binding[COLOR0_INDEX] = vertex_buffer; - - if (vertex_format & OBJ_VERTEX_BONE_DATA) { - vertex_attrib_buffer_binding[BONE_WEIGHT_INDEX] = vertex_buffer; - vertex_attrib_buffer_binding[BONE_INDEX_INDEX] = vertex_buffer; - } - - if (!compression && (vertex_format & OBJ_VERTEX_UNKNOWN)) - vertex_attrib_buffer_binding[UNKNOWN_INDEX] = vertex_buffer; - - if (args->morph_vertex_buffer) { - if (vertex_format & OBJ_VERTEX_POSITION) - vertex_attrib_buffer_binding[MORPH_POSITION_INDEX] = morph_vertex_buffer; - if (vertex_format & OBJ_VERTEX_NORMAL) - vertex_attrib_buffer_binding[MORPH_NORMAL_INDEX] = morph_vertex_buffer; - if (vertex_format & OBJ_VERTEX_TANGENT) - vertex_attrib_buffer_binding[MORPH_TANGENT_INDEX] = morph_vertex_buffer; - if (vertex_format & OBJ_VERTEX_TEXCOORD0) - vertex_attrib_buffer_binding[MORPH_TEXCOORD0_INDEX] = morph_vertex_buffer; - if (vertex_format & OBJ_VERTEX_TEXCOORD1) - vertex_attrib_buffer_binding[MORPH_TEXCOORD1_INDEX] = morph_vertex_buffer; - if (vertex_format & OBJ_VERTEX_COLOR0) - vertex_attrib_buffer_binding[MORPH_COLOR_INDEX] = morph_vertex_buffer; - } -} - static void sub_140436760(const cam_data& cam) { for (auto& i : rctx_ptr->disp_manager->obj[mdl::OBJ_TYPE_TRANSLUCENT]) { if (i->kind != mdl::OBJ_KIND_NORMAL) diff --git a/src/CRE/mdl/disp_manager.hpp b/src/CRE/mdl/disp_manager.hpp index 633d52e5..5a2a444d 100644 --- a/src/CRE/mdl/disp_manager.hpp +++ b/src/CRE/mdl/disp_manager.hpp @@ -478,16 +478,11 @@ namespace mdl { GLuint morph_vertex_buffer; size_t morph_vertex_buffer_offset; GLuint index_buffer; - int32_t alive_time; GLuint vertex_array; - bool vertex_attrib_array[16]; obj_vertex_format vertex_format; GLsizei size_vertex; uint32_t compression; - GLuint vertex_attrib_buffer_binding[16]; int32_t texcoord_array[2]; - - void reset_vertex_attrib(); }; mdl::ObjFlags obj_flags; @@ -525,7 +520,9 @@ namespace mdl { DispManager(); ~DispManager(); - void add_vertex_array(ObjSubMeshArgs* args); + void add_vertex_array(const obj_mesh* mesh, const obj_sub_mesh* sub_mesh, const obj_material_data* material, + GLuint vertex_buffer, size_t vertex_buffer_offset, GLuint index_buffer, + GLuint morph_vertex_buffer, size_t morph_vertex_buffer_offset); void* alloc_data(int32_t size); ObjData* alloc_obj_data(ObjKind kind); mat4* alloc_mat4_array(int32_t count); @@ -533,9 +530,6 @@ namespace mdl { void calc_obj_radius(const cam_data& cam, ObjType type); void calc_obj_radius(const cam_data& cam, ObjTypeScreen type); void calc_obj_radius(const cam_data& cam, ObjTypeReflect type); - void check_index_buffer(GLuint buffer); - void check_vertex_arrays(); - void check_vertex_buffer(GLuint buffer); void draw(render_data_context& rend_data_ctx, ObjType type, const cam_data& cam, int32_t depth_mask = 0, bool reflect_texture_mask = true, int32_t alpha = -1); void draw(render_data_context& rend_data_ctx, ObjTypeScreen type, const cam_data& cam, @@ -559,7 +553,7 @@ namespace mdl { bool entry_obj_by_object_info(const mat4& mat, object_info obj_info, const mat4* bone_mat); bool entry_obj_by_object_info(const mat4& mat, object_info obj_info, const vec4* blend_color, const mat4* bone_mat, int32_t instances_count, const mat4* instances_mat, - void(*func)(const mdl::ObjSubMeshArgs*), const ObjSubMeshArgs* func_data, bool enable_bone_mat); + void(*func)(const ObjSubMeshArgs*), const ObjSubMeshArgs* func_data, bool enable_bone_mat); bool entry_obj_by_object_info_screen(const mat4& mat, object_info obj_info, const vec4* blend_color); bool entry_obj_by_object_info(const mat4& mat, object_info obj_info, float_t alpha, const mat4* bone_mat = 0); bool entry_obj_by_object_info(const mat4& mat, object_info obj_info, @@ -577,11 +571,13 @@ namespace mdl { void entry_obj_etc(const mat4& mat, const EtcObj& etc); void entry_obj_etc_screen(const mat4& mat, const EtcObj& etc); 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 obj_mesh* mesh, const obj_sub_mesh* sub_mesh, + const obj_material_data* material, GLuint vertex_buffer, size_t vertex_buffer_offset, + GLuint index_buffer, GLuint morph_vertex_buffer, size_t morph_vertex_buffer_offset); bool get_chara_color(); void get_material_list(int32_t& count, material_list_struct*& value); void get_morph(object_info& object, float_t& weight); - void get_obj_center(const mat4& mat, const mdl::ObjSubMeshArgs* args, vec3& center); + void get_obj_center(const mat4& mat, const ObjSubMeshArgs* args, vec3& center); int32_t get_obj_count(ObjType type); int32_t get_obj_count(ObjTypeScreen type); int32_t get_obj_count(ObjTypeReflect type); @@ -601,6 +597,8 @@ namespace mdl { void obj_sort(render_data_context& rend_data_ctx, ObjTypeReflect type, int32_t compare_func, const cam_data& cam); void refresh(); + void remove_index_buffer(GLuint buffer); + void remove_vertex_buffer(GLuint buffer); void set_chara_color(bool value = false); void set_culling_func(bool(*func)(const obj_bounding_sphere*, const mat4*) = 0); void set_obj_flags(ObjFlags flags = (ObjFlags)0); diff --git a/src/CRE/mdl/draw_object.cpp b/src/CRE/mdl/draw_object.cpp index 8ac54417..f48e447e 100644 --- a/src/CRE/mdl/draw_object.cpp +++ b/src/CRE/mdl/draw_object.cpp @@ -127,7 +127,9 @@ namespace mdl { void draw_sub_mesh(render_data_context& rend_data_ctx, const ObjSubMeshArgs* args, const mat4* mat, void(*func)(render_data_context& rend_data_ctx, const ObjSubMeshArgs* args, const cam_data& cam, const mat4* mat), const cam_data& cam) { - GLuint vao = rctx_ptr->disp_manager->get_vertex_array(args); + GLuint vao = rctx_ptr->disp_manager->get_vertex_array(args->mesh, + args->sub_mesh, args->material, args->vertex_buffer, args->vertex_buffer_offset, + args->index_buffer, args->morph_vertex_buffer, args->morph_vertex_buffer_offset); if (!vao) return; diff --git a/src/CRE/object.cpp b/src/CRE/object.cpp index 81bbc854..3864f8cc 100644 --- a/src/CRE/object.cpp +++ b/src/CRE/object.cpp @@ -44,6 +44,7 @@ static void ObjsetInfo_index_buffer_free(ObjsetInfo* info); static bool ObjsetInfo_load_textures(ObjsetInfo* info, const void* data, bool big_endian); static bool ObjsetInfo_load_textures_modern(ObjsetInfo* info, const void* data, size_t size, const char* file, texture_database* tex_db); +static void ObjsetInfo_vertex_array_load(ObjsetInfo* info); static bool ObjsetInfo_vertex_buffer_load(ObjsetInfo* info); static void ObjsetInfo_vertex_buffer_free(ObjsetInfo* info); static uint32_t obj_vertex_format_get_vertex_size(obj_vertex_format format); @@ -2218,6 +2219,7 @@ bool objset_info_storage_load_obj_set_check_not_read(uint32_t set_id, || !ObjsetInfo_index_buffer_load(info)) return false; + ObjsetInfo_vertex_array_load(info); ObjsetInfo_calc_axis_aligned_bounding_box(info); info->obj_loaded = true; } @@ -2331,6 +2333,7 @@ bool objset_info_storage_load_obj_set_check_not_read(uint32_t set_id, || !ObjsetInfo_index_buffer_load(info)) return false; + ObjsetInfo_vertex_array_load(info); ObjsetInfo_calc_axis_aligned_bounding_box(info); info->obj_loaded = true; @@ -2462,7 +2465,7 @@ static void free_index_buffer(GLuint buffer) { return; extern render_context* rctx_ptr; - rctx_ptr->disp_manager->check_index_buffer(buffer); + rctx_ptr->disp_manager->remove_index_buffer(buffer); GLint size = 0; if (GLAD_GL_VERSION_4_5) @@ -2484,7 +2487,7 @@ static void free_vertex_buffer(GLuint buffer) { return; extern render_context* rctx_ptr; - rctx_ptr->disp_manager->check_vertex_buffer(buffer); + rctx_ptr->disp_manager->remove_vertex_buffer(buffer); GLint size = 0; if (GLAD_GL_VERSION_4_5) @@ -2714,6 +2717,64 @@ static bool ObjsetInfo_load_textures_modern(ObjsetInfo* info, return false; } +static void ObjsetInfo_vertex_array_load(ObjsetInfo* info) { + obj_set* set = info->obj_set; + obj_vertex_buffer* obj_vert_buf = info->objvb; + obj_index_buffer* obj_index_buf = info->objib; + for (int32_t i = 0; i < set->obj_num; i++) { + obj* obj = set->obj_data[i]; + +#if SHARED_OBJECT_BUFFER + bool double_buffer = false; + for (int32_t i = 0; i < obj->num_mesh; i++) { + obj_mesh& mesh = obj->mesh_array[i]; + if (!mesh.num_vertex || !mesh.vertex_array) + continue; + + double_buffer |= !!mesh.attrib.m.double_buffer; + } +#endif + + for (int32_t j = 0; j < obj->num_mesh; j++) { + obj_mesh* mesh = &obj->mesh_array[j]; + if (!mesh->num_vertex || !mesh->vertex_array) + continue; + + for (int32_t k = 0; k < mesh->num_submesh; k++) { + obj_sub_mesh* sub_mesh = &mesh->submesh_array[k]; + if (sub_mesh->attrib.m.cloth) + continue; + + obj_material_data* material = &obj->material_array[sub_mesh->material_index]; + +#if SHARED_OBJECT_BUFFER + for (int32_t l = 0; l < (double_buffer ? 2 : 1); l++) { +#else + for (int32_t l = 0; l < (mesh->attrib.m.double_buffer ? 2 : 1); l++) { +#endif + GLuint vertex_buffer = 0; + size_t vertex_buffer_offset = 0; + if (obj_vert_buf && obj_vert_buf[i].mesh_data) { + vertex_buffer = obj_vert_buf[i].mesh_data[j].get_buffer(); + vertex_buffer_offset = obj_vert_buf[i].mesh_data[j].get_offset(); + } + + GLuint index_buffer = 0; + if (obj_index_buf && obj_index_buf[i].mesh_data) + index_buffer = obj_index_buf[i].mesh_data[j].buffer; + + extern render_context* rctx_ptr; + rctx_ptr->disp_manager->add_vertex_array(mesh, sub_mesh, material, + vertex_buffer, vertex_buffer_offset, index_buffer, 0, 0); + + if (obj_vert_buf && obj_vert_buf[i].mesh_data) + obj_vert_buf[i].mesh_data[j].cycle_index(); + } + } + } + } +} + static bool ObjsetInfo_vertex_buffer_load(ObjsetInfo* info) { obj_set* set = info->obj_set; info->objvb_num = set->obj_num; diff --git a/src/CRE/render_manager.cpp b/src/CRE/render_manager.cpp index edfbe7c9..665e8500 100644 --- a/src/CRE/render_manager.cpp +++ b/src/CRE/render_manager.cpp @@ -347,7 +347,6 @@ namespace rndr { rend_data_ctx.state.finish(); } - rctx_ptr->disp_manager->check_vertex_arrays(); rctx_ptr->etc_obj_manager->post_draw(); sprite_manager_post_draw(); diff --git a/src/CRE/rob/ex_block.cpp b/src/CRE/rob/ex_block.cpp index 381137d5..85eadc5f 100644 --- a/src/CRE/rob/ex_block.cpp +++ b/src/CRE/rob/ex_block.cpp @@ -1735,6 +1735,30 @@ void RobCloth::InitDataParent(obj_skin_block_cloth* cls_data, this->cls_data = cls_data; InitData(cls_data->num_root, cls_data->num_node, cls_data->root_array, cls_data->node_array, cls_data->mat_array, cls_data->loop, itm_eq_obj, bone_data); + + obj* obj = objset_info_storage_get_obj(itm_eq_obj->obj_info); + if (!obj) + return; + + for (int32_t i = 0; i < 2; i++) { + if (!mesh[i].num_vertex || !mesh[i].vertex_array || !index_buffer[i].buffer) + continue; + + obj_mesh_vertex_buffer* obj_vert_buf = &vertex_buffer[i]; + obj_mesh_index_buffer* obj_index_buf = &index_buffer[i]; + + obj_mesh* mesh = &this->mesh[i]; + for (int32_t j = 0; j < mesh->num_submesh; j++) { + obj_material_data* material = &obj->material_array[mesh->submesh_array[j].material_index]; + for (int32_t k = 0; k < (mesh->attrib.m.double_buffer ? 2 : 1); k++) { + extern render_context* rctx_ptr; + rctx_ptr->disp_manager->add_vertex_array(mesh, &mesh->submesh_array[j], material, + obj_vert_buf->get_buffer(), obj_vert_buf->get_offset(), obj_index_buf->buffer, 0, 0); + + obj_vert_buf->cycle_index(); + } + } + } } const float_t* RobCloth::LoadOpdData(size_t node_index, const float_t* opd_data, size_t opd_count) { diff --git a/src/CRE/rob/rob.cpp b/src/CRE/rob/rob.cpp index d561aabb..0d5cd477 100644 --- a/src/CRE/rob/rob.cpp +++ b/src/CRE/rob/rob.cpp @@ -18907,6 +18907,15 @@ void rob_chara_age_age_object::load(object_info obj_info, int32_t count) { sub_mesh.index_offset = 0; axis_aligned_bounding_box = sm->axis_aligned_bounding_box; + + if (mesh.num_vertex && mesh.vertex_array) + for (int32_t i = 0; i < 2; i++) { + extern render_context* rctx_ptr; + rctx_ptr->disp_manager->add_vertex_array(&mesh, &sub_mesh, material, + obj_vert_buf.get_buffer(), obj_vert_buf.get_offset(), obj_index_buf.buffer, 0, 0); + + obj_vert_buf.cycle_index(); + } } void rob_chara_age_age_object::reset() {