/* by korenkonder GitHub/GitLab: korenkonder */ #include #include #include #include #include "object.hpp" #include "data.hpp" #include "gl_state.hpp" #include "shader_ft.hpp" #include "../KKdLib/io/file_stream.hpp" #include "../KKdLib/io/json.hpp" #include "../KKdLib/io/path.hpp" #include "../KKdLib/dds.hpp" #include "../KKdLib/hash.hpp" #include "../KKdLib/msgpack.hpp" #include "../KKdLib/str_utils.hpp" static void obj_set_handler_calc_axis_aligned_bounding_box(obj_set_handler* handler); static void obj_set_handler_get_shader_index_texture_index(obj_set_handler* handler); static bool obj_set_handler_index_buffer_load(obj_set_handler* handler); static void obj_set_handler_index_buffer_free(obj_set_handler* handler); static bool obj_set_handler_load_textures(obj_set_handler* handler, const void* data, bool big_endian); static bool obj_set_handler_load_textures_modern(obj_set_handler* handler, const void* data, size_t size, const char* file, texture_database* tex_db); static bool obj_set_handler_vertex_buffer_load(obj_set_handler* handler); static void obj_set_handler_vertex_buffer_free(obj_set_handler* handler); static uint32_t obj_vertex_format_get_vertex_size(obj_vertex_format format); static uint32_t obj_vertex_format_get_vertex_size_comp(obj_vertex_format format); std::map object_storage_data; std::map object_storage_data_modern; obj_mesh_index_buffer::obj_mesh_index_buffer() : buffer(), size() { } bool obj_mesh_index_buffer::load(obj_mesh& mesh) { size_t num_index = 0; for (uint32_t i = 0; i < mesh.num_submesh; i++) num_index += mesh.submesh_array[i].num_index; if (!num_index) { buffer = 0; return true; } uint16_t* indices = force_malloc_s(uint16_t, num_index); obj_mesh_index_buffer::fill_data(indices, mesh); bool ret = load_data(num_index * sizeof(uint16_t), indices); free_def(indices); return ret; } bool obj_mesh_index_buffer::load_data(size_t size, const void* data) { if (!size) return false; this->size = (GLsizeiptr)size; glGenBuffers(1, &buffer); gl_state_bind_element_array_buffer(buffer, true); if (GLAD_GL_VERSION_4_4) glBufferStorage(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)size, data, 0); else glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)size, data, GL_STATIC_DRAW); gl_state_bind_element_array_buffer(0); return true; } void obj_mesh_index_buffer::unload() { if (buffer) glDeleteBuffers(1, &buffer); buffer = 0; size = 0; } void* obj_mesh_index_buffer::fill_data(void* data, obj_mesh& mesh) { uint16_t* indices = (uint16_t*)data; for (uint32_t i = 0; i < mesh.num_submesh; i++) { obj_sub_mesh& sub_mesh = mesh.submesh_array[i]; uint32_t num_index = sub_mesh.num_index; uint32_t* index = sub_mesh.index_array; for (uint32_t j = num_index; j; j--, index++) *indices++ = (uint16_t)*index; } indices = (uint16_t*)data; for (uint32_t i = 0, offset = 0; i < mesh.num_submesh; i++) { obj_sub_mesh& sub_mesh = mesh.submesh_array[i]; sub_mesh.first_index = 0; sub_mesh.last_index = 0; sub_mesh.index_offset = 0; if (sub_mesh.index_format != OBJ_INDEX_U16) continue; uint16_t first_index = 0xFFFF; uint16_t last_index = 0; for (uint32_t j = sub_mesh.num_index; j; j--) { uint16_t index = *indices++; if (index == 0xFFFF) continue; if (first_index > index) first_index = index; if (last_index < index) last_index = index; } sub_mesh.first_index = first_index; sub_mesh.last_index = last_index; sub_mesh.index_offset = (int32_t)(offset * sizeof(uint16_t)); offset += sub_mesh.num_index; } 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(), size(), index() { #endif } void obj_mesh_vertex_buffer::cycle_index() { if (++index >= count) index = 0; } GLuint obj_mesh_vertex_buffer::get_buffer() { if (index < count) return buffers[index]; return 0; } #if SHARED_OBJECT_BUFFER size_t obj_mesh_vertex_buffer::get_offset() { if (buffers[0]) return offset; return 0; } #endif GLsizeiptr obj_mesh_vertex_buffer::get_size() { if (buffers[0]) return size; return 0; } bool obj_mesh_vertex_buffer::load(obj_mesh& mesh, bool dynamic) { if (!mesh.num_vertex || !mesh.vertex_array) return false; uint32_t size_vertex; if (!mesh.attrib.m.compressed) size_vertex = obj_vertex_format_get_vertex_size(mesh.vertex_format); else size_vertex = obj_vertex_format_get_vertex_size_comp(mesh.vertex_format); void* vertex = force_malloc((size_t)size_vertex * mesh.num_vertex); obj_mesh_vertex_buffer::fill_data(vertex, mesh); mesh.size_vertex = size_vertex; bool ret = load_data((size_t)size_vertex * mesh.num_vertex, vertex, mesh.attrib.m.double_buffer ? 2 : 1, dynamic); free_def(vertex); return ret; } bool obj_mesh_vertex_buffer::load_data(size_t size, const void* data, int32_t count, bool dynamic) { if (!size || count > 3) return false; this->count = count; this->size = (GLsizeiptr)size; #if SHARED_OBJECT_BUFFER offset = 0; #endif glGenBuffers(count, buffers); for (int32_t i = 0; i < count; i++) { gl_state_bind_array_buffer(buffers[i], true); if (GLAD_GL_VERSION_4_4) glBufferStorage(GL_ARRAY_BUFFER, (GLsizeiptr)size, data, dynamic ? GL_DYNAMIC_STORAGE_BIT | GL_MAP_WRITE_BIT : 0); else glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)size, data, dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); } gl_state_bind_array_buffer(0); return true; } void obj_mesh_vertex_buffer::unload() { if (buffers[0]) glDeleteBuffers(count, buffers); count = 0; buffers[0] = 0; #if SHARED_OBJECT_BUFFER offset = 0; #endif size = 0; index = 0; } void* obj_mesh_vertex_buffer::fill_data(void* data, obj_mesh& mesh) { obj_vertex_format vertex_format = mesh.vertex_format; obj_vertex_data* vtx = mesh.vertex_array; uint32_t num_vertex = mesh.num_vertex; size_t d = (size_t)data; if (!mesh.attrib.m.compressed) { size_t size = (size_t)num_vertex * mesh.size_vertex; for (uint32_t i = num_vertex; i; i--, vtx++) { if (vertex_format & OBJ_VERTEX_POSITION) { *(vec3*)d = vtx->position; d += 12; } if (vertex_format & OBJ_VERTEX_NORMAL) { *(vec3*)d = vtx->normal; d += 12; } if (vertex_format & OBJ_VERTEX_TANGENT) { *(vec4*)d = vtx->tangent; d += 16; } if (vertex_format & OBJ_VERTEX_BINORMAL) { *(vec3*)d = vtx->binormal; d += 12; } if (vertex_format & OBJ_VERTEX_TEXCOORD0) { *(vec2*)d = vtx->texcoord0; d += 8; } if (vertex_format & OBJ_VERTEX_TEXCOORD1) { *(vec2*)d = vtx->texcoord1; d += 8; } if (vertex_format & OBJ_VERTEX_TEXCOORD2) { *(vec2*)d = vtx->texcoord2; d += 8; } if (vertex_format & OBJ_VERTEX_TEXCOORD3) { *(vec2*)d = vtx->texcoord3; d += 8; } if (vertex_format & OBJ_VERTEX_COLOR0) { *(vec4*)d = vtx->color0; d += 16; } if (vertex_format & OBJ_VERTEX_COLOR1) { *(vec4*)d = vtx->color1; d += 16; } if (vertex_format & OBJ_VERTEX_BONE_DATA) { *(vec4*)d = vtx->bone_weight; d += 16; *(vec4i16*)d = vtx->bone_index; d += 8; } if (vertex_format & OBJ_VERTEX_UNKNOWN) { *(vec4*)d = vtx->unknown; d += 16; } } } else { for (uint32_t i = num_vertex; i; i--, vtx++) { if (vertex_format & OBJ_VERTEX_POSITION) { *(vec3*)d = vtx->position; d += 12; } if (vertex_format & OBJ_VERTEX_NORMAL) { vec3 normal = vtx->normal * 32727.0f; vec3_to_vec3i16(normal, *(vec3i16*)d); *(int16_t*)(d + 6) = 0; d += 8; } if (vertex_format & OBJ_VERTEX_TANGENT) { vec4 tangent = vtx->tangent * 32727.0f; vec4_to_vec4i16(tangent, *(vec4i16*)d); d += 8; } if (vertex_format & OBJ_VERTEX_TEXCOORD0) { vec2_to_vec2h(vtx->texcoord0, *(vec2h*)d); d += 4; } if (vertex_format & OBJ_VERTEX_TEXCOORD1) { vec2_to_vec2h(vtx->texcoord1, *(vec2h*)d); d += 4; } if (vertex_format & OBJ_VERTEX_TEXCOORD2) { vec2_to_vec2h(vtx->texcoord2, *(vec2h*)d); d += 4; } if (vertex_format & OBJ_VERTEX_TEXCOORD3) { vec2_to_vec2h(vtx->texcoord3, *(vec2h*)d); d += 4; } if (vertex_format & OBJ_VERTEX_COLOR0) { vec4 color0 = vtx->color0; vec4_to_vec4h(color0, *(vec4h*)d); d += 8; } if (vertex_format & OBJ_VERTEX_BONE_DATA) { vec4 bone_weight = vtx->bone_weight * 65535.0f; vec4_to_vec4u16(bone_weight, *(vec4u16*)d); d += 8; *(vec4i16*)d = vtx->bone_index; d += 8; } } } return (void*)d; } #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) { void* data = index; for (uint32_t i = 0; i < mesh_num; i++) { mesh_data[i].size = (GLsizeiptr)buffer_size; 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; } } glGenBuffers(1, &buffer); gl_state_bind_element_array_buffer(buffer, true); if (GLAD_GL_VERSION_4_4) glBufferStorage(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)buffer_size, index, 0); else glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)buffer_size, index, GL_STATIC_DRAW); gl_state_bind_element_array_buffer(0); 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 if (buffer) glDeleteBuffers(1, &buffer); #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 || !mesh.vertex_array) continue; uint32_t size_vertex; if (!mesh.attrib.m.compressed) size_vertex = obj_vertex_format_get_vertex_size(mesh.vertex_format); else size_vertex = obj_vertex_format_get_vertex_size_comp(mesh.vertex_format); mesh.size_vertex = size_vertex; buffer_size += (size_t)size_vertex * mesh.num_vertex; double_buffer |= !!mesh.attrib.m.double_buffer; } uint32_t count = double_buffer ? 2 : 1; void* vertex = force_malloc(buffer_size); if (vertex) { 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]); } } glGenBuffers(count, buffers); for (uint32_t i = 0; i < count; i++) { gl_state_bind_array_buffer(buffers[i], true); if (GLAD_GL_VERSION_4_4) glBufferStorage(GL_ARRAY_BUFFER, (GLsizeiptr)buffer_size, vertex, 0); else glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)buffer_size, vertex, GL_STATIC_DRAW); } gl_state_bind_array_buffer(0); 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 if (buffers[0]) glDeleteBuffers(mesh_data[0].count, buffers); #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 } obj_set_handler::obj_set_handler() : obj_loaded(), tex_loaded(), obj_set(), tex_num(), tex_data(), set_id(), vertex_buffer_num(), vertex_buffer_data(), index_buffer_num(), index_buffer_data(), load_count(), modern() { } obj_set_handler::~obj_set_handler() { if (tex_data) { texture_array_free(tex_data); tex_data = 0; } obj_set_handler_index_buffer_free(this); obj_set_handler_vertex_buffer_free(this); alloc_handler.reset(); while (tex_file_handler.ptr && tex_file_handler.ptr->count) tex_file_handler.reset(); while (obj_file_handler.ptr && obj_file_handler.ptr->count) obj_file_handler.reset(); while (farc_file_handler.ptr && farc_file_handler.ptr->count) farc_file_handler.reset(); } inline int32_t obj_material_texture_type_get_texcoord_index( obj_material_texture_type type, int32_t index) { switch (type) { case OBJ_MATERIAL_TEXTURE_COLOR: case OBJ_MATERIAL_TEXTURE_ENVIRONMENT_SPHERE: // XHD if (index < 2) return index; case OBJ_MATERIAL_TEXTURE_NORMAL: case OBJ_MATERIAL_TEXTURE_SPECULAR: return 0; case OBJ_MATERIAL_TEXTURE_TRANSLUCENCY: case OBJ_MATERIAL_TEXTURE_TRANSPARENCY: return 1; } return -1; } inline int32_t obj_material_texture_type_get_texture_index( obj_material_texture_type type, int32_t base_index) { switch (type) { case OBJ_MATERIAL_TEXTURE_COLOR: case OBJ_MATERIAL_TEXTURE_ENVIRONMENT_SPHERE: // XHD if (base_index < 2) return base_index; case OBJ_MATERIAL_TEXTURE_NORMAL: return 2; case OBJ_MATERIAL_TEXTURE_SPECULAR: return 3; case OBJ_MATERIAL_TEXTURE_TRANSLUCENCY: return 1; case OBJ_MATERIAL_TEXTURE_TRANSPARENCY: return 4; //case OBJ_MATERIAL_TEXTURE_ENVIRONMENT_SPHERE: // AFT case OBJ_MATERIAL_TEXTURE_ENVIRONMENT_CUBE: return 5; } return -1; } 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) { if (!s->num_bone) return; if (mat) for (uint32_t i = 0; i < s->num_bone; i++) { mat4 temp; int32_t bone_id = s->bone_array[i].id; if (bone_id & 0x8000) mat4_mult(mat, &ex_data_matrices[bone_id & 0x7FFF], &temp); else mat4_mult(mat, &matrices[bone_id], &temp); mat4_mult(&temp, global_mat, &temp); mat4_mult(&s->bone_array[i].inv_bind_pose_mat, &temp, &matrix_buffer[i]); } else for (uint32_t i = 0; i < s->num_bone; i++) { mat4 temp; int32_t bone_id = s->bone_array[i].id; if (bone_id & 0x8000) temp = ex_data_matrices[bone_id & 0x7FFF]; else temp = matrices[bone_id]; mat4_mult(&temp, global_mat, &temp); mat4_mult(&s->bone_array[i].inv_bind_pose_mat, &temp, &matrix_buffer[i]); } } void object_material_msgpack_read(const char* path, const char* set_name, obj_set* obj_set, object_database* obj_db) { if (!path_check_directory_exists(path)) return; char set_name_buf[0x80]; for (const char* i = set_name; *i && *i != '.'; i++) { char c = *i; if (c >= 'a' && c <= 'z') c -= 0x20; set_name_buf[i - set_name] = c; set_name_buf[i - set_name + 1] = 0; } char buf[0x200]; sprintf_s(buf, sizeof(buf), "%s\\%s\\", path, set_name_buf); if (!path_check_directory_exists(buf)) return; sprintf_s(buf, sizeof(buf), "%s\\%s\\config.json", path, set_name_buf); if (!path_check_file_exists(buf)) return; msgpack msg; file_stream s; s.open(buf, "rb"); io_json_read(s, &msg); s.close(); if (msg.type != MSGPACK_ARRAY) return; msgpack_array* ptr = msg.data.arr; for (msgpack& i : *ptr) { msgpack& object = i; std::string name = object.read_string("name"); uint32_t name_hash = hash_string_murmurhash(name); for (uint32_t i = 0; i < obj_set->obj_num; i++) { obj* obj = obj_set->obj_data[i]; if (name_hash != hash_string_murmurhash(obj->name)) continue; msgpack* materials = object.read_array("material"); if (materials) { msgpack_array* ptr = materials->data.arr; for (msgpack& j : *ptr) { msgpack& material = j; std::string name = material.read_string("name"); uint32_t name_hash = hash_string_murmurhash(name); for (size_t k = 0; k < obj->num_material; k++) { obj_material& mat = obj->material_array[k].material; if (name_hash != hash_string_murmurhash(mat.name)) continue; msgpack* shader_compo = material.read("shader_compo"); if (shader_compo) { mat.shader_compo.m.color = shader_compo->read_bool("color") ? 1 : 0; mat.shader_compo.m.color_a = shader_compo->read_bool("color_a") ? 1 : 0; mat.shader_compo.m.color_l1 = shader_compo->read_bool("color_l1") ? 1 : 0; mat.shader_compo.m.color_l1_a = shader_compo->read_bool("color_l1_a") ? 1 : 0; mat.shader_compo.m.color_l2 = shader_compo->read_bool("color_l2") ? 1 : 0; mat.shader_compo.m.color_l2_a = shader_compo->read_bool("color_l2_a") ? 1 : 0; mat.shader_compo.m.transparency = shader_compo->read_bool("transparency") ? 1 : 0; mat.shader_compo.m.specular = shader_compo->read_bool("specular") ? 1 : 0; mat.shader_compo.m.normal_01 = shader_compo->read_bool("normal_01") ? 1 : 0; mat.shader_compo.m.normal_02 = shader_compo->read_bool("normal_02") ? 1 : 0; mat.shader_compo.m.envmap = shader_compo->read_bool("envmap") ? 1 : 0; mat.shader_compo.m.color_l3 = shader_compo->read_bool("color_l3") ? 1 : 0; mat.shader_compo.m.color_l3_a = shader_compo->read_bool("color_l3_a") ? 1 : 0; mat.shader_compo.m.translucency = shader_compo->read_bool("translucency") ? 1 : 0; mat.shader_compo.m.flag_14 = shader_compo->read_bool("flag_14") ? 1 : 0; mat.shader_compo.m.override_ibl = shader_compo->read_bool("override_ibl") ? 1 : 0; mat.shader_compo.m.dummy = shader_compo->read_uint32_t("dummy"); } msgpack* _shader_name = material.read("shader_name"); if (_shader_name) { std::string shader_name = _shader_name->read_string(); size_t name_length = min_def(sizeof(mat.shader.name) - 1, shader_name.size()); memcpy_s(mat.shader.name, sizeof(mat.shader.name) - 1, shader_name.c_str(), name_length); mat.shader.name[name_length] = 0; } msgpack* shader_info = material.read("shader_info"); if (shader_info) { mat.shader_info.m.vtx_trans_type = (obj_material_vertex_translation_type) shader_info->read_uint32_t("vtx_trans_type"); mat.shader_info.m.col_src = (obj_material_color_source_type)shader_info->read_uint32_t("col_src"); mat.shader_info.m.is_lgt_diffuse = shader_info->read_bool("is_lgt_diffuse") ? 1 : 0; mat.shader_info.m.is_lgt_specular = shader_info->read_bool("is_lgt_specular") ? 1 : 0; mat.shader_info.m.is_lgt_per_pixel = shader_info->read_bool("is_lgt_per_pixel") ? 1 : 0; mat.shader_info.m.is_lgt_double = shader_info->read_bool("is_lgt_double") ? 1 : 0; mat.shader_info.m.bump_map_type = (obj_material_bump_map_type) shader_info->read_uint32_t("bump_map_type"); mat.shader_info.m.fresnel_type = shader_info->read_uint32_t("fresnel_type"); mat.shader_info.m.line_light = shader_info->read_uint32_t("line_light"); mat.shader_info.m.recieve_shadow = shader_info->read_bool("recieve_shadow") ? 1 : 0; mat.shader_info.m.cast_shadow = shader_info->read_bool("cast_shadow") ? 1 : 0; mat.shader_info.m.specular_quality = (obj_material_specular_quality) shader_info->read_uint32_t("specular_quality"); mat.shader_info.m.aniso_direction = (obj_material_aniso_direction) shader_info->read_uint32_t("aniso_direction"); mat.shader_info.m.dummy = shader_info->read_uint32_t("dummy"); } int32_t num_of_textures = 0; msgpack* texdata = material.read("texdata"); if (texdata) { for (obj_material_texture_data& l : mat.texdata) { sprintf_s(buf, sizeof(buf), "%d", (int32_t)(&l - mat.texdata)); msgpack* tex = texdata->read(buf); l.tex_index = -1; if (!tex) continue; msgpack* attrib = tex->read("attrib"); if (attrib) { l.attrib.m.repeat_u = attrib->read_bool("repeat_u") ? 1 : 0; l.attrib.m.repeat_v = attrib->read_bool("repeat_v") ? 1 : 0; l.attrib.m.mirror_u = attrib->read_bool("mirror_u") ? 1 : 0; l.attrib.m.mirror_v = attrib->read_bool("mirror_v") ? 1 : 0; l.attrib.m.ignore_alpha = attrib->read_bool("ignore_alpha") ? 1 : 0; l.attrib.m.blend = attrib->read_uint32_t("blend"); l.attrib.m.alpha_blend = attrib->read_uint32_t("alpha_blend"); l.attrib.m.border = attrib->read_bool("border") ? 1 : 0; l.attrib.m.clamp2edge = attrib->read_bool("clamp2edge") ? 1 : 0; l.attrib.m.filter = attrib->read_uint32_t("filter"); l.attrib.m.mipmap = attrib->read_uint32_t("mipmap"); l.attrib.m.mipmap_bias = attrib->read_uint32_t("mipmap_bias"); l.attrib.m.flag_29 = attrib->read_bool("flag_29") ? 1 : 0; l.attrib.m.anisotropic_filter = attrib->read_uint32_t("anisotropic_filter"); } msgpack* _tex_name = tex->read("tex_name"); if (_tex_name) { std::string tex_name = _tex_name->read_string(); l.tex_index = hash_string_murmurhash(tex_name); } msgpack* shader_info = tex->read("shader_info"); if (shader_info) { l.shader_info.m.tex_type = (obj_material_texture_type) shader_info->read_uint32_t("tex_type"); l.shader_info.m.uv_idx = shader_info->read_uint32_t("uv_idx"); l.shader_info.m.texcoord_trans = (obj_material_texture_coordinate_translation_type) shader_info->read_uint32_t("texcoord_trans"); l.shader_info.m.dummy = shader_info->read_uint32_t("dummy"); } msgpack* _ex_shader = material.read("ex_shader"); if (_ex_shader) { std::string shader_name = _ex_shader->read_string(); size_t name_length = min_def(sizeof(l.ex_shader) - 1, shader_name.size()); memcpy_s(l.ex_shader, sizeof(l.ex_shader) - 1, shader_name.c_str(), name_length); l.ex_shader[name_length] = 0; } msgpack* weight = tex->read("weight"); if (weight) l.weight = weight->read_float_t(); msgpack* tex_coord_mat = tex->read_array("tex_coord_mat"); if (tex_coord_mat) { msgpack_array* tex_coord_mat_ptr = tex_coord_mat->data.arr; { msgpack& row0 = tex_coord_mat_ptr->data()[0]; msgpack_array* row0_ptr = row0.data.arr; l.tex_coord_mat.row0.x = row0_ptr->data()[0].read_float_t(); l.tex_coord_mat.row0.y = row0_ptr->data()[1].read_float_t(); l.tex_coord_mat.row0.z = row0_ptr->data()[2].read_float_t(); l.tex_coord_mat.row0.w = row0_ptr->data()[3].read_float_t(); } { msgpack& row1 = tex_coord_mat_ptr->data()[1]; msgpack_array* row1_ptr = row1.data.arr; l.tex_coord_mat.row1.x = row1_ptr->data()[0].read_float_t(); l.tex_coord_mat.row1.y = row1_ptr->data()[1].read_float_t(); l.tex_coord_mat.row1.z = row1_ptr->data()[2].read_float_t(); l.tex_coord_mat.row1.w = row1_ptr->data()[3].read_float_t(); } { msgpack& row2 = tex_coord_mat_ptr->data()[2]; msgpack_array* row2_ptr = row2.data.arr; l.tex_coord_mat.row2.x = row2_ptr->data()[0].read_float_t(); l.tex_coord_mat.row2.y = row2_ptr->data()[1].read_float_t(); l.tex_coord_mat.row2.z = row2_ptr->data()[2].read_float_t(); l.tex_coord_mat.row2.w = row2_ptr->data()[3].read_float_t(); } { msgpack& row3 = tex_coord_mat_ptr->data()[3]; msgpack_array* row3_ptr = row3.data.arr; l.tex_coord_mat.row3.x = row3_ptr->data()[0].read_float_t(); l.tex_coord_mat.row3.y = row3_ptr->data()[1].read_float_t(); l.tex_coord_mat.row3.z = row3_ptr->data()[2].read_float_t(); l.tex_coord_mat.row3.w = row3_ptr->data()[3].read_float_t(); } } msgpack* reserved = tex->read_array("reserved"); if (reserved) { msgpack_array* ptr = reserved->data.arr; for (int32_t m = 0; m < 8; m++) l.reserved[m] = ptr->data()[m].read_uint32_t(); } num_of_textures++; } } obj->material_array[k].num_of_textures = num_of_textures; msgpack* attrib = material.read("attrib"); if (attrib) { mat.attrib.m.alpha_texture = attrib->read_bool("alpha_texture") ? 1 : 0; mat.attrib.m.alpha_material = attrib->read_bool("alpha_material") ? 1 : 0; mat.attrib.m.punch_through = attrib->read_bool("punch_through") ? 1 : 0; mat.attrib.m.double_sided = attrib->read_bool("double_sided") ? 1 : 0; mat.attrib.m.normal_dir_light = attrib->read_bool("normal_dir_light") ? 1 : 0; mat.attrib.m.src_blend_factor = (obj_material_blend_factor) attrib->read_uint32_t("src_blend_factor"); mat.attrib.m.dst_blend_factor = (obj_material_blend_factor) attrib->read_uint32_t("dst_blend_factor"); mat.attrib.m.blend_operation = attrib->read_uint32_t("blend_operation"); mat.attrib.m.zbias = attrib->read_uint32_t("zbias"); mat.attrib.m.no_fog = attrib->read_bool("no_fog") ? 1 : 0; mat.attrib.m.translucent_priority = attrib->read_uint32_t("translucent_priority"); mat.attrib.m.has_fog_height = attrib->read_bool("has_fog_height") ? 1 : 0; mat.attrib.m.flag_28 = attrib->read_bool("flag_28") ? 1 : 0; mat.attrib.m.fog_height = attrib->read_bool("fog_height") ? 1 : 0; mat.attrib.m.flag_30 = attrib->read_bool("flag_30") ? 1 : 0; mat.attrib.m.flag_31 = attrib->read_bool("flag_31") ? 1 : 0; } msgpack* color = material.read("color"); if (color) { msgpack* diffuse = color->read("diffuse"); if (diffuse) { mat.color.diffuse.x = diffuse->read_float_t("r"); mat.color.diffuse.y = diffuse->read_float_t("g"); mat.color.diffuse.z = diffuse->read_float_t("b"); mat.color.diffuse.w = diffuse->read_float_t("a"); } msgpack* ambient = color->read("ambient"); if (ambient) { mat.color.ambient.x = ambient->read_float_t("r"); mat.color.ambient.y = ambient->read_float_t("g"); mat.color.ambient.z = ambient->read_float_t("b"); mat.color.ambient.w = ambient->read_float_t("a"); } msgpack* specular = color->read("specular"); if (specular) { mat.color.specular.x = specular->read_float_t("r"); mat.color.specular.y = specular->read_float_t("g"); mat.color.specular.z = specular->read_float_t("b"); mat.color.specular.w = specular->read_float_t("a"); } msgpack* emission = color->read("emission"); if (emission) { mat.color.emission.x = emission->read_float_t("r"); mat.color.emission.y = emission->read_float_t("g"); mat.color.emission.z = emission->read_float_t("b"); mat.color.emission.w = emission->read_float_t("a"); } msgpack* shininess = color->read("shininess"); if (shininess) mat.color.shininess = shininess->read_float_t(); msgpack* intensity = color->read("intensity"); if (intensity) mat.color.intensity = intensity->read_float_t(); } msgpack* center = material.read("center"); if (center) { mat.center.x = center->read_float_t("x"); mat.center.y = center->read_float_t("y"); mat.center.z = center->read_float_t("z"); } msgpack* radius = material.read("radius"); if (radius) mat.radius = radius->read_float_t(); msgpack* bump_depth = material.read("bump_depth"); if (bump_depth) mat.radius = bump_depth->read_float_t(); msgpack* reserved = material.read_array("reserved"); if (reserved) { msgpack_array* ptr = reserved->data.arr; for (int32_t m = 0; m < 15; m++) mat.reserved[m] = ptr->data()[m].read_uint32_t(); } break; } } } msgpack* meshes = object.read_array("mesh"); if (meshes) { msgpack_array* ptr = meshes->data.arr; for (msgpack& j : *ptr) { msgpack& _mesh = j; std::string name = _mesh.read_string("name"); uint32_t name_hash = hash_string_murmurhash(name); for (size_t k = 0; k < obj->num_mesh; k++) { obj_mesh& mesh = obj->mesh_array[k]; if (name_hash != hash_string_murmurhash(mesh.name)) continue; msgpack* sub_meshes = _mesh.read_array("sub_mesh"); if (!sub_meshes) continue; msgpack_array* ptr = sub_meshes->data.arr; for (size_t l = 0; l < mesh.num_submesh; l++) { obj_sub_mesh& sub_mesh = mesh.submesh_array[l]; msgpack& _sub_mesh = ptr->data()[l]; msgpack* attrib = _sub_mesh.read("attrib"); if (attrib) { msgpack* recieve_shadow = attrib->read("recieve_shadow"); msgpack* cast_shadow = attrib->read("cast_shadow"); msgpack* transparent = attrib->read("transparent"); if (recieve_shadow) sub_mesh.attrib.m.recieve_shadow = recieve_shadow->read_bool(); if (cast_shadow) sub_mesh.attrib.m.cast_shadow = cast_shadow->read_bool(); if (transparent) sub_mesh.attrib.m.transparent = transparent->read_bool(); } } break; } } } break; } } } void object_material_msgpack_read(const char* path, const char* set_name, txp_set* txp_set, texture_database* tex_db, obj_set_handler* handler) { if (!tex_db || !path_check_directory_exists(path)) return; char set_name_buf[0x80]; for (const char* i = set_name; *i && *i != '.'; i++) { char c = *i; if (c >= 'a' && c <= 'z') c -= 0x20; set_name_buf[i - set_name] = c; set_name_buf[i - set_name + 1] = 0; } char buf[0x200]; sprintf_s(buf, sizeof(buf), "%s\\%s\\", path, set_name_buf); if (!path_check_directory_exists(buf)) return; sprintf_s(buf, sizeof(buf), "%s\\%s\\config_tex.json", path, set_name_buf); if (!path_check_file_exists(buf)) return; msgpack msg; file_stream s; s.open(buf, "rb"); io_json_read(s, &msg); s.close(); if (msg.type != MSGPACK_MAP) return; obj_set* set = handler->obj_set; msgpack* add = msg.read_array("Add"); if (add) { std::vector ids; msgpack_array* ptr = add->data.arr; for (msgpack& i : *ptr) { std::string name = i.read_string(); if (!name.size()) continue; sprintf_s(buf, sizeof(buf), "%s\\%s\\%s.dds", path, set_name_buf, name.c_str()); if (!path_check_file_exists(buf)) continue; dds d; sprintf_s(buf, sizeof(buf), "%s\\%s\\%s", path, set_name_buf, name.c_str()); d.read(buf); if (!d.width || !d.height || !d.mipmaps_count || d.data.size() < 1) continue; uint32_t id = hash_string_murmurhash(name); ids.push_back(id); tex_db->texture.emplace_back(); texture_info* info = &tex_db->texture.back(); info->name.assign(name); info->name_hash = hash_string_murmurhash(info->name); info->id = id; txp_set->textures.push_back({}); txp* tex = &txp_set->textures.back(); tex->array_size = d.has_cube_map ? 6 : 1; tex->has_cube_map = d.has_cube_map; tex->mipmaps_count = d.mipmaps_count; tex->mipmaps.reserve((tex->has_cube_map ? 6LL : 1LL) * tex->mipmaps_count); int32_t index = 0; do for (uint32_t i = 0; i < tex->mipmaps_count; i++) { txp_mipmap tex_mip; tex_mip.width = max_def(d.width >> i, 1); tex_mip.height = max_def(d.height >> i, 1); tex_mip.format = d.format; uint32_t size = txp::get_size(tex_mip.format, tex_mip.width, tex_mip.height); tex_mip.size = size; tex_mip.data.resize(size); memcpy(tex_mip.data.data(), d.data[index], size); tex->mipmaps.push_back(tex_mip); index++; } while (index / tex->mipmaps_count < tex->array_size); } tex_db->sort(); size_t tex_id_num = txp_set->textures.size(); if (set->tex_id_num != tex_id_num) { uint32_t* tex_id_data = handler->alloc_handler->allocate(tex_id_num); memmove(tex_id_data, set->tex_id_data, sizeof(uint32_t) * set->tex_id_num); memmove(&tex_id_data[set->tex_id_num], ids.data(), sizeof(uint32_t) * (tex_id_num - set->tex_id_num)); set->tex_id_data = tex_id_data; set->tex_id_num = (uint32_t)tex_id_num; handler->tex_num = (uint32_t)tex_id_num; } } msgpack* replace = msg.read_array("Replace"); if (replace) { msgpack_array* ptr = replace->data.arr; for (msgpack& i : *ptr) { std::string name = i.read_string(); if (!name.size()) continue; sprintf_s(buf, sizeof(buf), "%s\\%s\\%s.dds", path, set_name_buf, name.c_str()); if (!path_check_file_exists(buf)) continue; dds d; sprintf_s(buf, sizeof(buf), "%s\\%s\\%s", path, set_name_buf, name.c_str()); d.read(buf); if (!d.width || !d.height || !d.mipmaps_count || d.data.size() < 1) continue; uint32_t id = hash_string_murmurhash(name); uint32_t* tex_id_data = set->tex_id_data; uint32_t tex_id_num = set->tex_id_num; txp* tex = 0; for (uint32_t i = 0; i < tex_id_num; i++) if (id == tex_id_data[i]) { tex = &txp_set->textures[i]; break; } if (!tex) continue; tex->array_size = d.has_cube_map ? 6 : 1; tex->has_cube_map = d.has_cube_map; tex->mipmaps_count = d.mipmaps_count; tex->mipmaps.clear(); tex->mipmaps.reserve((tex->has_cube_map ? 6LL : 1LL) * tex->mipmaps_count); int32_t index = 0; do for (uint32_t i = 0; i < tex->mipmaps_count; i++) { txp_mipmap tex_mip; tex_mip.width = max_def(d.width >> i, 1); tex_mip.height = max_def(d.height >> i, 1); tex_mip.format = d.format; uint32_t size = txp::get_size(tex_mip.format, tex_mip.width, tex_mip.height); tex_mip.size = size; tex_mip.data.resize(size); memcpy(tex_mip.data.data(), d.data[index], size); tex->mipmaps.push_back(tex_mip); index++; } while (index / tex->mipmaps_count < tex->array_size); } } } void object_material_msgpack_write(const char* path, const char* set_name, uint32_t set_id, obj_set* obj_set, txp_set* txp_set, object_database* obj_db, texture_database* tex_db) { if (!path_check_directory_exists(path) && !CreateDirectoryA(path, 0)) return; char buf[0x200]; sprintf_s(buf, sizeof(buf), "%s\\%s\\", path, set_name); if (!path_check_directory_exists(buf) && !CreateDirectoryA(buf, 0)) return; msgpack_array objects(obj_set->obj_num); for (uint32_t i = 0; i < obj_set->obj_num; i++) { obj* obj = obj_set->obj_data[i]; msgpack& object = objects.data()[i]; object = msgpack(msgpack_map()); object.append("name", obj->name); msgpack* materials = object.append("material", msgpack_array()); if (materials) { msgpack_array* ptr = materials->data.arr; ptr->resize(obj->num_material); for (size_t j = 0; j < obj->num_material; j++) { obj_material& mat = obj->material_array[j].material; msgpack& material = ptr->data()[j]; material = msgpack_map(); msgpack* shader_compo = material.append("shader_compo", msgpack_map()); if (shader_compo) { shader_compo->append("color", (bool)mat.shader_compo.m.color); shader_compo->append("color_a", (bool)mat.shader_compo.m.color_a); shader_compo->append("color_l1", (bool)mat.shader_compo.m.color_l1); shader_compo->append("color_l1_a", (bool)mat.shader_compo.m.color_l1_a); shader_compo->append("color_l2", (bool)mat.shader_compo.m.color_l2); shader_compo->append("color_l2_a", (bool)mat.shader_compo.m.color_l2_a); shader_compo->append("transparency", (bool)mat.shader_compo.m.transparency); shader_compo->append("specular", (bool)mat.shader_compo.m.specular); shader_compo->append("normal_01", (bool)mat.shader_compo.m.normal_01); shader_compo->append("normal_02", (bool)mat.shader_compo.m.normal_02); shader_compo->append("envmap", (bool)mat.shader_compo.m.envmap); shader_compo->append("color_l3", (bool)mat.shader_compo.m.color_l3); shader_compo->append("color_l3_a", (bool)mat.shader_compo.m.color_l3_a); shader_compo->append("translucency", (bool)mat.shader_compo.m.translucency); shader_compo->append("flag_14", (bool)mat.shader_compo.m.flag_14); shader_compo->append("override_ibl", (bool)mat.shader_compo.m.override_ibl); shader_compo->append("dummy", mat.shader_compo.m.dummy); } material.append("shader_name", mat.shader.name); msgpack* shader_info = material.append("shader_info", msgpack_map()); if (shader_info) { shader_info->append("vtx_trans_type", mat.shader_info.m.vtx_trans_type); shader_info->append("col_src", mat.shader_info.m.col_src); shader_info->append("is_lgt_diffuse", (bool)mat.shader_info.m.is_lgt_diffuse); shader_info->append("is_lgt_specular", (bool)mat.shader_info.m.is_lgt_specular); shader_info->append("is_lgt_per_pixel", (bool)mat.shader_info.m.is_lgt_per_pixel); shader_info->append("is_lgt_double", (bool)mat.shader_info.m.is_lgt_double); shader_info->append("bump_map_type", mat.shader_info.m.bump_map_type); shader_info->append("fresnel_type", mat.shader_info.m.fresnel_type); shader_info->append("line_light", mat.shader_info.m.line_light); shader_info->append("recieve_shadow", (bool)mat.shader_info.m.recieve_shadow); shader_info->append("cast_shadow", (bool)mat.shader_info.m.cast_shadow); shader_info->append("specular_quality", mat.shader_info.m.specular_quality); shader_info->append("aniso_direction", mat.shader_info.m.aniso_direction); shader_info->append("dummy", mat.shader_info.m.dummy); } msgpack* texdata = material.append("texdata", msgpack_map()); if (texdata) { for (obj_material_texture_data& k : mat.texdata) { if (!k.tex_index || k.tex_index == -1 || k.tex_index == hash_murmurhash_empty || k.tex_index == hash_murmurhash_null) continue; sprintf_s(buf, sizeof(buf), "%d", (int32_t)(&k - mat.texdata)); msgpack& tex = *texdata->append(buf, msgpack_map()); msgpack* attrib = tex.append("attrib", msgpack_map()); if (attrib) { attrib->append("repeat_u", (bool)k.attrib.m.repeat_u); attrib->append("repeat_v", (bool)k.attrib.m.repeat_v); attrib->append("mirror_u", (bool)k.attrib.m.mirror_u); attrib->append("mirror_v", (bool)k.attrib.m.mirror_v); attrib->append("ignore_alpha", (bool)k.attrib.m.ignore_alpha); attrib->append("blend", k.attrib.m.blend); attrib->append("alpha_blend", k.attrib.m.alpha_blend); attrib->append("border", (bool)k.attrib.m.border); attrib->append("clamp2edge", (bool)k.attrib.m.clamp2edge); attrib->append("filter", k.attrib.m.filter); attrib->append("mipmap", k.attrib.m.mipmap); attrib->append("mipmap_bias", k.attrib.m.mipmap_bias); attrib->append("flag_29", (bool)k.attrib.m.flag_29); attrib->append("anisotropic_filter", k.attrib.m.anisotropic_filter); } tex.append("tex_name", tex_db->get_texture_name(k.tex_index)); msgpack* shader_info = tex.append("shader_info", msgpack_map()); if (shader_info) { shader_info->append("tex_type", k.shader_info.m.tex_type); shader_info->append("uv_idx", k.shader_info.m.uv_idx); shader_info->append("texcoord_trans", k.shader_info.m.texcoord_trans); shader_info->append("dummy", k.shader_info.m.dummy); } tex.append("ex_shader", k.ex_shader); tex.append("weight", k.weight); msgpack* tex_coord_mat = tex.append("tex_coord_mat", msgpack_array()); if (tex_coord_mat) { msgpack_array* tex_coord_mat_ptr = tex_coord_mat->data.arr; tex_coord_mat_ptr->resize(4); { msgpack& row0 = tex_coord_mat_ptr->data()[0]; row0 = msgpack_array(); msgpack_array* row0_ptr = row0.data.arr; row0_ptr->resize(4); row0_ptr->data()[0] = k.tex_coord_mat.row0.x; row0_ptr->data()[1] = k.tex_coord_mat.row0.y; row0_ptr->data()[2] = k.tex_coord_mat.row0.z; row0_ptr->data()[3] = k.tex_coord_mat.row0.w; } { msgpack& row1 = tex_coord_mat_ptr->data()[1]; row1 = msgpack_array(); msgpack_array* row1_ptr = row1.data.arr; row1_ptr->resize(4); row1_ptr->data()[0] = k.tex_coord_mat.row1.x; row1_ptr->data()[1] = k.tex_coord_mat.row1.y; row1_ptr->data()[2] = k.tex_coord_mat.row1.z; row1_ptr->data()[3] = k.tex_coord_mat.row1.w; } { msgpack& row2 = tex_coord_mat_ptr->data()[2]; row2 = msgpack_array(); msgpack_array* row2_ptr = row2.data.arr; row2_ptr->resize(4); row2_ptr->data()[0] = k.tex_coord_mat.row2.x; row2_ptr->data()[1] = k.tex_coord_mat.row2.y; row2_ptr->data()[2] = k.tex_coord_mat.row2.z; row2_ptr->data()[3] = k.tex_coord_mat.row2.w; } { msgpack& row3 = tex_coord_mat_ptr->data()[3]; row3 = msgpack_array(); msgpack_array* row3_ptr = row3.data.arr; row3_ptr->resize(4); row3_ptr->data()[0] = k.tex_coord_mat.row3.x; row3_ptr->data()[1] = k.tex_coord_mat.row3.y; row3_ptr->data()[2] = k.tex_coord_mat.row3.z; row3_ptr->data()[3] = k.tex_coord_mat.row3.w; } } msgpack* reserved = tex.append("reserved", msgpack_array()); if (reserved) { msgpack_array* ptr = reserved->data.arr; ptr->resize(8); for (int32_t l = 0; l < 8; l++) ptr->data()[l] = k.reserved[l]; } } } msgpack* attrib = material.append("attrib", msgpack_map()); if (attrib) { attrib->append("alpha_texture", (bool)mat.attrib.m.alpha_texture); attrib->append("alpha_material", (bool)mat.attrib.m.alpha_material); attrib->append("punch_through", (bool)mat.attrib.m.punch_through); attrib->append("double_sided", (bool)mat.attrib.m.double_sided); attrib->append("normal_dir_light", (bool)mat.attrib.m.normal_dir_light); attrib->append("src_blend_factor", mat.attrib.m.src_blend_factor); attrib->append("dst_blend_factor", mat.attrib.m.dst_blend_factor); attrib->append("blend_operation", mat.attrib.m.blend_operation); attrib->append("zbias", mat.attrib.m.zbias); attrib->append("no_fog", (bool)mat.attrib.m.no_fog); attrib->append("translucent_priority", mat.attrib.m.translucent_priority); attrib->append("has_fog_height", (bool)mat.attrib.m.has_fog_height); attrib->append("flag_28", (bool)mat.attrib.m.flag_28); attrib->append("fog_height", (bool)mat.attrib.m.fog_height); attrib->append("flag_30", (bool)mat.attrib.m.flag_30); attrib->append("flag_31", (bool)mat.attrib.m.flag_31); } msgpack* color = material.append("color", msgpack_map()); if (color) { msgpack* diffuse = color->append("diffuse", msgpack_map()); if (diffuse) { diffuse->append("r", mat.color.diffuse.x); diffuse->append("g", mat.color.diffuse.y); diffuse->append("b", mat.color.diffuse.z); diffuse->append("a", mat.color.diffuse.w); } msgpack* ambient = color->append("ambient", msgpack_map()); if (ambient) { ambient->append("r", mat.color.ambient.x); ambient->append("g", mat.color.ambient.y); ambient->append("b", mat.color.ambient.z); ambient->append("a", mat.color.ambient.w); } msgpack* specular = color->append("specular", msgpack_map()); if (specular) { specular->append("r", mat.color.specular.x); specular->append("g", mat.color.specular.y); specular->append("b", mat.color.specular.z); specular->append("a", mat.color.specular.w); } msgpack* emission = color->append("emission", msgpack_map()); if (emission) { emission->append("r", mat.color.emission.x); emission->append("g", mat.color.emission.y); emission->append("b", mat.color.emission.z); emission->append("a", mat.color.emission.w); } color->append("shininess", mat.color.shininess); color->append("intensity", mat.color.intensity); } msgpack* center = material.append("center", msgpack_map()); if (center) { center->append("x", mat.center.x); center->append("y", mat.center.y); center->append("z", mat.center.z); } material.append("radius", mat.radius); material.append("name", mat.name); material.append("bump_depth", mat.bump_depth); msgpack* reserved = material.append("reserved", msgpack_array()); if (reserved) { msgpack_array* ptr = reserved->data.arr; ptr->resize(15); for (int32_t k = 0; k < 15; k++) ptr->data()[k] = mat.reserved[k]; } } } msgpack* meshes = object.append("mesh", msgpack_array()); if (meshes) { msgpack_array* ptr = meshes->data.arr; ptr->resize(obj->num_mesh); for (size_t j = 0; j < obj->num_mesh; j++) { obj_mesh& mesh = obj->mesh_array[j]; msgpack& _mesh = ptr->data()[j]; _mesh = msgpack_map(); _mesh.append("name", mesh.name); msgpack* sub_meshes = _mesh.append("sub_mesh", msgpack_array()); if (sub_meshes) { msgpack_array* ptr = sub_meshes->data.arr; ptr->resize(mesh.num_submesh); for (size_t k = 0; k < mesh.num_submesh; k++) { obj_sub_mesh& sub_mesh = mesh.submesh_array[k]; msgpack& _sub_mesh = ptr->data()[k]; _sub_mesh = msgpack_map(); { msgpack attrib = msgpack_map(); attrib.append("recieve_shadow", (bool)sub_mesh.attrib.m.recieve_shadow); attrib.append("cast_shadow", (bool)sub_mesh.attrib.m.cast_shadow); _sub_mesh.append("attrib", attrib); } } } } } } msgpack msg = objects; sprintf_s(buf, sizeof(buf), "%s\\%s\\config.json", path, set_name); file_stream s; s.open(buf, "wb"); io_json_write(s, &msg); s.close(); for (uint32_t i = 0; i < obj_set->tex_id_num; i++) { const char* texture_name = tex_db->get_texture_name(obj_set->tex_id_data[i]); txp& tex = txp_set->textures[i]; txp_format format = tex.mipmaps[0].format; uint32_t width = tex.mipmaps[0].width; uint32_t height = tex.mipmaps[0].height; dds d; d.format = format; d.width = width; d.height = height; d.mipmaps_count = tex.mipmaps_count; d.has_cube_map = tex.has_cube_map; d.data.reserve((tex.has_cube_map ? 6LL : 1LL) * tex.mipmaps_count); uint32_t index = 0; do for (uint32_t j = 0; j < tex.mipmaps_count; j++) { uint32_t size = txp::get_size(format, max_def(width >> j, 1), max_def(height >> j, 1)); void* data = force_malloc(size); memcpy(data, tex.mipmaps[index].data.data(), size); d.data.push_back(data); index++; } while (index / tex.mipmaps_count < tex.array_size); sprintf_s(buf, sizeof(buf), "%s\\%s\\%s", path, set_name, texture_name); d.write(buf); } } inline void object_storage_init(const object_database* obj_db) { for (const object_set_info& i : obj_db->object_set) { obj_set_handler handler; handler.set_id = i.id; handler.name.assign(i.name); object_storage_data.insert({ i.id, handler }); } object_storage_data_modern.clear(); } inline obj* object_storage_get_obj(object_info obj_info) { auto elem = object_storage_data.find(obj_info.set_id); if (elem != object_storage_data.end()) { obj_set* set = elem->second.obj_set; if (set) for (uint32_t j = 0; j < set->obj_num; j++) if (set->obj_data[j]->id == obj_info.id) return set->obj_data[j]; return 0; } auto elem_modern = object_storage_data_modern.find(obj_info.set_id); if (elem_modern != object_storage_data_modern.end()) { obj_set* set = elem_modern->second.obj_set; if (set) for (uint32_t j = 0; j < set->obj_num; j++) if (set->obj_data[j]->id == obj_info.id) return set->obj_data[j]; return 0; } return 0; } inline obj_set_handler* object_storage_get_obj_set_handler(uint32_t set_id) { auto elem = object_storage_data.find(set_id); if (elem != object_storage_data.end()) return &elem->second; auto elem_modern = object_storage_data_modern.find(set_id); if (elem_modern != object_storage_data_modern.end()) return &elem_modern->second; return 0; } inline obj_mesh* object_storage_get_obj_mesh(object_info obj_info, const char* mesh_name) { auto elem = object_storage_data.find(obj_info.set_id); if (elem != object_storage_data.end()) { obj_set* set = elem->second.obj_set; if (set) for (uint32_t j = 0; j < set->obj_num; j++) if (set->obj_data[j]->id == obj_info.id) return set->obj_data[j]->get_obj_mesh(mesh_name); return 0; } auto elem_modern = object_storage_data_modern.find(obj_info.set_id); if (elem_modern != object_storage_data_modern.end()) { obj_set* set = elem_modern->second.obj_set; if (set) for (uint32_t j = 0; j < set->obj_num; j++) if (set->obj_data[j]->id == obj_info.id) return set->obj_data[j]->get_obj_mesh(mesh_name); return 0; } return 0; } inline obj_mesh* object_storage_get_obj_mesh_by_index(object_info obj_info, uint32_t index) { auto elem = object_storage_data.find(obj_info.set_id); if (elem != object_storage_data.end()) { obj_set* set = elem->second.obj_set; if (!set) return 0; for (uint32_t j = 0; j < set->obj_num; j++) { if (set->obj_data[j]->id != obj_info.id) continue; obj* obj = set->obj_data[j]; if (index >= 0 && index < obj->num_mesh) return &obj->mesh_array[index]; return 0; } return 0; } auto elem_modern = object_storage_data_modern.find(obj_info.set_id); if (elem_modern != object_storage_data_modern.end()) { obj_set* set = elem_modern->second.obj_set; if (!set) return 0; for (uint32_t j = 0; j < set->obj_num; j++) { if (set->obj_data[j]->id != obj_info.id) continue; obj* obj = set->obj_data[j]; if (index >= 0 && index < obj->num_mesh) return &obj->mesh_array[index]; return 0; } return 0; } return 0; } inline obj_mesh* object_storage_get_obj_mesh_by_object_hash(uint32_t hash, const char* mesh_name) { for (auto& i : object_storage_data) { obj_set* set = i.second.obj_set; if (!set) continue; for (uint32_t j = 0; j < set->obj_num; j++) if (set->obj_data[j]->hash == hash) return set->obj_data[j]->get_obj_mesh(mesh_name); } for (auto& i : object_storage_data_modern) { obj_set* set = i.second.obj_set; if (!set) continue; for (uint32_t j = 0; j < set->obj_num; j++) if (set->obj_data[j]->hash == hash) return set->obj_data[j]->get_obj_mesh(mesh_name); } return 0; } inline obj_mesh* object_storage_get_obj_mesh_by_object_hash_index(uint32_t hash, uint32_t index) { for (auto& i : object_storage_data) { obj_set* set = i.second.obj_set; if (!set) continue; for (uint32_t j = 0; j < set->obj_num; j++) { if (set->obj_data[j]->hash != hash) continue; obj* obj = set->obj_data[j]; if (index >= 0 && index < obj->num_mesh) return &obj->mesh_array[index]; return 0; } } for (auto& i : object_storage_data_modern) { obj_set* set = i.second.obj_set; if (!set) continue; for (uint32_t j = 0; j < set->obj_num; j++) { if (set->obj_data[j]->hash != hash) continue; obj* obj = set->obj_data[j]; if (index >= 0 && index < obj->num_mesh) return &obj->mesh_array[index]; return 0; } } return 0; } inline uint32_t object_storage_get_obj_mesh_index(object_info obj_info, const char* mesh_name) { auto elem = object_storage_data.find(obj_info.set_id); if (elem != object_storage_data.end()) { obj_set* set = elem->second.obj_set; if (!set) return -1; for (uint32_t j = 0; j < set->obj_num; j++) if (set->obj_data[j]->id == obj_info.id) return set->obj_data[j]->get_obj_mesh_index(mesh_name); } auto elem_modern = object_storage_data_modern.find(obj_info.set_id); if (elem_modern != object_storage_data_modern.end()) { obj_set* set = elem_modern->second.obj_set; if (!set) return -1; for (uint32_t j = 0; j < set->obj_num; j++) if (set->obj_data[j]->id == obj_info.id) return set->obj_data[j]->get_obj_mesh_index(mesh_name); } return -1; } inline uint32_t object_storage_get_obj_mesh_index_by_hash(uint32_t hash, const char* mesh_name) { for (auto& i : object_storage_data) { obj_set* set = i.second.obj_set; if (!set) continue; for (uint32_t j = 0; j < set->obj_num; j++) if (set->obj_data[j]->hash == hash) return set->obj_data[j]->get_obj_mesh_index(mesh_name); } for (auto& i : object_storage_data_modern) { obj_set* set = i.second.obj_set; if (!set) continue; for (uint32_t j = 0; j < set->obj_num; j++) if (set->obj_data[j]->hash == hash) return set->obj_data[j]->get_obj_mesh_index(mesh_name); } return -1; } inline obj_set* object_storage_get_obj_set(uint32_t set_id) { auto elem = object_storage_data.find(set_id); if (elem != object_storage_data.end()) return elem->second.obj_set; auto elem_modern = object_storage_data_modern.find(set_id); if (elem_modern != object_storage_data_modern.end()) return elem_modern->second.obj_set; return 0; } inline size_t object_storage_get_obj_set_count() { return object_storage_data.size() + object_storage_data_modern.size(); } inline int32_t object_storage_get_obj_storage_load_count(uint32_t set_id) { auto elem = object_storage_data.find(set_id); if (elem != object_storage_data.end()) return elem->second.load_count; auto elem_modern = object_storage_data_modern.find(set_id); if (elem_modern != object_storage_data_modern.end()) return elem_modern->second.load_count; return 0; } inline obj_skin* object_storage_get_obj_skin(object_info obj_info) { auto elem = object_storage_data.find(obj_info.set_id); if (elem != object_storage_data.end()) { obj_set* set = elem->second.obj_set; if (!set) return 0; for (uint32_t j = 0; j < set->obj_num; j++) if (set->obj_data[j]->id == obj_info.id) return set->obj_data[j]->skin; return 0; } auto elem_modern = object_storage_data_modern.find(obj_info.set_id); if (elem_modern != object_storage_data_modern.end()) { obj_set* set = elem_modern->second.obj_set; if (!set) return 0; for (uint32_t j = 0; j < set->obj_num; j++) if (set->obj_data[j]->id == obj_info.id) return set->obj_data[j]->skin; return 0; } return 0; } inline obj_index_buffer* object_storage_get_obj_index_buffers(uint32_t set_id) { obj_set_handler* handler = object_storage_get_obj_set_handler(set_id); if (handler && handler->index_buffer_data) return handler->index_buffer_data; return 0; } inline obj_mesh_index_buffer* object_storage_get_obj_mesh_index_buffer(object_info obj_info) { obj_set_handler* handler = object_storage_get_obj_set_handler(obj_info.set_id); if (handler && handler->obj_set && handler->index_buffer_data) { obj_set* set = handler->obj_set; for (uint32_t i = 0; i < set->obj_num; i++) if (set->obj_data[i]->id == obj_info.id) return handler->index_buffer_data[i].mesh_data; } return 0; } inline obj_vertex_buffer* object_storage_get_obj_vertex_buffers(uint32_t set_id) { obj_set_handler* handler = object_storage_get_obj_set_handler(set_id); if (handler && handler->vertex_buffer_data) return handler->vertex_buffer_data; return 0; } inline obj_mesh_vertex_buffer* object_storage_get_obj_mesh_vertex_buffer(object_info obj_info) { obj_set_handler* handler = object_storage_get_obj_set_handler(obj_info.set_id); if (handler && handler->obj_set && handler->vertex_buffer_data) { obj_set* set = handler->obj_set; for (uint32_t i = 0; i < set->obj_num; i++) if (set->obj_data[i]->id == obj_info.id) return handler->vertex_buffer_data[i].mesh_data; } return 0; } texture* obj_database_get_obj_set_texture(int32_t set, uint32_t tex_id) { std::vector* textures = object_storage_get_obj_set_textures(set); if (!textures) return 0; obj_set_handler* handler = object_storage_get_obj_set_handler(set); if (!handler) return 0; auto elem = handler->tex_id_data.find(tex_id); if (elem != handler->tex_id_data.end()) return (*textures)[elem->second]; return 0; } inline std::vector* object_storage_get_obj_set_textures(int32_t set) { obj_set_handler* handler = object_storage_get_obj_set_handler(set); if (handler) return &handler->gentex; return 0; } int32_t object_storage_load_set(void* data, const object_database* obj_db, const char* name) { const object_set_info* set_info = obj_db->get_object_set_info(name); if (!set_info) return 1; obj_set_handler* handler = object_storage_get_obj_set_handler(set_info->id); if (!handler) return 1; if (handler->load_count > 0) { handler->load_count++; return 1; } const std::string& archive_file_name = set_info->archive_file_name; const std::string& object_file_name = set_info->object_file_name; const std::string& texture_file_name = set_info->texture_file_name; if (!object_file_name.size() || !texture_file_name.size()) return 1; if (archive_file_name.size()) { handler->obj_file_handler.read_file(data, "rom/objset/", archive_file_name.c_str(), object_file_name.c_str(), false); handler->tex_file_handler.read_file(data, "rom/objset/", archive_file_name.c_str(), texture_file_name.c_str(), false); } else { handler->obj_file_handler.read_file(data, "rom/objset/", object_file_name.c_str()); handler->tex_file_handler.read_file(data, "rom/objset/", texture_file_name.c_str()); } handler->load_count = 1; handler->obj_loaded = false; handler->tex_loaded = false; return 0; } int32_t object_storage_load_set(void* data, const object_database* obj_db, uint32_t set_id) { const object_set_info* set_info = obj_db->get_object_set_info(set_id); if (!set_info) return 1; obj_set_handler* handler = object_storage_get_obj_set_handler(set_id); if (!handler) return 1; if (handler->load_count > 0) { handler->load_count++; return 1; } handler->modern = false; const std::string& archive_file_name = set_info->archive_file_name; const std::string& object_file_name = set_info->object_file_name; const std::string& texture_file_name = set_info->texture_file_name; if (!object_file_name.size() || !texture_file_name.size()) return 1; if (archive_file_name.size()) { handler->obj_file_handler.read_file(data, "rom/objset/", archive_file_name.c_str(), object_file_name.c_str(), false); handler->tex_file_handler.read_file(data, "rom/objset/", archive_file_name.c_str(), texture_file_name.c_str(), false); } else { handler->obj_file_handler.read_file(data, "rom/objset/", object_file_name.c_str()); handler->tex_file_handler.read_file(data, "rom/objset/", texture_file_name.c_str()); } handler->load_count = 1; handler->obj_loaded = false; handler->tex_loaded = false; return 0; } int32_t object_storage_load_set_hash(void* data, uint32_t hash) { if (!hash || hash == hash_murmurhash_empty) return 1; std::string file; if (!((data_struct*)data)->get_file("root+/objset/", hash, ".farc", file)) return 1; obj_set_handler* handler = object_storage_get_obj_set_handler(hash); if (!handler) { handler = &object_storage_data_modern.insert({ hash, {} }).first->second; handler->set_id = hash; } if (handler->load_count > 0) { handler->load_count++; return 1; } handler->modern = true; handler->farc_file_handler.read_file(data, "root+/objset/", file.c_str()); handler->load_count = 1; handler->obj_loaded = false; handler->tex_loaded = false; return 0; } bool object_storage_load_obj_set_check_not_read(uint32_t set_id, object_database* obj_db, texture_database* tex_db) { obj_set_handler* handler = object_storage_get_obj_set_handler(set_id); if (!handler) return true; if (!handler->modern) { if (!handler->obj_loaded && !handler->obj_file_handler.check_not_ready()) { const void* data = handler->obj_file_handler.get_data(); size_t size = handler->obj_file_handler.get_size(); if (!data || !size) return false; prj::shared_ptr& alloc = handler->alloc_handler; alloc = prj::shared_ptr(new prj::stack_allocator); obj_set* set = alloc->allocate(); handler->obj_set = set; set->unpack_file(alloc, data, size, false); if (!set->ready) return false; handler->obj_file_handler.reset(); handler->obj_id_data.reserve(set->obj_num); for (uint32_t i = 0; i < set->obj_num; i++) handler->obj_id_data.push_back(set->obj_data[i]->id, i); handler->obj_id_data.sort(); if (!obj_set_handler_vertex_buffer_load(handler) || !obj_set_handler_index_buffer_load(handler)) return false; obj_set_handler_calc_axis_aligned_bounding_box(handler); handler->obj_loaded = true; } if (!handler->obj_loaded) return true; if (!handler->tex_loaded && !handler->tex_file_handler.check_not_ready()) { if (!handler->tex_file_handler.get_data()) return false; else if (obj_set_handler_load_textures(handler, handler->tex_file_handler.get_data(), false)) return false; obj_set_handler_get_shader_index_texture_index(handler); handler->tex_file_handler.reset(); handler->tex_loaded = true; } } else if (!handler->obj_loaded && !handler->farc_file_handler.check_not_ready()) { const void* data = handler->farc_file_handler.get_data(); size_t size = handler->farc_file_handler.get_size(); if (!data || !size) return false; farc f; f.read(data, size, true); std::string& file = handler->farc_file_handler.ptr->file; size_t file_len = file.size(); if (file_len >= 0x100 - 4) return false; const char* t = strrchr(file.c_str(), '.'); if (t) file_len = t - file.c_str(); char buf[0x100]; memcpy_s(buf, sizeof(buf), file.c_str(), file_len); char* ext = buf + file_len; size_t ext_len = sizeof(buf) - file_len; memcpy_s(ext, ext_len, ".osd", 5); farc_file* osd = f.read_file(buf); if (!osd) return false; memcpy_s(ext, ext_len, ".txd", 5); farc_file* txd = f.read_file(buf); if (!txd) return false; memcpy_s(ext, ext_len, ".osi", 5); farc_file* osi = f.read_file(buf); if (!osi) return false; memcpy_s(ext, ext_len, ".txi", 5); farc_file* txi = f.read_file(buf); if (!txi) return false; object_database_file obj_db_file; obj_db_file.read(osi->data, osi->size, true); texture_database_file tex_db_file; tex_db_file.read(txi->data, txi->size, true); object_set_info_file* set_info_file = 0; if (obj_db_file.ready) for (object_set_info_file& m : obj_db_file.object_set) if (m.id == handler->set_id) { set_info_file = &m; break; } if (!set_info_file) return false; object_database local_obj_db; if (obj_db_file.ready) { if (obj_db) obj_db->add(&obj_db_file); local_obj_db.add(&obj_db_file); } texture_database local_tex_db; if (tex_db_file.ready) { if (tex_db) tex_db->add(&tex_db_file); local_tex_db.add(&tex_db_file); } handler->name.assign(set_info_file->name); prj::shared_ptr& alloc = handler->alloc_handler; alloc = prj::shared_ptr(new prj::stack_allocator); obj_set* set = alloc->allocate(); handler->obj_set = set; set->unpack_file(alloc, osd->data, osd->size, true); if (!set->ready) return false; object_material_msgpack_read("patch\\AFT\\objset", file.c_str(), set, &local_obj_db); handler->obj_file_handler.reset(); handler->obj_id_data.reserve(set->obj_num); for (uint32_t i = 0; i < set->obj_num; i++) handler->obj_id_data.push_back(set->obj_data[i]->id, i); if (!obj_set_handler_vertex_buffer_load(handler) || !obj_set_handler_index_buffer_load(handler)) return false; obj_set_handler_calc_axis_aligned_bounding_box(handler); handler->obj_loaded = true; if (obj_set_handler_load_textures_modern(handler, txd->data, txd->size, file.c_str(), &local_tex_db)) return false; obj_set_handler_get_shader_index_texture_index(handler); handler->tex_loaded = true; handler->farc_file_handler.reset(); } if (handler->obj_loaded && handler->tex_loaded) return false; return true; } inline void object_storage_unload_set(const object_database* obj_db, const char* name) { const object_set_info* set_info = obj_db->get_object_set_info(name); if (!set_info) return; obj_set_handler* handler = object_storage_get_obj_set_handler(set_info->id); if (!handler || handler->load_count <= 0) return; if (--handler->load_count > 0) return; handler->obj_id_data.clear(); handler->tex_id_data.clear(); handler->gentex.clear(); texture_array_free(handler->tex_data); handler->tex_data = 0; handler->tex_num = 0; obj_set_handler_index_buffer_free(handler); obj_set_handler_vertex_buffer_free(handler); handler->load_count = 0; handler->tex_loaded = false; handler->obj_loaded = false; handler->alloc_handler.reset(); handler->obj_set = 0; handler->tex_file_handler.reset(); handler->obj_file_handler.reset(); handler->farc_file_handler.reset(); } inline void object_storage_unload_set(uint32_t set_id) { obj_set_handler* handler = object_storage_get_obj_set_handler(set_id); if (!handler || handler->load_count <= 0) return; if (--handler->load_count > 0) return; handler->obj_id_data.clear(); handler->tex_id_data.clear(); handler->gentex.clear(); texture_array_free(handler->tex_data); handler->tex_data = 0; handler->tex_num = 0; obj_set_handler_index_buffer_free(handler); obj_set_handler_vertex_buffer_free(handler); handler->load_count = 0; handler->tex_loaded = false; handler->obj_loaded = false; handler->alloc_handler.reset(); handler->obj_set = 0; handler->tex_file_handler.reset(); handler->obj_file_handler.reset(); handler->farc_file_handler.reset(); if (handler->modern) object_storage_data_modern.erase(set_id); } inline void object_storage_free() { object_storage_data.clear(); object_storage_data_modern.clear(); } static void obj_set_handler_calc_axis_aligned_bounding_box(obj_set_handler* handler) { obj_set* set = handler->obj_set; for (uint32_t i = 0; i < set->obj_num; i++) { obj* obj = set->obj_data[i]; for (uint32_t j = 0; j < obj->num_mesh; j++) { obj_mesh& mesh = obj->mesh_array[j]; for (uint32_t k = 0; k < mesh.num_submesh; k++) { vec3 _min = 9999999.0f; vec3 _max = -100000000.0f; obj_sub_mesh& sub_mesh = mesh.submesh_array[k]; uint32_t* index = sub_mesh.index_array; uint32_t num_index = sub_mesh.num_index; obj_vertex_data* vertex_array = mesh.vertex_array; if (sub_mesh.index_format == OBJ_INDEX_U16) for (uint32_t l = 0; l < num_index; l++, index++) { if (*index == 0xFFFFFFFF) continue; vec3 pos = vertex_array[*index].position; _min = vec3::min(_min, pos); _max = vec3::max(_max, pos); } else for (uint32_t l = 0; l < num_index; l++, index++) { vec3 pos = vertex_array[*index].position; _min = vec3::min(_min, pos); _max = vec3::max(_max, pos); } vec3 center = (_max + _min) * 0.5f; vec3 size = _max - center; sub_mesh.axis_aligned_bounding_box.center = center; sub_mesh.axis_aligned_bounding_box.size = size; } } } } static void obj_set_handler_get_shader_index_texture_index(obj_set_handler* handler) { obj_set* set = handler->obj_set; for (uint32_t i = 0; i < set->obj_num; i++) { obj* obj = set->obj_data[i]; uint32_t num_material = obj->num_material; for (uint32_t j = 0; j < num_material; j++) { obj_material_data& material_data = obj->material_array[j]; obj_material& material = material_data.material; if (*(int32_t*)&material.shader.name[4] != 0xDEADFF) { material.shader.index = shaders_ft.get_index_by_name(material.shader.name); *(int32_t*)&material.shader.name[4] = 0xDEADFF; } for (obj_material_texture_data& k : material.texdata) { if (k.tex_index == -1) continue; obj_material_texture_data& texture = k; uint32_t tex_index = texture.tex_index; texture.tex_index = -1; texture.texture_index = 0; std::pair* tex_id_data = handler->tex_id_data.data(); uint32_t tex_id_num = (uint32_t)handler->tex_id_data.size(); for (uint32_t l = tex_id_num; l; l--, tex_id_data++) if (tex_id_data->first == tex_index) { texture.tex_index = tex_index; texture.texture_index = tex_id_data->second; break; } } } } } static bool obj_set_handler_index_buffer_load(obj_set_handler* handler) { obj_set* set = handler->obj_set; handler->index_buffer_num = set->obj_num; handler->index_buffer_data = new obj_index_buffer[set->obj_num]; if (!handler->index_buffer_data) return true; for (uint32_t i = 0; i < set->obj_num; i++) if (!handler->index_buffer_data[i].load(set->obj_data[i])) return false; return true; } static void obj_set_handler_index_buffer_free(obj_set_handler* handler) { if (handler->index_buffer_data) { for (uint32_t i = 0; i < handler->index_buffer_num; i++) handler->index_buffer_data[i].unload(); delete[] handler->index_buffer_data; } handler->index_buffer_data = 0; handler->index_buffer_num = 0; } static bool obj_set_handler_load_textures(obj_set_handler* handler, const void* data, bool big_endian) { obj_set* set = handler->obj_set; if (!set || !data) return true; else if (!set->tex_id_num) return false; { txp_set txp; txp.unpack_file(data, big_endian); handler->tex_num = (int32_t)txp.textures.size(); texture_txp_set_load(&txp, &handler->tex_data, set->tex_id_data); } handler->tex_id_data.reserve(handler->tex_num); handler->gentex.reserve(handler->tex_num); uint32_t* tex_id_data = set->tex_id_data; uint32_t tex_num = handler->tex_num; texture** tex_data = handler->tex_data; for (uint32_t i = 0; i < tex_num; i++) { handler->tex_id_data.push_back(tex_id_data[i], i); handler->gentex.push_back(tex_data[i]); } handler->tex_id_data.sort(); return false; } static bool obj_set_handler_load_textures_modern(obj_set_handler* handler, const void* data, size_t size, const char* file, texture_database* tex_db) { obj_set* set = handler->obj_set; if (!set || !data || !size) return true; else if (!set->tex_id_num) return false; { txp_set txp; txp.unpack_file_modern(data, size, 'MTXD'); handler->tex_num = (int32_t)txp.textures.size(); object_material_msgpack_read("patch\\AFT\\objset", file, &txp, tex_db, handler); texture_txp_set_load(&txp, &handler->tex_data, set->tex_id_data); } handler->tex_id_data.reserve(handler->tex_num); handler->gentex.reserve(handler->tex_num); uint32_t* tex_id_data = set->tex_id_data; uint32_t tex_num = handler->tex_num; texture** tex_data = handler->tex_data; for (uint32_t i = 0; i < tex_num; i++) { handler->tex_id_data.push_back(tex_id_data[i], i); handler->gentex.push_back(tex_data[i]); } handler->tex_id_data.sort(); return false; } static bool obj_set_handler_vertex_buffer_load(obj_set_handler* handler) { obj_set* set = handler->obj_set; handler->vertex_buffer_num = set->obj_num; handler->vertex_buffer_data = new obj_vertex_buffer[set->obj_num]; if (!handler->vertex_buffer_data) return true; for (uint32_t i = 0; i < set->obj_num; i++) if (!handler->vertex_buffer_data[i].load(set->obj_data[i])) return false; return true; } static void obj_set_handler_vertex_buffer_free(obj_set_handler* handler) { if (handler->vertex_buffer_data) { for (uint32_t i = 0; i < handler->vertex_buffer_num; i++) handler->vertex_buffer_data[i].unload(); delete[] handler->vertex_buffer_data; } handler->vertex_buffer_data = 0; handler->vertex_buffer_num = 0; } inline static uint32_t obj_vertex_format_get_vertex_size(obj_vertex_format format) { uint32_t size = 0; if (format & OBJ_VERTEX_POSITION) size += 12; if (format & OBJ_VERTEX_NORMAL) size += 12; if (format & OBJ_VERTEX_TANGENT) size += 16; if (format & OBJ_VERTEX_BINORMAL) size += 12; if (format & OBJ_VERTEX_TEXCOORD0) size += 8; if (format & OBJ_VERTEX_TEXCOORD1) size += 8; if (format & OBJ_VERTEX_TEXCOORD2) size += 8; if (format & OBJ_VERTEX_TEXCOORD3) size += 8; if (format & OBJ_VERTEX_COLOR0) size += 16; if (format & OBJ_VERTEX_COLOR1) size += 16; if (format & OBJ_VERTEX_BONE_DATA) size += 24; if (format & OBJ_VERTEX_UNKNOWN) size += 16; return size; } inline static uint32_t obj_vertex_format_get_vertex_size_comp(obj_vertex_format format) { uint32_t size = 0; if (format & OBJ_VERTEX_POSITION) size += 12; if (format & OBJ_VERTEX_NORMAL) size += 8; if (format & OBJ_VERTEX_TANGENT) size += 8; if (format & OBJ_VERTEX_TEXCOORD0) size += 4; if (format & OBJ_VERTEX_TEXCOORD1) size += 4; if (format & OBJ_VERTEX_TEXCOORD2) size += 4; if (format & OBJ_VERTEX_TEXCOORD3) size += 4; if (format & OBJ_VERTEX_COLOR0) size += 8; if (format & OBJ_VERTEX_BONE_DATA) size += 16; return size; }