From ad2d465a0683a245bd00651a517ba7dc3f0ab76f Mon Sep 17 00:00:00 2001 From: korenkonder Date: Tue, 2 Jan 2024 00:12:49 +0300 Subject: [PATCH] Shared Object Buffer --- src/DivaGL/mdl/disp_manager.cpp | 100 ++++++-- src/DivaGL/mdl/disp_manager.hpp | 20 +- src/DivaGL/object.cpp | 411 ++++++++++++++++++++++++++++++-- src/DivaGL/object.hpp | 66 +++++ src/DivaGL/rob/rob.cpp | 4 + 5 files changed, 557 insertions(+), 44 deletions(-) diff --git a/src/DivaGL/mdl/disp_manager.cpp b/src/DivaGL/mdl/disp_manager.cpp index 8ac5665..3ee0c47 100644 --- a/src/DivaGL/mdl/disp_manager.cpp +++ b/src/DivaGL/mdl/disp_manager.cpp @@ -64,10 +64,10 @@ namespace mdl { prj::vector vertex_array_cache; prj::vector etc_vertex_array_cache; - ObjSubMeshArgs::ObjSubMeshArgs() : sub_mesh(), mesh(), material(), textures(), mat_count(), - mats(), vertex_buffer(), index_buffer(), set_blend_color(), chara_color(), self_shadow(), - shadow(), morph_vertex_buffer(), morph_weight(), texture_pattern_count(), texture_transform_count(), - field_7C4(), field_7C8(), instances_count(), instances_mat(), func(), func_data() { + 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(), + texture_transform_count(), field_7C4(), field_7C8(), instances_count(), instances_mat(), func(), func_data() { } @@ -185,10 +185,11 @@ namespace mdl { disp_manager->add_vertex_array(&args.etc, this->mat); } - void ObjData::init_sub_mesh(const mat4* mat, - float_t radius, obj_sub_mesh* sub_mesh, obj_mesh* mesh, obj_material_data* material, - prj::vector* textures, int32_t mat_count, mat4* mats, GLuint vertex_buffer, - GLuint index_buffer, vec4* blend_color, GLuint morph_vertex_buffer, + 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, 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) { kind = mdl::OBJ_KIND_NORMAL; @@ -204,8 +205,10 @@ namespace mdl { args->mat_count = mat_count; args->mats = mats; args->vertex_buffer = vertex_buffer; + args->vertex_buffer_offset = vertex_buffer_offset; args->index_buffer = index_buffer; args->morph_vertex_buffer = morph_vertex_buffer; + args->morph_vertex_buffer_offset = morph_vertex_buffer_offset; args->texture_pattern_count = disp_manager->texture_pattern_count; for (int32_t i = 0; i < disp_manager->texture_pattern_count && i < TEXTURE_PATTERN_COUNT; i++) @@ -278,7 +281,9 @@ namespace mdl { 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; int32_t texcoord_array[2] = { -1, -1 }; @@ -308,7 +313,9 @@ namespace mdl { DispManager::vertex_array* vertex_array = 0; for (DispManager::vertex_array& i : vertex_array_cache) if (i.alive_time >= 0 && 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 && !memcmp(i.vertex_attrib_buffer_binding, @@ -358,7 +365,9 @@ namespace mdl { } 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; @@ -372,7 +381,7 @@ namespace mdl { if (index_buffer) gl_state_bind_element_array_buffer(index_buffer, true); - size_t offset = 0; + size_t offset = vertex_buffer_offset; if (vertex_format & OBJ_VERTEX_POSITION) { if (!vertex_array->vertex_attrib_array[POSITION_INDEX]) { glEnableVertexAttribArray(POSITION_INDEX); @@ -518,7 +527,7 @@ namespace mdl { if (morph_vertex_buffer) { gl_state_bind_array_buffer(morph_vertex_buffer, true); - size_t offset = 0; + 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); @@ -2015,16 +2024,22 @@ namespace mdl { continue; GLuint morph_vertex_buffer = 0; - if (obj_morph_vertex_buf) + 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(); + } GLuint index_buffer = 0; if (obj_index_buf) index_buffer = obj_index_buf[i].buffer; GLuint vertex_buffer = 0; - if (obj_vertex_buf) + 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 (!vertex_buffer || !index_buffer || obj_morph_vertex_buf && !morph_vertex_buffer) continue; @@ -2033,9 +2048,9 @@ namespace mdl { if (blend_color) _blend_color = *blend_color; - data->init_sub_mesh(mat, object->bounding_sphere.radius, sub_mesh, - mesh, material, textures, num_bone_index, mats, vertex_buffer, index_buffer, - &_blend_color, morph_vertex_buffer, instances_count, instances_mat, func, func_data); + data->init_sub_mesh(mat, object->bounding_sphere.radius, sub_mesh, mesh, material, textures, + num_bone_index, mats, vertex_buffer, vertex_buffer_offset, index_buffer, &_blend_color, + morph_vertex_buffer, morph_vertex_buffer_offset, instances_count, instances_mat, func, func_data); if (obj_flags & mdl::OBJ_SHADOW_OBJECT) { entry_list((ObjType)(OBJ_TYPE_SHADOW_OBJECT_CHARA @@ -2211,6 +2226,41 @@ namespace mdl { 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, + obj_mesh_index_buffer* obj_index_buf, mat4* bone_mat, float_t alpha) { + if (!obj) + return; + + obj_mesh_vertex_buffer* _obj_vert_buf = new (_operator_new( + sizeof(obj_mesh_vertex_buffer) * obj->num_mesh)) obj_mesh_vertex_buffer[obj->num_mesh]; + if (!_obj_vert_buf) + return; + + for (uint32_t i = 0; i < obj->num_mesh; i++) { + _obj_vert_buf[i].count = obj_vert_buf[i].count; + _obj_vert_buf[i].buffers[0] = obj_vert_buf[i].buffers[0]; + _obj_vert_buf[i].buffers[1] = obj_vert_buf[i].buffers[1]; + _obj_vert_buf[i].buffers[2] = obj_vert_buf[i].buffers[2]; + _obj_vert_buf[i].index = obj_vert_buf[i].index; + _obj_vert_buf[i].size = obj_vert_buf[i].get_size(); + _obj_vert_buf[i].offset = 0; + } + + vec4 blend_color = 1.0f; + 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, + 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, 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); @@ -2220,7 +2270,7 @@ namespace mdl { 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) { - if (obj_info.id == -1 && obj_info.set_id == -1) + if (obj_info.id == (uint16_t)-1 && obj_info.set_id == (uint16_t)-1) return false; ::obj* object = object_info_get_object(obj_info); @@ -2233,7 +2283,7 @@ namespace mdl { ::obj* obj_morph = 0; obj_mesh_vertex_buffer* obj_morph_vertex_buffer = 0; - if (morph.object.set_id != -1) { + if (morph.object.set_id != (uint16_t)-1) { obj_morph = object_info_get_object(morph.object); obj_morph_vertex_buffer = object_info_get_mesh_vertex_buffer(morph.object, 0); } @@ -2353,7 +2403,9 @@ namespace mdl { 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; int32_t texcoord_array[2] = { -1, -1 }; @@ -2382,7 +2434,9 @@ namespace mdl { for (DispManager::vertex_array& i : vertex_array_cache) if (i.alive_time > 0 && 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 && !memcmp(i.vertex_attrib_buffer_binding, @@ -2700,10 +2754,18 @@ namespace mdl { disp_manager->entry_obj_etc(&mat4_identity, etc); } - 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) { + +#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); } +#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); + } +#endif HOOK(void, FASTCALL, sub_1404BCC60, 0x00000001404BCC60, vec3* pos, float_t width, float_t height) { mdl::EtcObj etc(ETC_OBJ_PLANE); diff --git a/src/DivaGL/mdl/disp_manager.hpp b/src/DivaGL/mdl/disp_manager.hpp index bfa5c1a..be5101e 100644 --- a/src/DivaGL/mdl/disp_manager.hpp +++ b/src/DivaGL/mdl/disp_manager.hpp @@ -150,10 +150,11 @@ namespace mdl { const obj_sub_mesh* sub_mesh; const obj_mesh* mesh; const obj_material_data* material; - prj::vector* textures; + const prj::vector* textures; int32_t mat_count; const mat4* mats; GLuint vertex_buffer; + size_t vertex_buffer_offset; GLuint index_buffer; bool set_blend_color; bool chara_color; @@ -161,6 +162,7 @@ namespace mdl { int32_t self_shadow; shadow_type_enum shadow; GLuint morph_vertex_buffer; + size_t morph_vertex_buffer_offset; float_t morph_weight; int32_t texture_pattern_count; texture_pattern_struct texture_pattern_array[TEXTURE_PATTERN_COUNT]; @@ -302,10 +304,11 @@ namespace mdl { ~ObjData(); void init_etc(const mat4* mat, mdl::EtcObj* etc); - void init_sub_mesh(const mat4* mat, - float_t radius, obj_sub_mesh* sub_mesh, obj_mesh* mesh, obj_material_data* material, - prj::vector* textures, int32_t mat_count, mat4* mats, GLuint vertex_buffer, - GLuint index_buffer, vec4* blend_color, GLuint morph_vertex_buffer, + 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, 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); @@ -331,7 +334,9 @@ namespace mdl { struct DispManager { struct vertex_array { GLuint vertex_buffer; + size_t vertex_buffer_offset; GLuint morph_vertex_buffer; + size_t morph_vertex_buffer_offset; GLuint index_buffer; int32_t alive_time; GLuint vertex_array; @@ -410,6 +415,11 @@ namespace mdl { void entry_obj_by_obj(const mat4* mat, ::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, + 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, mat4* bone_mat = 0); 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, diff --git a/src/DivaGL/object.cpp b/src/DivaGL/object.cpp index 649a121..e21aa5c 100644 --- a/src/DivaGL/object.cpp +++ b/src/DivaGL/object.cpp @@ -5,6 +5,7 @@ #include "object.hpp" #include "mdl/disp_manager.hpp" +#include "file_handler.hpp" #include "gl_state.hpp" #include "wrap.hpp" #include @@ -16,6 +17,43 @@ struct BufObjMgr { int32_t ib_all_size; }; +struct shared_ptr_prj__stack_allocator { + void* ptr; + void* ref; +}; + +struct ObjsetInfo { + p_file_handler obj_file_handler; + bool obj_loaded; + p_file_handler tex_file_handler; + bool tex_loaded; + shared_ptr_prj__stack_allocator alloc_handler; + obj_set* obj_set; + prj::vector> obj_id_data; + bool field_50; + int32_t field_54; + int32_t tex_num; + prj::vector gentex; + prj::vector> tex_id_data; + bool field_90; + texture** textures; + int32_t set_id; + int32_t objvb_num; + obj_vertex_buffer* objvb; + int32_t objib_num; + obj_index_buffer* objib; + obj_vertex_buffer* field_C0; + obj_index_buffer* field_C8; + int32_t load_count; + + void index_buffer_free(); + bool index_buffer_load(); + void vertex_buffer_free(); + bool vertex_buffer_load(); +}; + +static_assert(sizeof(ObjsetInfo) == 0xD8, "\"ObjsetInfo\" struct should have a size of 0xD8"); + uint32_t(FASTCALL* object_database_get_object_info)(const char* name) = (uint32_t(FASTCALL*)(const char* name))0x0000000140459F80; obj* (FASTCALL* object_info_get_object)(object_info obj_info) @@ -68,6 +106,10 @@ int32_t obj_texture_attrib::get_blend() const { } } +obj_mesh_index_buffer::obj_mesh_index_buffer() : buffer() { + +} + bool obj_mesh_index_buffer::load(obj_mesh* mesh) { size_t num_index = 0; for (uint32_t i = 0; i < mesh->num_submesh; i++) @@ -141,6 +183,14 @@ void* obj_mesh_index_buffer::fill_data(void* data, obj_mesh* mesh) { return (void*)indices; } +#if SHARED_OBJECT_BUFFER +obj_mesh_vertex_buffer::obj_mesh_vertex_buffer() : count(), buffers(), size(), offset(), index() { +#else +obj_mesh_vertex_buffer::obj_mesh_vertex_buffer() : count(), buffers(), index(), target() { +#endif + +} + void obj_mesh_vertex_buffer::cycle_index() { if (++index >= count) index = 0; @@ -152,7 +202,19 @@ GLuint obj_mesh_vertex_buffer::get_buffer() { return 0; } +size_t obj_mesh_vertex_buffer::get_offset() { +#if SHARED_OBJECT_BUFFER + if (buffers[0]) + return offset; + return 0; +#endif +} + GLsizeiptr obj_mesh_vertex_buffer::get_size() { +#if SHARED_OBJECT_BUFFER + if (buffers[0]) + return size; +#else if (buffers[0]) { GLint buffer; GLint size; @@ -162,6 +224,7 @@ GLsizeiptr obj_mesh_vertex_buffer::get_size() { gl_state_bind_element_array_buffer(buffer); return size; } +#endif return 0; } @@ -351,7 +414,205 @@ void* obj_mesh_vertex_buffer::fill_data(void* data, obj_mesh* mesh) { d += 16; } - return (void*)d; + return (void*)((size_t)data + (size_t)size_vertex * num_vertex); +} + +#if SHARED_OBJECT_BUFFER +void obj_mesh_vertex_buffer_aft::cycle_index() { + if (++index >= count) + index = 0; +} + +GLuint obj_mesh_vertex_buffer_aft::get_buffer() { + if (index < count) + return buffers[index]; + return 0; +} + +GLsizeiptr obj_mesh_vertex_buffer_aft::get_size() { + if (buffers[0]) { + GLint buffer; + GLint size; + glGetIntegervDLL(GL_ARRAY_BUFFER_BINDING, &buffer); + gl_state_bind_element_array_buffer(buffers[0]); + glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size); + gl_state_bind_element_array_buffer(buffer); + return size; + } + return 0; +} +#endif + +#if SHARED_OBJECT_BUFFER +obj_index_buffer::obj_index_buffer() : mesh_num(), mesh_data(), buffer() { +#else +obj_index_buffer::obj_index_buffer() : mesh_num(), mesh_data() { +#endif + +} + +bool obj_index_buffer::load(obj* obj) { + if (!obj) + return false; + + mesh_num = obj->num_mesh; + mesh_data = new obj_mesh_index_buffer[obj->num_mesh]; + if (!mesh_data) + return false; + +#if SHARED_OBJECT_BUFFER + size_t buffer_size = 0; + for (uint32_t i = 0; i < mesh_num; i++) { + obj_mesh& mesh = obj->mesh_array[i]; + size_t num_index = 0; + for (uint32_t i = 0; i < mesh.num_submesh; i++) + num_index += mesh.submesh_array[i].num_index; + buffer_size += num_index * sizeof(uint16_t); + } + + void* index = force_malloc(buffer_size); + if (!index) { + buffer = 0; + unload(); + return false; + } + + void* data = index; + for (uint32_t i = 0; i < mesh_num; i++) { + uint32_t offset = (uint32_t)((size_t)data - (size_t)index); + data = obj_mesh_index_buffer::fill_data(data, &obj->mesh_array[i]); + + obj_mesh& mesh = obj->mesh_array[i]; + for (uint32_t j = 0; j < mesh.num_submesh; j++) + mesh.submesh_array[j].index_offset += offset; + } + + buffer = create_index_buffer(buffer_size, index); + if (!buffer) { + free_def(index); + unload(); + return false; + } + + free_def(index); + + for (uint32_t i = 0; i < mesh_num; i++) + mesh_data[i].buffer = buffer; +#else + for (uint32_t i = 0; i < mesh_num; i++) + if (!mesh_data[i].load(&obj->mesh_array[i])) + return false; +#endif + return true; +} + +void obj_index_buffer::unload() { + if (mesh_data) { +#if SHARED_OBJECT_BUFFER + free_index_buffer(buffer); + buffer = 0; +#else + for (uint32_t i = 0; i < mesh_num; i++) + mesh_data[i].unload(); +#endif + delete[] mesh_data; + } + mesh_data = 0; + mesh_num = 0; +#if SHARED_OBJECT_BUFFER + buffer = 0; +#endif +} + +#if SHARED_OBJECT_BUFFER +obj_vertex_buffer::obj_vertex_buffer() : mesh_num(), mesh_data(), buffers() { +#else +obj_vertex_buffer::obj_vertex_buffer() : mesh_num(), mesh_data() { +#endif + +} + +bool obj_vertex_buffer::load(obj* obj) { + if (!obj) + return false; + + mesh_num = obj->num_mesh; + mesh_data = new obj_mesh_vertex_buffer[obj->num_mesh]; + if (!mesh_data) + return false; + +#if SHARED_OBJECT_BUFFER + size_t buffer_size = 0; + bool double_buffer = false; + for (uint32_t i = 0; i < mesh_num; i++) { + obj_mesh& mesh = obj->mesh_array[i]; + if (!mesh.num_vertex) + continue; + + uint32_t size_vertex = obj_vertex_format_get_vertex_size(mesh.vertex_format); + mesh.size_vertex = size_vertex; + + buffer_size += (size_t)size_vertex * mesh.num_vertex; + double_buffer |= !!mesh.attrib.m.double_buffer; + } + + int32_t count = double_buffer ? 2 : 1; + + void* vertex = force_malloc(buffer_size); + if (!vertex) { + for (int32_t i = 0; i < count; i++) + buffers[i] = 0; + unload(); + return false; + } + + void* data = vertex; + for (uint32_t i = 0; i < mesh_num; i++) { + obj_mesh_vertex_buffer& mesh_buffer = mesh_data[i]; + mesh_buffer.offset = (size_t)data - (size_t)vertex; + mesh_buffer.count = count; + mesh_buffer.size = (GLsizeiptr)buffer_size; + + data = obj_mesh_vertex_buffer::fill_data(data, &obj->mesh_array[i]); + } + + for (int32_t i = 0; i < count; i++) { + buffers[i] = create_vertex_buffer(buffer_size, vertex); + if (!buffers[i]) { + free_def(vertex); + unload(); + return false; + } + } + + free_def(vertex); + + for (uint32_t i = 0; i < mesh_num; i++) + memcpy(mesh_data[i].buffers, buffers, count * sizeof(GLuint)); +#else + for (uint32_t i = 0; i < mesh_num; i++) + if (!mesh_data[i].load(&obj->mesh_array[i])) + return false; +#endif + return true; +} + +void obj_vertex_buffer::unload() { + if (mesh_data) { +#if SHARED_OBJECT_BUFFER + for (int32_t i = 0; i < mesh_data[0].count; i++) + free_vertex_buffer(buffers[i]); +#else + for (uint32_t i = 0; i < mesh_num; i++) + mesh_data[i].unload(); +#endif + delete[] mesh_data; + } + mesh_data = 0; + mesh_num = 0; +#if SHARED_OBJECT_BUFFER + buffers[0] = 0; +#endif } inline int32_t obj_material_texture_type_get_texcoord_index( @@ -424,38 +685,148 @@ void obj_skin_set_matrix_buffer(obj_skin* s, mat4* matrices, } } -HOOK(bool, FASTCALL, obj_mesh_index_buffer__load, 0x0000000140458040, obj_mesh_index_buffer* objib, obj_mesh* mesh) { - return objib->load(mesh); -} - -HOOK(bool, FASTCALL, obj_mesh_vertex_buffer__load, 0x000000140458A70, obj_mesh_vertex_buffer* objvb, obj_mesh* mesh) { - return objvb->load(mesh); -} - -HOOK(bool, FASTCALL, obj_mesh_vertex_buffer__load_dynamic, 0x0000000140458280, obj_mesh_vertex_buffer* objvb, obj_mesh* mesh) { +HOOK(bool, FASTCALL, obj_mesh_vertex_buffer__load, 0x0000000140458280, obj_mesh_vertex_buffer* objvb, obj_mesh* mesh) { return objvb->load(mesh, true); } +HOOK(bool, FASTCALL, ObjsetInfo__index_buffer_load, 0x00000001404588F0, ObjsetInfo* info) { + return info->index_buffer_load(); +} + +HOOK(bool, FASTCALL, ObjsetInfo__vertex_buffer_load, 0x00000001404589B0, ObjsetInfo* info) { + return info->vertex_buffer_load(); +} + +HOOK(void, FASTCALL, ObjsetInfo__index_buffer_free, 0x0000000140459B40, ObjsetInfo* info) { + info->index_buffer_free(); +} + +HOOK(void, FASTCALL, ObjsetInfo__vertex_buffer_free, 0x0000000140459C70, ObjsetInfo* info) { + info->vertex_buffer_free(); +} + +HOOK(obj_mesh_index_buffer*, FASTCALL, object_info_get_mesh_index_buffer, 0x000000014045A250, object_info obj_info, int32_t a2) { + bool(FASTCALL * object_database_check_set)(int32_t set) + = (bool(FASTCALL*)(int32_t set))0x00000001404577D0; + int32_t(FASTCALL * object_database_get_object_index)(int32_t set, uint32_t object_id) + = (int32_t(FASTCALL*)(int32_t set, uint32_t object_id))0x000000014045A7A0; + ObjsetInfo* (FASTCALL * object_database_get_objset_info)(int32_t set) + = (ObjsetInfo * (FASTCALL*)(int32_t set))0x000000014045AC00; + + if (object_database_check_set(obj_info.set_id)) + return 0; + + ObjsetInfo* info = object_database_get_objset_info(obj_info.set_id); + if (!info || !info->objvb) + return 0; + + int32_t object_index = object_database_get_object_index(obj_info.set_id, obj_info.id); + if (object_index >= 0) { + if (!a2) + return info->objib[object_index].mesh_data; + else if (info->field_C8) + return info->field_C8[object_index].mesh_data; + } + return 0; +} + +HOOK(obj_mesh_vertex_buffer*, FASTCALL, object_info_get_mesh_vertex_buffer, 0x000000014045A480, object_info obj_info, int32_t a2) { + bool(FASTCALL * object_database_check_set)(int32_t set) + = (bool(FASTCALL*)(int32_t set))0x00000001404577D0; + int32_t(FASTCALL * object_database_get_object_index)(int32_t set, uint32_t object_id) + = (int32_t(FASTCALL*)(int32_t set, uint32_t object_id))0x000000014045A7A0; + ObjsetInfo* (FASTCALL * object_database_get_objset_info)(int32_t set) + = (ObjsetInfo * (FASTCALL*)(int32_t set))0x000000014045AC00; + + if (object_database_check_set(obj_info.set_id)) + return 0; + + ObjsetInfo* info = object_database_get_objset_info(obj_info.set_id); + if (!info || !info->objvb) + return 0; + + int32_t object_index = object_database_get_object_index(obj_info.set_id, obj_info.id); + if (object_index >= 0) { + if (!a2) + return info->objvb[object_index].mesh_data; + else if (info->field_C0) + return info->field_C0[object_index].mesh_data; + } + return 0; +} + HOOK(void, FASTCALL, obj_mesh_vertex_buffer__unload, 0x0000000140461870, obj_mesh_vertex_buffer* objvb) { objvb->unload(); } -HOOK(void, FASTCALL, obj_mesh_index_buffer__unload, 0x0000000140461900, obj_mesh_index_buffer* objib) { - objib->unload(); -} - void object_patch() { - WRITE_CALL(0x0000000140458860, 0x000000140458A70); - WRITE_MEMORY(0x0000000140459BB5, uint8_t, - 0x48, 0x8D, 0x0C, 0x30, 0x0F, 0x1F, 0x00); +#if SHARED_OBJECT_BUFFER + WRITE_MEMORY(0x000000014045A4E7, uint8_t, sizeof(obj_vertex_buffer)); +#endif - INSTALL_HOOK(obj_mesh_index_buffer__load); INSTALL_HOOK(obj_mesh_vertex_buffer__load); - INSTALL_HOOK(obj_mesh_vertex_buffer__load_dynamic); + INSTALL_HOOK(ObjsetInfo__index_buffer_load); + INSTALL_HOOK(ObjsetInfo__vertex_buffer_load); + INSTALL_HOOK(ObjsetInfo__index_buffer_free); + INSTALL_HOOK(ObjsetInfo__vertex_buffer_free); + INSTALL_HOOK(object_info_get_mesh_index_buffer); + INSTALL_HOOK(object_info_get_mesh_vertex_buffer); INSTALL_HOOK(obj_mesh_vertex_buffer__unload); - INSTALL_HOOK(obj_mesh_index_buffer__unload); } +#pragma warning(push) +#pragma warning(disable: 6385) +void ObjsetInfo::index_buffer_free() { + if (objib) { + for (int32_t i = 0; i < objib_num; i++) + objib[i].unload(); + prj::HeapCMallocFree(prj::HeapCMallocSystem, objvb); + } + + objib = 0; + objib_num = 0; +} + +bool ObjsetInfo::index_buffer_load() { + ::obj_set* set = obj_set; + objib_num = set->obj_num; + objib = new (prj::HeapCMallocAllocate(prj::HeapCMallocSystem, + sizeof(obj_index_buffer) * set->obj_num, "OBJIB")) obj_index_buffer[set->obj_num]; + if (!objib) + return true; + + for (uint32_t i = 0; i < set->obj_num; i++) + if (!objib[i].load(set->obj_data[i])) + return false; + return true; +} + +void ObjsetInfo::vertex_buffer_free() { + if (objvb) { + for (int32_t i = 0; i < objvb_num; i++) + objvb[i].unload(); + prj::HeapCMallocFree(prj::HeapCMallocSystem, objvb); + } + + objvb = 0; + objvb_num = 0; +} + +bool ObjsetInfo::vertex_buffer_load() { + ::obj_set* set = obj_set; + objvb_num = set->obj_num; + objvb = new (prj::HeapCMallocAllocate(prj::HeapCMallocSystem, + sizeof(obj_vertex_buffer) * set->obj_num, "OBJVB")) obj_vertex_buffer[set->obj_num]; + if (!objvb) + return true; + + for (uint32_t i = 0; i < set->obj_num; i++) + if (!objvb[i].load(set->obj_data[i])) + return false; + return true; +} +#pragma warning(pop) + static GLuint create_index_buffer(size_t size, const void* data) { GLuint buffer = 0; glGenBuffers(1, &buffer); diff --git a/src/DivaGL/object.hpp b/src/DivaGL/object.hpp index 4fbf52d..1de61bb 100644 --- a/src/DivaGL/object.hpp +++ b/src/DivaGL/object.hpp @@ -11,6 +11,8 @@ #include "texture.hpp" #include "types.hpp" +#define SHARED_OBJECT_BUFFER (1) + enum obj_index_format : uint32_t { OBJ_INDEX_U8 = 0x00, OBJ_INDEX_U16 = 0x01, @@ -419,6 +421,21 @@ struct obj_skin { static_assert(sizeof(obj_skin) == 0x38, "\"obj_skin\" struct should have a size of 0x38"); +struct obj_set { + uint32_t version; + uint32_t obj_num; + uint32_t last_obj_id; + obj** obj_data; + obj_skin** obj_skin_data; + const char** obj_name_data; + uint32_t* obj_id_data; + uint32_t* tex_id_data; + uint32_t tex_num; + uint32_t reserved[2]; +}; + +static_assert(sizeof(obj_set) == 0x48, "\"obj_set\" struct should have a size of 0x48"); + struct object_info { uint16_t id; uint16_t set_id; @@ -474,6 +491,8 @@ inline bool operator !=(const object_info& left, const object_info& right) { struct obj_mesh_index_buffer { GLuint buffer; + obj_mesh_index_buffer(); + bool load(obj_mesh* mesh); bool load_data(size_t size, const void* data); void unload(); @@ -481,16 +500,26 @@ struct obj_mesh_index_buffer { static void* fill_data(void* data, obj_mesh* mesh); }; +#if !SHARED_OBJECT_BUFFER static_assert(sizeof(obj_mesh_index_buffer) == 0x04, "\"obj_mesh_index_buffer\" struct should have a size of 0x04"); +#endif struct obj_mesh_vertex_buffer { int32_t count; GLuint buffers[3]; int32_t index; +#if SHARED_OBJECT_BUFFER + GLsizeiptr size; + size_t offset; +#else GLenum target; +#endif + + obj_mesh_vertex_buffer(); void cycle_index(); GLuint get_buffer(); + size_t get_offset(); GLsizeiptr get_size(); bool load(obj_mesh* mesh, bool dynamic = false); bool load_data(size_t size, const void* data, int32_t count, bool dynamic); @@ -499,21 +528,58 @@ struct obj_mesh_vertex_buffer { static void* fill_data(void* data, obj_mesh* mesh); }; +#if SHARED_OBJECT_BUFFER +struct obj_mesh_vertex_buffer_aft { + int32_t count; + GLuint buffers[3]; + int32_t index; + GLenum target; + + void cycle_index(); + GLuint get_buffer(); + GLsizeiptr get_size(); +}; +#endif + +#if SHARED_OBJECT_BUFFER +static_assert(sizeof(obj_mesh_vertex_buffer_aft) == 0x18, "\"obj_mesh_vertex_buffer_aft\" struct should have a size of 0x18"); +#else static_assert(sizeof(obj_mesh_vertex_buffer) == 0x18, "\"obj_mesh_vertex_buffer\" struct should have a size of 0x18"); +#endif struct obj_index_buffer { uint32_t mesh_num; obj_mesh_index_buffer* mesh_data; +#if SHARED_OBJECT_BUFFER + GLuint buffer; +#endif + + obj_index_buffer(); + + bool load(obj* obj); + void unload(); }; +#if !SHARED_OBJECT_BUFFER static_assert(sizeof(obj_index_buffer) == 0x10, "\"obj_index_buffer\" struct should have a size of 0x10"); +#endif struct obj_vertex_buffer { uint32_t mesh_num; obj_mesh_vertex_buffer* mesh_data; +#if SHARED_OBJECT_BUFFER + GLuint buffers[3]; +#endif + + obj_vertex_buffer(); + + bool load(obj* obj); + void unload(); }; +#if !SHARED_OBJECT_BUFFER static_assert(sizeof(obj_vertex_buffer) == 0x10, "\"obj_vertex_buffer\" struct should have a size of 0x10"); +#endif extern uint32_t(FASTCALL* object_database_get_object_info)(const char* name); extern obj* (FASTCALL* object_info_get_object)(object_info obj_info); diff --git a/src/DivaGL/rob/rob.cpp b/src/DivaGL/rob/rob.cpp index c138048..d8ecd80 100644 --- a/src/DivaGL/rob/rob.cpp +++ b/src/DivaGL/rob/rob.cpp @@ -43,7 +43,11 @@ struct rob_chara_age_age_object { rob_chara_age_age_object_vertex* vertex_data; int32_t vertex_data_size; int32_t vertex_array_size; +#if SHARED_OBJECT_BUFFER + obj_mesh_vertex_buffer_aft obj_vert_buf; +#else obj_mesh_vertex_buffer obj_vert_buf; +#endif obj_mesh_index_buffer obj_index_buf; vec3 trans[10]; int32_t disp_count;