mirror of
https://github.com/korenkonder/ReDIVA.git
synced 2026-10-04 12:47:56 +03:00
1585 lines
62 KiB
C
1585 lines
62 KiB
C
/*
|
|
by korenkonder
|
|
GitHub/GitLab: korenkonder
|
|
*/
|
|
|
|
#include "object.h"
|
|
#include "data.h"
|
|
#include "gl_state.h"
|
|
#include "shader_ft.h"
|
|
#include "../KKdLib/str_utils.h"
|
|
|
|
typedef obj object_file;
|
|
typedef obj_material_data object_material_data_file;
|
|
typedef obj_material object_material_file;
|
|
typedef obj_material_texture object_material_texture_file;
|
|
typedef obj_mesh object_mesh_file;
|
|
typedef obj_set object_set_file;
|
|
typedef obj_skin object_skin_file;
|
|
typedef obj_skin_block object_skin_block_file;
|
|
typedef obj_skin_block_cloth object_skin_block_cloth_file;
|
|
typedef obj_skin_block_constraint object_skin_block_constraint_file;
|
|
typedef obj_skin_block_constraint_attach_point object_skin_block_constraint_attach_point_file;
|
|
typedef obj_skin_block_constraint_direction object_skin_block_constraint_direction_file;
|
|
typedef obj_skin_block_constraint_distance object_skin_block_constraint_distance_file;
|
|
typedef obj_skin_block_constraint_orientation object_skin_block_constraint_orientation_file;
|
|
typedef obj_skin_block_constraint_position object_skin_block_constraint_position_file;
|
|
typedef obj_skin_block_constraint_up_vector object_skin_block_constraint_up_vector_file;
|
|
typedef obj_skin_block_expression object_skin_block_expression_file;
|
|
typedef obj_skin_block_motion object_skin_block_motion_file;
|
|
typedef obj_skin_block_node object_skin_block_node_file;
|
|
typedef obj_skin_block_osage object_skin_block_osage_file;
|
|
typedef obj_skin_bone object_skin_bone_file;
|
|
typedef obj_skin_ex_data object_skin_ex_data_file;
|
|
typedef obj_skin_osage_node object_skin_osage_node_file;
|
|
typedef obj_skin_osage_sibling_info object_skin_osage_sibling_info_file;
|
|
typedef obj_skin_motion_node object_skin_motion_node_file;
|
|
typedef obj_sub_mesh object_sub_mesh_file;
|
|
typedef obj_vertex_data object_vertex_data_file;
|
|
|
|
typedef struct object_storage {
|
|
uint32_t set_id;
|
|
int32_t count;
|
|
object_set set;
|
|
} object_storage;
|
|
|
|
vector(object_storage)
|
|
|
|
static bool object_mesh_index_buffer_load(object_mesh_index_buffer* buffer, object_mesh* mesh);
|
|
static GLuint object_mesh_index_buffer_load_data(size_t size, void* data);
|
|
static void object_mesh_index_buffer_free(object_mesh_index_buffer* buffer);
|
|
static bool object_mesh_vertex_buffer_load(object_mesh_vertex_buffer* buffer, object_mesh* mesh);
|
|
static bool object_mesh_vertex_buffer_load_data(object_mesh_vertex_buffer* buffer,
|
|
size_t size, void* data, int32_t count);
|
|
static void object_mesh_vertex_buffer_free(object_mesh_vertex_buffer* buffer);
|
|
static bool object_set_index_buffer_load(object_set* set);
|
|
static void object_set_index_buffer_free(object_set* set);
|
|
static bool object_set_vertex_buffer_load(object_set* set);
|
|
static void object_set_vertex_buffer_free(object_set* set);
|
|
static void object_skin_block_constraint_attach_point_load(
|
|
object_skin_block_constraint_attach_point* attach_point,
|
|
object_skin_block_constraint_attach_point_file* attach_point_file);
|
|
static void object_skin_block_constraint_up_vector_load(
|
|
object_skin_block_constraint_up_vector* up_vector,
|
|
object_skin_block_constraint_up_vector_file* up_vector_file);
|
|
static void object_skin_block_node_load(object_skin_block_node* node,
|
|
object_skin_block_node_file* node_file);
|
|
static void object_skin_block_node_free(object_skin_block_node* node);
|
|
static size_t object_vertex_flags_get_vertex_size(object_vertex_flags flags);
|
|
static size_t object_vertex_flags_get_vertex_size_comp(object_vertex_flags flags);
|
|
static bool object_set_load_file(void* data, char* path, char* file, uint32_t hash);
|
|
static bool object_set_load_file_modern(void* data, char* path, char* file, uint32_t hash);
|
|
|
|
vector_func(object_storage)
|
|
|
|
vector_object_storage object_storage_data;
|
|
|
|
void object_set_init(object_set* set) {
|
|
if (!set)
|
|
return;
|
|
|
|
memset(set, 0, sizeof(object_set));
|
|
}
|
|
|
|
void object_set_load(object_set* set, obj_set* obj_set_file, txp_set* txp_set_file,
|
|
texture_database* tex_db, string* name, uint32_t id, bool compressed) {
|
|
if (!set || !obj_set_file || !txp_set_file || !tex_db || !name)
|
|
return;
|
|
|
|
bool is_x = obj_set_file->is_x;
|
|
set->is_x = is_x;
|
|
set->texture_ids_count = obj_set_file->texture_ids_count;
|
|
set->texture_ids = force_malloc_s(uint32_t, obj_set_file->texture_ids_count);
|
|
memcpy(set->texture_ids, obj_set_file->texture_ids, obj_set_file->texture_ids_count * sizeof(uint32_t));
|
|
|
|
set->texture_names_count = obj_set_file->texture_ids_count;
|
|
set->texture_names = force_malloc_s(string, obj_set_file->texture_ids_count);
|
|
if (tex_db->ready)
|
|
for (int32_t i = 0; i < set->texture_names_count; i++) {
|
|
int32_t texture_id = set->texture_ids[i];
|
|
string* name = &set->texture_names[i];
|
|
*name = string_empty;
|
|
|
|
for (texture_info* j = tex_db->texture.begin; j != tex_db->texture.end; j++)
|
|
if (j->id == texture_id) {
|
|
string_copy(&j->name, name);
|
|
break;
|
|
}
|
|
|
|
if (!name->length) {
|
|
char buf[0x100];
|
|
int32_t len = sprintf_s(buf, sizeof(buf), "TEXTURE_%d", i);
|
|
string_init_length(name, buf, len);
|
|
}
|
|
}
|
|
else
|
|
for (int32_t i = 0; i < set->texture_names_count; i++) {
|
|
string* name = &set->texture_names[i];
|
|
|
|
char buf[0x100];
|
|
int32_t len = sprintf_s(buf, sizeof(buf), "TEXTURE_%d", i);
|
|
string_init_length(name, buf, len);
|
|
}
|
|
|
|
string_copy(name, &set->name);
|
|
set->id = id;
|
|
set->hash = hash_murmurhash(string_data(&set->name), set->name.length, 0, false, false);
|
|
|
|
int32_t objects_count = obj_set_file->objects_count;
|
|
set->objects_count = objects_count;
|
|
set->objects = force_malloc_s(object, objects_count);
|
|
for (int32_t i = 0; i < objects_count; i++) {
|
|
object* obj = &set->objects[i];
|
|
object_file* obj_file = &obj_set_file->objects[i];
|
|
obj->bounding_sphere.center = obj_file->bounding_sphere.center;
|
|
obj->bounding_sphere.radius = obj_file->bounding_sphere.radius;
|
|
|
|
int32_t meshes_count = obj_file->meshes_count;
|
|
obj->meshes_count = meshes_count;
|
|
obj->meshes = force_malloc_s(object_mesh, meshes_count);
|
|
for (int32_t j = 0; j < meshes_count; j++) {
|
|
object_mesh* mesh = &obj->meshes[j];
|
|
object_mesh_file* mesh_file = &obj_file->meshes[j];
|
|
|
|
mesh->bounding_sphere.center = mesh_file->bounding_sphere.center;
|
|
mesh->bounding_sphere.radius = mesh_file->bounding_sphere.radius;
|
|
|
|
int32_t sub_meshes_count = mesh_file->sub_meshes_count;
|
|
mesh->sub_meshes_count = sub_meshes_count;
|
|
mesh->sub_meshes = force_malloc_s(object_sub_mesh, sub_meshes_count);
|
|
for (int32_t k = 0; k < sub_meshes_count; k++) {
|
|
object_sub_mesh* sub_mesh = &mesh->sub_meshes[k];
|
|
object_sub_mesh_file* sub_mesh_file = &mesh_file->sub_meshes[k];
|
|
|
|
sub_mesh->bounding_sphere.center = sub_mesh_file->bounding_sphere.center;
|
|
sub_mesh->bounding_sphere.radius = sub_mesh_file->bounding_sphere.radius;
|
|
sub_mesh->material_index = sub_mesh_file->material_index;
|
|
memcpy(sub_mesh->texcoord_indices, sub_mesh_file->texcoord_indices,
|
|
sizeof(sub_mesh_file->texcoord_indices));
|
|
|
|
sub_mesh->bone_indices_count = sub_mesh_file->bone_indices_count;
|
|
sub_mesh->bone_indices = force_malloc_s(uint16_t, sub_mesh_file->bone_indices_count);
|
|
memcpy(sub_mesh->bone_indices, sub_mesh_file->bone_indices,
|
|
sub_mesh_file->bone_indices_count * sizeof(uint16_t));
|
|
sub_mesh->bones_per_vertex = sub_mesh_file->bones_per_vertex;
|
|
sub_mesh->primitive_type = sub_mesh_file->primitive_type;
|
|
sub_mesh->index_format = sub_mesh_file->index_format;
|
|
sub_mesh->flags = sub_mesh_file->flags;
|
|
|
|
bool u16 = sub_mesh_file->index_format == OBJ_INDEX_U16;
|
|
vec3 _min = (vec3){ 9999999.0f, 9999999.0f, 9999999.0f };
|
|
vec3 _max = (vec3){ -100000000.0f, -100000000.0f, -100000000.0f };
|
|
|
|
uint32_t* indices = (uint32_t*)sub_mesh_file->indices;
|
|
int32_t indices_count = sub_mesh_file->indices_count;
|
|
object_vertex_data_file* vertex = mesh_file->vertex;
|
|
if (u16)
|
|
for (int32_t l = 0; l < indices_count; l++) {
|
|
if (indices[l] == 0xFFFFFFFF)
|
|
continue;
|
|
|
|
vec3 pos = vertex[indices[l]].position;
|
|
vec3_min(_min, pos, _min);
|
|
vec3_max(_max, pos, _max);
|
|
}
|
|
else
|
|
for (int32_t l = 0; l < indices_count; l++) {
|
|
vec3 pos = vertex[indices[l]].position;
|
|
vec3_min(_min, pos, _min);
|
|
vec3_max(_max, pos, _max);
|
|
}
|
|
|
|
vec3 center;
|
|
vec3 size;
|
|
vec3_add(_max, _min, center);
|
|
vec3_mult_scalar(center, 0.5f, center);
|
|
vec3_sub(_max, center, size);
|
|
sub_mesh->axis_aligned_bounding_box.center = center;
|
|
sub_mesh->axis_aligned_bounding_box.size = size;
|
|
|
|
sub_mesh->indices_count = indices_count;
|
|
sub_mesh->first_index = 0;
|
|
sub_mesh->last_index = 0;
|
|
sub_mesh->indices_offset = 0;
|
|
if (u16) {
|
|
uint16_t first_index = 0xFFFF;
|
|
uint16_t last_index = 0;
|
|
for (int32_t i = 0; i < indices_count; i++) {
|
|
uint16_t index = (uint16_t)indices[i];
|
|
if (index == 0xFFFF)
|
|
continue;
|
|
|
|
if (index < first_index)
|
|
first_index = index;
|
|
if (index > last_index)
|
|
last_index = index;
|
|
}
|
|
|
|
sub_mesh->first_index = first_index;
|
|
sub_mesh->last_index = last_index;
|
|
}
|
|
}
|
|
|
|
mesh->compressed = compressed;
|
|
|
|
size_t vertex_size;
|
|
if (!compressed)
|
|
vertex_size = object_vertex_flags_get_vertex_size(mesh_file->vertex_flags);
|
|
else
|
|
vertex_size = object_vertex_flags_get_vertex_size_comp(mesh_file->vertex_flags);
|
|
|
|
void* vertex = force_malloc(vertex_size * mesh_file->vertex_count);
|
|
if (vertex) {
|
|
object_vertex_flags flags = mesh_file->vertex_flags;
|
|
object_vertex_data_file* vertex_file = mesh_file->vertex;
|
|
int32_t vertex_count = mesh_file->vertex_count;
|
|
size_t d = (size_t)vertex;
|
|
if (!compressed) {
|
|
for (int32_t i = 0; i < vertex_count; i++) {
|
|
if (flags & OBJECT_VERTEX_POSITION) {
|
|
*(vec3*)d = vertex_file[i].position;
|
|
d += 12;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_NORMAL) {
|
|
*(vec3*)d = vertex_file[i].normal;
|
|
d += 12;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_TANGENT) {
|
|
*(vec4u*)d = vertex_file[i].tangent;
|
|
d += 16;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_BINORMAL) {
|
|
*(vec3*)d = vertex_file[i].binormal;
|
|
d += 12;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_TEXCOORD0) {
|
|
*(vec2*)d = vertex_file[i].texcoord0;
|
|
d += 8;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_TEXCOORD1) {
|
|
*(vec2*)d = vertex_file[i].texcoord1;
|
|
d += 8;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_TEXCOORD2) {
|
|
*(vec2*)d = vertex_file[i].texcoord2;
|
|
d += 8;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_TEXCOORD3) {
|
|
*(vec2*)d = vertex_file[i].texcoord3;
|
|
d += 8;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_COLOR0) {
|
|
*(vec4u*)d = vertex_file[i].color0;
|
|
d += 16;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_COLOR1) {
|
|
*(vec4u*)d = vertex_file[i].color1;
|
|
d += 16;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_BONE_DATA) {
|
|
*(vec4u*)d = vertex_file[i].bone_weight;
|
|
d += 16;
|
|
*(vec4iu*)d = vertex_file[i].bone_index;
|
|
d += 16;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_UNKNOWN) {
|
|
*(vec4u*)d = vertex_file[i].unknown;
|
|
d += 16;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (int32_t i = 0; i < vertex_count; i++) {
|
|
if (flags & OBJECT_VERTEX_POSITION) {
|
|
*(vec3*)d = vertex_file[i].position;
|
|
d += 12;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_NORMAL) {
|
|
vec3 normal;
|
|
vec3_mult_scalar(vertex_file[i].normal, 32727.0f, normal);
|
|
vec3_to_vec3i16(normal, *(vec3i16*)d);
|
|
*(int16_t*)(d + 6) = 0;
|
|
d += 8;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_TANGENT) {
|
|
vec4 tangent;
|
|
vec4u_to_vec4(vertex_file[i].tangent, tangent);
|
|
vec4_mult_scalar(tangent, 32727.0f, tangent);
|
|
vec4_to_vec4i16(tangent, *(vec4i16*)d);
|
|
d += 8;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_TEXCOORD0) {
|
|
vec2_to_vec2h(vertex_file[i].texcoord0, *(vec2h*)d);
|
|
d += 4;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_TEXCOORD1) {
|
|
vec2_to_vec2h(vertex_file[i].texcoord1, *(vec2h*)d);
|
|
d += 4;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_TEXCOORD2) {
|
|
vec2_to_vec2h(vertex_file[i].texcoord2, *(vec2h*)d);
|
|
d += 4;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_TEXCOORD3) {
|
|
vec2_to_vec2h(vertex_file[i].texcoord3, *(vec2h*)d);
|
|
d += 4;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_COLOR0) {
|
|
vec4 color0;
|
|
vec4u_to_vec4(vertex_file[i].color0, color0);
|
|
vec4_to_vec4h(color0, *(vec4h*)d);
|
|
d += 8;
|
|
}
|
|
|
|
if (flags & OBJECT_VERTEX_BONE_DATA) {
|
|
vec4 bone_weight;
|
|
vec4u_to_vec4(vertex_file[i].bone_weight, bone_weight);
|
|
vec4_mult_scalar(bone_weight, 65535.0f, bone_weight);
|
|
vec4_to_vec4u16(bone_weight, *(vec4u16*)d);
|
|
d += 8;
|
|
|
|
vec4i bone_index;
|
|
vec4iu_to_vec4i(vertex_file[i].bone_index, bone_index);
|
|
vec4i_to_vec4u16(bone_index, *(vec4u16*)d);
|
|
d += 8;
|
|
}
|
|
}
|
|
}
|
|
|
|
mesh->vertex = vertex;
|
|
mesh->vertex_count = mesh_file->vertex_count;
|
|
mesh->vertex_size = (int32_t)vertex_size;
|
|
}
|
|
else {
|
|
mesh->vertex = 0;
|
|
mesh->vertex_count = 0;
|
|
mesh->vertex_size = 0;
|
|
}
|
|
|
|
size_t indices_count = 0;
|
|
for (int32_t k = 0; k < mesh->sub_meshes_count; k++)
|
|
if (mesh_file->sub_meshes[k].index_format == OBJ_INDEX_U16)
|
|
indices_count += mesh_file->sub_meshes[k].indices_count;
|
|
|
|
if (indices_count) {
|
|
uint16_t* indices = force_malloc_s(uint16_t, indices_count);
|
|
size_t offset = 0;
|
|
for (int32_t k = 0; k < mesh->sub_meshes_count; k++) {
|
|
object_sub_mesh* sub_mesh = &mesh->sub_meshes[k];
|
|
object_sub_mesh_file* sub_mesh_file = &mesh_file->sub_meshes[k];
|
|
if (sub_mesh->index_format != OBJ_INDEX_U16)
|
|
continue;
|
|
|
|
int32_t sub_mesh_indices_count = sub_mesh_file->indices_count;
|
|
uint32_t* sub_mesh_indices = sub_mesh_file->indices;
|
|
for (int32_t l = 0; l < sub_mesh_indices_count; l++)
|
|
indices[offset + l] = (uint16_t)sub_mesh_indices[l];
|
|
sub_mesh->indices_offset = (int32_t)(sizeof(uint16_t) * offset);
|
|
offset += sub_mesh_file->indices_count;
|
|
}
|
|
mesh->indices = indices;
|
|
mesh->indices_count = (int32_t)indices_count;
|
|
}
|
|
else {
|
|
mesh->indices = 0;
|
|
mesh->indices_count = 0;
|
|
}
|
|
|
|
mesh->vertex_flags = mesh_file->vertex_flags;
|
|
mesh->flags = mesh_file->flags;
|
|
memcpy(mesh->name, mesh_file->name, sizeof(mesh_file->name));
|
|
mesh->name[sizeof(mesh->name) - 1] = 0;
|
|
}
|
|
|
|
int32_t materials_count = obj_file->materials_count;
|
|
obj->materials_count = materials_count;
|
|
obj->materials = force_malloc_s(object_material_data, materials_count);
|
|
for (int32_t j = 0; j < materials_count; j++) {
|
|
obj->materials[j].textures_count = obj_file->materials[j].textures_count;
|
|
|
|
object_material* material = &obj->materials[j].material;
|
|
object_material_file* material_file = &obj_file->materials[j].material;
|
|
|
|
material->flags = material_file->flags;
|
|
material->shader_index = shader_get_index_by_name(&shaders_ft, material_file->shader_name);
|
|
memcpy(&material->shader_flags, &material_file->shader_flags,
|
|
sizeof(material_file->shader_flags));
|
|
|
|
for (int32_t k = 0; k < 8; k++) {
|
|
object_material_texture* textures = &material->textures[k];
|
|
object_material_texture_file* textures_file = &material_file->textures[k];
|
|
|
|
memcpy(&textures->sampler_flags, &textures_file->sampler_flags,
|
|
sizeof(textures_file->sampler_flags));
|
|
textures->texture_id = -1;
|
|
textures->texture_index = -1;
|
|
memcpy(&textures->texture_flags, &textures_file->texture_flags,
|
|
sizeof(textures_file->texture_flags));
|
|
memcpy(&textures->shader_name, &textures_file->shader_name,
|
|
sizeof(textures_file->shader_name));
|
|
textures->weight = textures_file->weight;
|
|
textures->tex_coord_mat = textures_file->tex_coord_mat;
|
|
|
|
uint32_t* texture_ids = set->texture_ids;
|
|
int32_t texture_ids_count = set->texture_ids_count;
|
|
for (int32_t l = 0; l < texture_ids_count; l++) {
|
|
if (texture_ids[l] == textures_file->texture_id) {
|
|
textures->texture_id = textures_file->texture_id;
|
|
textures->texture_index = l;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
material->diffuse = material_file->diffuse;
|
|
material->ambient = material_file->ambient;
|
|
material->specular = material_file->specular;
|
|
material->emission = material_file->emission;
|
|
memcpy(&material->blend_flags, &material_file->blend_flags,
|
|
sizeof(material_file->blend_flags));
|
|
material->shininess = material_file->shininess;
|
|
material->intensity = material_file->intensity;
|
|
material->reserved_sphere.center = material_file->reserved_sphere.center;
|
|
material->reserved_sphere.radius = material_file->reserved_sphere.radius;
|
|
memcpy(material->name, material_file->name, sizeof(material_file->name) - 1);
|
|
material->name[sizeof(material->name) - 1] = 0;
|
|
material->bump_depth = material_file->bump_depth;
|
|
}
|
|
|
|
obj->flags = obj_file->flags;
|
|
string_copy(&obj_file->name, &obj->name);
|
|
obj->id = obj_file->id;
|
|
obj->hash = hash_murmurhash(string_data(&obj->name), obj->name.length, 0, false, false);
|
|
|
|
if (!obj_file->skin_init) {
|
|
memset(&obj->skin, 0, sizeof(object_skin));
|
|
obj->skin_init = false;
|
|
continue;
|
|
}
|
|
|
|
object_skin* skin = &obj->skin;
|
|
object_skin_file* skin_file = &obj_file->skin;
|
|
|
|
int32_t bones_count = skin_file->bones_count;
|
|
skin->bones_count = bones_count;
|
|
skin->bones = force_malloc_s(object_skin_bone, bones_count);
|
|
for (int32_t j = 0; j < bones_count; j++) {
|
|
object_skin_bone* bone = &skin->bones[j];
|
|
object_skin_bone_file* bone_file = &skin_file->bones[j];
|
|
|
|
bone->id = bone_file->id;
|
|
bone->inv_bind_pose_mat = bone_file->inv_bind_pose_mat;
|
|
string_copy(&bone_file->name, &bone->name);
|
|
bone->parent = bone_file->parent;
|
|
}
|
|
obj->skin_init = true;
|
|
|
|
if (!skin_file->ex_data_init) {
|
|
memset(&skin->ex_data, 0, sizeof(object_skin_ex_data));
|
|
skin->ex_data_init = false;
|
|
continue;
|
|
}
|
|
|
|
object_skin_ex_data* ex_data = &skin->ex_data;
|
|
object_skin_ex_data_file* ex_data_file = &skin_file->ex_data;
|
|
|
|
int32_t osage_nodes_count = ex_data_file->osage_nodes_count;
|
|
ex_data->osage_nodes_count = osage_nodes_count;
|
|
ex_data->osage_nodes = force_malloc_s(object_skin_osage_node, osage_nodes_count);
|
|
for (int32_t j = 0; j < osage_nodes_count; j++) {
|
|
object_skin_osage_node* node = &ex_data->osage_nodes[j];
|
|
object_skin_osage_node_file* node_file = &ex_data_file->osage_nodes[j];
|
|
|
|
node->name_index = node_file->name_index;
|
|
node->length = node_file->length;
|
|
node->rotation = node_file->rotation;
|
|
}
|
|
|
|
int32_t bone_names_count = ex_data_file->bone_names_count;
|
|
|
|
size_t buf_size = 0;
|
|
char** bone_names_file_ptr = ex_data_file->bone_names;
|
|
for (int32_t i = 0; i < bone_names_count; i++)
|
|
buf_size += utf8_length(*bone_names_file_ptr++) + 1;
|
|
|
|
ex_data->bone_names_buf = force_malloc(buf_size);
|
|
ex_data->bone_names = force_malloc_s(char*, buf_size + 1);
|
|
ex_data->bone_names_count = bone_names_count;
|
|
|
|
bone_names_file_ptr = ex_data_file->bone_names;
|
|
char* bone_names_buf = ex_data->bone_names_buf;
|
|
char** bone_names_ptr = ex_data->bone_names;
|
|
for (int32_t i = 0; i < bone_names_count; i++) {
|
|
*bone_names_ptr++ = bone_names_buf;
|
|
size_t len = utf8_length(*bone_names_file_ptr);
|
|
memcpy(bone_names_buf, *bone_names_file_ptr++, len);
|
|
bone_names_buf[len] = 0;
|
|
bone_names_buf += len + 1;
|
|
}
|
|
*bone_names_ptr = 0;
|
|
|
|
int32_t blocks_count = ex_data_file->blocks_count;
|
|
ex_data->blocks_count = blocks_count;
|
|
ex_data->blocks = force_malloc_s(object_skin_block, blocks_count);
|
|
for (int32_t j = 0; j < blocks_count; j++) {
|
|
object_skin_block* block = &ex_data->blocks[j];
|
|
object_skin_block_file* block_file = &ex_data_file->blocks[j];
|
|
|
|
object_skin_block_node_load(&block->base, &block_file->base);
|
|
|
|
switch (block_file->type) {
|
|
case OBJ_SKIN_BLOCK_CLOTH: {
|
|
block->type = OBJECT_SKIN_BLOCK_CLOTH;
|
|
|
|
object_skin_block_cloth* cloth = &block->cloth;
|
|
object_skin_block_cloth_file* cloth_file = &block_file->cloth;
|
|
|
|
} break;
|
|
case OBJ_SKIN_BLOCK_CONSTRAINT: {
|
|
block->type = OBJECT_SKIN_BLOCK_CONSTRAINT;
|
|
|
|
object_skin_block_constraint* constraint = &block->constraint;
|
|
object_skin_block_constraint_file* constraint_file = &block_file->constraint;
|
|
|
|
constraint->coupling = constraint_file->coupling;
|
|
constraint->name_index = constraint_file->name_index;
|
|
string_copy(&constraint_file->source_node_name, &constraint->source_node_name);
|
|
|
|
switch (constraint_file->type) {
|
|
case OBJ_SKIN_BLOCK_CONSTRAINT_ORIENTATION:
|
|
constraint->type = OBJECT_SKIN_BLOCK_CONSTRAINT_ORIENTATION;
|
|
|
|
object_skin_block_constraint_orientation* orientation = &constraint->orientation;
|
|
object_skin_block_constraint_orientation_file* orientation_file
|
|
= &constraint_file->orientation;
|
|
|
|
orientation->offset = orientation_file->offset;
|
|
break;
|
|
case OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION:
|
|
constraint->type = OBJECT_SKIN_BLOCK_CONSTRAINT_DIRECTION;
|
|
|
|
object_skin_block_constraint_direction* direction = &constraint->direction;
|
|
object_skin_block_constraint_direction_file* direction_file
|
|
= &constraint_file->direction;
|
|
|
|
object_skin_block_constraint_up_vector_load(
|
|
&direction->up_vector, &direction_file->up_vector);
|
|
direction->align_axis = direction_file->align_axis;
|
|
direction->target_offset = direction_file->target_offset;
|
|
break;
|
|
case OBJ_SKIN_BLOCK_CONSTRAINT_POSITION:
|
|
constraint->type = OBJECT_SKIN_BLOCK_CONSTRAINT_POSITION;
|
|
|
|
object_skin_block_constraint_position* position = &constraint->position;
|
|
object_skin_block_constraint_position_file* position_file
|
|
= &constraint_file->position;
|
|
|
|
object_skin_block_constraint_up_vector_load(
|
|
&position->up_vector, &position_file->up_vector);
|
|
string_copy(&position_file->up_vector.name, &position->up_vector.name);
|
|
object_skin_block_constraint_attach_point_load(
|
|
&position->constrained_object, &position_file->constrained_object);
|
|
object_skin_block_constraint_attach_point_load(
|
|
&position->constraining_object, &position_file->constraining_object);
|
|
break;
|
|
case OBJ_SKIN_BLOCK_CONSTRAINT_DISTANCE:
|
|
constraint->type = OBJECT_SKIN_BLOCK_CONSTRAINT_DISTANCE;
|
|
|
|
object_skin_block_constraint_distance* distance = &constraint->distance;
|
|
object_skin_block_constraint_distance_file* distance_file
|
|
= &constraint_file->distance;
|
|
|
|
object_skin_block_constraint_up_vector_load(
|
|
&distance->up_vector, &distance_file->up_vector);
|
|
distance->distance = distance_file->distance;
|
|
object_skin_block_constraint_attach_point_load(
|
|
&distance->constrained_object, &distance_file->constrained_object);
|
|
object_skin_block_constraint_attach_point_load(
|
|
&distance->constraining_object, &distance_file->constraining_object);
|
|
break;
|
|
}
|
|
|
|
} break;
|
|
case OBJ_SKIN_BLOCK_EXPRESSION: {
|
|
block->type = OBJECT_SKIN_BLOCK_EXPRESSION;
|
|
|
|
object_skin_block_expression* expression = &block->expression;
|
|
object_skin_block_expression_file* expression_file = &block_file->expression;
|
|
|
|
expression->name_index = expression_file->name_index;
|
|
int32_t expressions_count = min(expression_file->expressions_count, 9);
|
|
expression->expressions_count = expressions_count;
|
|
for (int32_t k = 0; k < expressions_count; k++)
|
|
string_copy(&expression_file->expressions[k], &expression->expressions[k]);
|
|
|
|
for (int32_t k = expressions_count; k < 9; k++)
|
|
expression->expressions[k] = string_empty;
|
|
|
|
} break;
|
|
case OBJ_SKIN_BLOCK_MOTION: {
|
|
block->type = OBJECT_SKIN_BLOCK_MOTION;
|
|
|
|
object_skin_block_motion* motion = &block->motion;
|
|
object_skin_block_motion_file* motion_file = &block_file->motion;
|
|
|
|
int32_t nodes_count = motion_file->nodes_count;
|
|
if (!is_x)
|
|
motion->name_index = motion_file->name_index;
|
|
else
|
|
string_copy(&motion_file->name, &motion->name);
|
|
motion->nodes_count = nodes_count;
|
|
motion->nodes = force_malloc_s(object_skin_motion_node, nodes_count);
|
|
for (int32_t k = 0; k < nodes_count; k++) {
|
|
object_skin_motion_node* node = &motion->nodes[j];
|
|
object_skin_motion_node_file* node_file = &motion_file->nodes[j];
|
|
|
|
node->name_index = node_file->name_index;
|
|
node->transformation = node_file->transformation;
|
|
}
|
|
|
|
} break;
|
|
case OBJ_SKIN_BLOCK_OSAGE: {
|
|
block->type = OBJECT_SKIN_BLOCK_OSAGE;
|
|
|
|
object_skin_block_osage* osage = &block->osage;
|
|
object_skin_block_osage_file* osage_file = &block_file->osage;
|
|
|
|
osage->start_index = osage_file->start_index;
|
|
osage->count = osage_file->count;
|
|
|
|
int32_t nodes_count = osage_file->nodes_count;
|
|
osage->nodes_count = nodes_count;
|
|
osage->nodes = force_malloc_s(object_skin_osage_node, nodes_count);
|
|
for (int32_t k = 0; k < nodes_count; k++) {
|
|
object_skin_osage_node* node = &osage->nodes[j];
|
|
object_skin_osage_node_file* node_file = &osage_file->nodes[j];
|
|
|
|
node->name_index = node_file->name_index;
|
|
node->length = node_file->length;
|
|
node->rotation = node_file->rotation;
|
|
}
|
|
|
|
osage->external_name_index = osage_file->external_name_index;
|
|
osage->name_index = osage_file->name_index;
|
|
string_copy(&osage_file->motion_node_name, &osage->motion_node_name);
|
|
} break;
|
|
}
|
|
}
|
|
|
|
int32_t osage_sibling_infos_count = ex_data_file->osage_sibling_infos_count;
|
|
ex_data->osage_sibling_infos_count = osage_sibling_infos_count;
|
|
ex_data->osage_sibling_infos = force_malloc_s(
|
|
object_skin_osage_sibling_info, osage_sibling_infos_count);
|
|
for (int32_t j = 0; j < osage_sibling_infos_count; j++) {
|
|
object_skin_osage_sibling_info* osage_sibling_info = &ex_data->osage_sibling_infos[j];
|
|
object_skin_osage_sibling_info_file* osage_sibling_info_file = &ex_data_file->osage_sibling_infos[j];
|
|
|
|
osage_sibling_info->name_index = osage_sibling_info_file->name_index;
|
|
osage_sibling_info->sibling_name_index = osage_sibling_info_file->sibling_name_index;
|
|
osage_sibling_info->distance = osage_sibling_info_file->distance;
|
|
}
|
|
skin->ex_data_init = true;
|
|
}
|
|
|
|
int32_t textures_count = (int32_t)vector_length(*txp_set_file);
|
|
set->textures_count = textures_count;
|
|
set->textures = force_malloc_s(GLuint, textures_count);
|
|
texture_txp_set_load(txp_set_file, &set->texture_data, set->texture_ids);
|
|
if (set->texture_ids)
|
|
for (int32_t i = 0; i < textures_count; i++)
|
|
if (set->texture_data[i])
|
|
set->textures[i] = set->texture_data[i]->texture;
|
|
else
|
|
set->textures[i] = 0;
|
|
|
|
object_set_vertex_buffer_load(set);
|
|
object_set_index_buffer_load(set);
|
|
}
|
|
|
|
bool object_set_load_db_entry(object_set_info** set_info,
|
|
void* data, object_database* obj_db, char* name) {
|
|
if (!object_database_get_object_set_info(obj_db, name, set_info))
|
|
return false;
|
|
else if (object_storage_get_object_set((*set_info)->id)) {
|
|
object_storage_append_object_set((*set_info)->id);
|
|
return true;
|
|
}
|
|
|
|
size_t temp[2];
|
|
temp[0] = (size_t)data;
|
|
temp[1] = (size_t)*set_info;
|
|
return data_struct_load_file(data, temp, "rom/objset/",
|
|
string_data(&(*set_info)->archive_file_name), object_set_load_file);
|
|
}
|
|
|
|
bool object_set_load_by_db_entry(object_set_info* set_info,
|
|
void* data, object_database* obj_db) {
|
|
if (object_storage_get_object_set(set_info->id)) {
|
|
object_storage_append_object_set(set_info->id);
|
|
return true;
|
|
}
|
|
|
|
size_t temp[2];
|
|
temp[0] = (size_t)data;
|
|
temp[1] = (size_t)set_info;
|
|
return data_struct_load_file(data, temp, "rom/objset/",
|
|
string_data(&set_info->archive_file_name), object_set_load_file);
|
|
}
|
|
|
|
bool object_set_load_by_db_index(object_set_info** set_info,
|
|
void* data, object_database* obj_db, uint32_t set_id) {
|
|
if (!object_database_get_object_set_info_by_set_id(obj_db, set_id, set_info))
|
|
return false;
|
|
else if (object_storage_get_object_set(set_id)) {
|
|
object_storage_append_object_set(set_id);
|
|
return true;
|
|
}
|
|
|
|
size_t temp[2];
|
|
temp[0] = (size_t)data;
|
|
temp[1] = (size_t)*set_info;
|
|
return data_struct_load_file(data, temp, "rom/objset/",
|
|
string_data(&(*set_info)->archive_file_name), object_set_load_file);
|
|
}
|
|
|
|
bool object_set_load_by_hash(void* data,
|
|
object_database* obj_db, texture_database* tex_db, uint32_t hash) {
|
|
size_t temp[2];
|
|
temp[0] = (size_t)obj_db;
|
|
temp[1] = (size_t)tex_db;
|
|
return data_struct_load_file_by_hash(data, temp, "rom/objset/",
|
|
hash, object_set_load_file_modern);
|
|
}
|
|
|
|
void object_set_free(object_set* set) {
|
|
if (!set)
|
|
return;
|
|
|
|
string_free(&set->name);
|
|
|
|
bool is_x = set->is_x;
|
|
for (int32_t i = 0; i < set->objects_count; i++) {
|
|
object* obj = &set->objects[i];
|
|
for (int32_t j = 0; j < obj->skin.bones_count; j++)
|
|
string_free(&obj->skin.bones[j].name);
|
|
free(obj->skin.bones);
|
|
obj->skin.bones_count = 0;
|
|
|
|
for (int32_t j = 0; j < obj->skin.ex_data.blocks_count; j++) {
|
|
object_skin_block* block = &obj->skin.ex_data.blocks[j];
|
|
switch (block->type) {
|
|
case OBJ_SKIN_BLOCK_CLOTH: {
|
|
object_skin_block_cloth* cloth = &block->cloth;
|
|
string_free(&cloth->mesh_name);
|
|
string_free(&cloth->backface_mesh_name);
|
|
|
|
for (uint32_t k = 0; k < cloth->count; k++) {
|
|
object_skin_block_cloth_field_1C* sub = &cloth->field_1C[k];
|
|
string_free(&sub->sub_data_0.bone_name);
|
|
string_free(&sub->sub_data_1.bone_name);
|
|
string_free(&sub->sub_data_2.bone_name);
|
|
string_free(&sub->sub_data_3.bone_name);
|
|
}
|
|
free(cloth->field_1C);
|
|
free(cloth->field_20);
|
|
free(cloth->field_24);
|
|
free(cloth->field_28);
|
|
cloth->count = 0;
|
|
} break;
|
|
case OBJ_SKIN_BLOCK_CONSTRAINT: {
|
|
object_skin_block_constraint* constraint = &block->constraint;
|
|
object_skin_block_node_free(&constraint->base);
|
|
string_free(&constraint->source_node_name);
|
|
} break;
|
|
case OBJ_SKIN_BLOCK_EXPRESSION: {
|
|
object_skin_block_expression* expression = &block->expression;
|
|
object_skin_block_node_free(&expression->base);
|
|
for (int32_t k = 0; k < 9; k++)
|
|
string_free(&expression->expressions[k]);
|
|
expression->expressions_count = 0;
|
|
} break;
|
|
case OBJ_SKIN_BLOCK_MOTION: {
|
|
object_skin_block_motion* motion = &block->motion;
|
|
object_skin_block_node_free(&motion->base);
|
|
if (is_x)
|
|
string_free(&motion->name);
|
|
free(motion->nodes);
|
|
motion->nodes_count = 0;
|
|
} break;
|
|
case OBJ_SKIN_BLOCK_OSAGE: {
|
|
object_skin_block_osage* osage = &block->osage;
|
|
object_skin_block_node_free(&osage->base);
|
|
free(osage->nodes);
|
|
osage->nodes_count = 0;
|
|
} break;
|
|
}
|
|
}
|
|
free(obj->skin.ex_data.blocks);
|
|
obj->skin.ex_data.blocks_count = 0;
|
|
|
|
free(obj->skin.ex_data.osage_nodes);
|
|
obj->skin.ex_data.osage_nodes_count = 0;
|
|
|
|
free(obj->skin.ex_data.bone_names_buf);
|
|
free(obj->skin.ex_data.bone_names);
|
|
obj->skin.ex_data.bone_names_count = 0;
|
|
|
|
free(obj->skin.ex_data.osage_sibling_infos);
|
|
obj->skin.ex_data.osage_sibling_infos_count = 0;
|
|
|
|
if (obj->meshes)
|
|
for (int32_t j = 0; j < obj->meshes_count; j++) {
|
|
object_mesh* mesh = &obj->meshes[j];
|
|
if (mesh->sub_meshes)
|
|
for (int32_t k = 0; k < mesh->sub_meshes_count; k++) {
|
|
object_sub_mesh* sub_mesh = &mesh->sub_meshes[k];
|
|
free(sub_mesh->bone_indices);
|
|
sub_mesh->bone_indices_count = 0;
|
|
}
|
|
free(mesh->vertex);
|
|
mesh->vertex_count = 0;
|
|
free(mesh->indices);
|
|
mesh->indices_count = 0;
|
|
free(mesh->sub_meshes);
|
|
mesh->sub_meshes_count = 0;
|
|
}
|
|
free(obj->meshes);
|
|
obj->meshes_count = 0;
|
|
free(obj->materials);
|
|
obj->materials_count = 0;
|
|
string_free(&obj->name);
|
|
}
|
|
free(set->objects);
|
|
set->objects_count = 0;
|
|
free(set->texture_ids);
|
|
set->texture_ids_count = 0;
|
|
for (int32_t i = 0; i < set->texture_names_count; i++)
|
|
string_free(&set->texture_names[i]);
|
|
free(set->texture_names);
|
|
set->texture_names_count = 0;
|
|
|
|
free(set->textures);
|
|
set->textures_count = 0;
|
|
free(set->texture_data);
|
|
|
|
object_set_vertex_buffer_free(set);
|
|
object_set_index_buffer_free(set);
|
|
}
|
|
|
|
inline object_material_shader_lighting_type object_material_shader_get_lighting_type(
|
|
object_material_shader_flags* flags) {
|
|
if (!flags->lambert_shading && !flags->phong_shading)
|
|
return OBJECT_MATERIAL_SHADER_LIGHTING_CONSTANT;
|
|
else if (!flags->phong_shading)
|
|
return OBJECT_MATERIAL_SHADER_LIGHTING_LAMBERT;
|
|
else
|
|
return OBJECT_MATERIAL_SHADER_LIGHTING_PHONG;
|
|
}
|
|
|
|
inline int32_t object_material_texture_get_blend(object_material_texture* tex) {
|
|
switch (tex->sampler_flags.blend) {
|
|
case 4:
|
|
return 2;
|
|
case 6:
|
|
return 1;
|
|
case 16:
|
|
return 3;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
inline int32_t object_material_texture_type_get_texcoord_index(
|
|
object_material_texture_type type, int32_t index) {
|
|
switch (type) {
|
|
case OBJECT_MATERIAL_TEXTURE_COLOR:
|
|
case OBJECT_MATERIAL_TEXTURE_ENVIRONMENT_SPHERE: // XHD
|
|
if (index < 2)
|
|
return index;
|
|
case OBJECT_MATERIAL_TEXTURE_NORMAL:
|
|
case OBJECT_MATERIAL_TEXTURE_SPECULAR:
|
|
return 0;
|
|
case OBJECT_MATERIAL_TEXTURE_TRANSLUCENCY:
|
|
case OBJECT_MATERIAL_TEXTURE_TRANSPARENCY:
|
|
return 1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
inline int32_t object_material_texture_type_get_texture_index(
|
|
object_material_texture_type type, int32_t base_index) {
|
|
switch (type) {
|
|
case OBJECT_MATERIAL_TEXTURE_COLOR:
|
|
case OBJECT_MATERIAL_TEXTURE_ENVIRONMENT_SPHERE: // XHD
|
|
if (base_index < 2)
|
|
return base_index;
|
|
case OBJECT_MATERIAL_TEXTURE_NORMAL:
|
|
return 2;
|
|
case OBJECT_MATERIAL_TEXTURE_SPECULAR:
|
|
return 3;
|
|
case OBJECT_MATERIAL_TEXTURE_TRANSLUCENCY:
|
|
return 1;
|
|
case OBJECT_MATERIAL_TEXTURE_TRANSPARENCY:
|
|
return 4;
|
|
//case OBJECT_MATERIAL_TEXTURE_ENVIRONMENT_SPHERE: // AFT
|
|
case OBJECT_MATERIAL_TEXTURE_ENVIRONMENT_CUBE:
|
|
return 5;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
inline GLuint object_mesh_vertex_buffer_get_buffer(object_mesh_vertex_buffer* buffer) {
|
|
if (buffer->index < buffer->count)
|
|
return buffer->buffers[buffer->index];
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
inline int32_t object_mesh_vertex_buffer_get_size(object_mesh_vertex_buffer* buffer) {
|
|
if (!buffer->buffers[0])
|
|
return 0;
|
|
|
|
int32_t size = 0;
|
|
gl_state_bind_array_buffer(buffer->buffers[0]);
|
|
glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
|
|
gl_state_bind_array_buffer(buffer->buffers[0]);
|
|
return size;
|
|
}
|
|
|
|
void object_skin_set_matrix_buffer(object_skin* s, mat4* matrices,
|
|
mat4* ex_data_matrices, mat4* matrix_buffer, mat4* mat, mat4* global_mat) {
|
|
if (!s->bones_count)
|
|
return;
|
|
|
|
if (mat)
|
|
for (int32_t i = 0; i < s->bones_count; i++) {
|
|
mat4 temp;
|
|
int32_t bone_id = s->bones[i].id;
|
|
if (bone_id & 0x8000)
|
|
if (ex_data_matrices)
|
|
mat4_mult(mat, &ex_data_matrices[bone_id & 0x7FFF], &temp);
|
|
else
|
|
temp = *mat;
|
|
else
|
|
mat4_mult(mat, &matrices[bone_id], &temp);
|
|
|
|
mat4_mult(&temp, global_mat, &temp);
|
|
|
|
mat4 inv_bind_pose_mat;
|
|
mat4u_to_mat4(&s->bones[i].inv_bind_pose_mat, &inv_bind_pose_mat);
|
|
mat4_mult(&inv_bind_pose_mat, &temp, &matrix_buffer[i]);
|
|
}
|
|
else
|
|
for (int32_t i = 0; i < s->bones_count; i++) {
|
|
mat4 temp;
|
|
int32_t bone_id = s->bones[i].id;
|
|
if (bone_id & 0x8000)
|
|
if (ex_data_matrices)
|
|
temp = ex_data_matrices[bone_id & 0x7FFF];
|
|
else
|
|
temp = mat4_identity;
|
|
else
|
|
temp = matrices[bone_id];
|
|
|
|
mat4_mult(&temp, global_mat, &temp);
|
|
|
|
mat4 inv_bind_pose_mat;
|
|
mat4u_to_mat4(&s->bones[i].inv_bind_pose_mat, &inv_bind_pose_mat);
|
|
mat4_mult(&inv_bind_pose_mat, &temp, &matrix_buffer[i]);
|
|
}
|
|
}
|
|
|
|
inline void object_storage_init() {
|
|
object_storage_data = vector_empty(object_storage);
|
|
}
|
|
|
|
inline void object_storage_append_object_set(uint32_t set_id) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++)
|
|
if (i->set_id == set_id) {
|
|
i->count++;
|
|
return;
|
|
}
|
|
}
|
|
|
|
inline void object_storage_insert_object_set(object_set* set, uint32_t set_id) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++)
|
|
if (i->set_id == set_id) {
|
|
object_set_free(&i->set);
|
|
i->count++;
|
|
i->set = *set;
|
|
return;
|
|
}
|
|
|
|
object_storage* obj_set_storage = vector_object_storage_reserve_back(&object_storage_data);
|
|
obj_set_storage->set_id = set_id;
|
|
obj_set_storage->count = 1;
|
|
obj_set_storage->set = *set;
|
|
}
|
|
|
|
inline object* object_storage_get_object(object_info obj_info) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++)
|
|
if (i->set_id == obj_info.set_id) {
|
|
object_set* set = &i->set;
|
|
for (int32_t j = 0; j < set->objects_count; j++)
|
|
if (set->objects[j].id == obj_info.id)
|
|
return &set->objects[j];
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
inline object_mesh* object_storage_get_object_mesh(object_info obj_info, char* mesh_name) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++)
|
|
if (i->set_id == obj_info.set_id) {
|
|
object_set* set = &i->set;
|
|
for (int32_t j = 0; j < set->objects_count; j++)
|
|
if (set->objects[j].id == obj_info.id) {
|
|
object* obj = &set->objects[j];
|
|
for (int32_t k = 0; k < obj->meshes_count; k++)
|
|
if (!str_utils_compare(obj->meshes[k].name, mesh_name))
|
|
return &obj->meshes[k];
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
inline object_mesh* object_storage_get_object_mesh_by_index(object_info obj_info, int32_t index) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++)
|
|
if (i->set_id == obj_info.set_id) {
|
|
object_set* set = &i->set;
|
|
for (int32_t j = 0; j < set->objects_count; j++)
|
|
if (set->objects[j].id == obj_info.id) {
|
|
object* obj = &set->objects[j];
|
|
if (index > -1 && index < obj->meshes_count)
|
|
return &obj->meshes[index];
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
inline object_mesh* object_storage_get_object_mesh_by_object_hash(uint32_t hash, char* mesh_name) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) {
|
|
object_set* set = &i->set;
|
|
for (int32_t j = 0; j < set->objects_count; j++)
|
|
if (set->objects[j].hash == hash) {
|
|
object* obj = &set->objects[j];
|
|
for (int32_t k = 0; k < obj->meshes_count; k++)
|
|
if (!str_utils_compare(obj->meshes[k].name, mesh_name))
|
|
return &obj->meshes[k];
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
inline object_mesh* object_storage_get_object_mesh_by_object_hash_index(uint32_t hash, int32_t index) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) {
|
|
object_set* set = &i->set;
|
|
for (int32_t j = 0; j < set->objects_count; j++)
|
|
if (set->objects[j].hash == hash) {
|
|
object* obj = &set->objects[j];
|
|
if (index > -1 && index < obj->meshes_count)
|
|
return &obj->meshes[index];
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
inline int32_t object_storage_get_object_mesh_index(object_info obj_info, char* mesh_name) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++)
|
|
if (i->set_id == obj_info.set_id) {
|
|
object_set* set = &i->set;
|
|
for (int32_t j = 0; j < set->objects_count; j++)
|
|
if (set->objects[j].id == obj_info.id) {
|
|
object* obj = &set->objects[j];
|
|
for (int32_t k = 0; k < obj->meshes_count; k++)
|
|
if (!str_utils_compare(obj->meshes[k].name, mesh_name))
|
|
return k;
|
|
return -1;
|
|
}
|
|
return -1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
inline int32_t object_storage_get_object_mesh_index_by_hash(uint32_t hash, char* mesh_name) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) {
|
|
object_set* set = &i->set;
|
|
for (int32_t j = 0; j < set->objects_count; j++)
|
|
if (set->objects[j].hash == hash) {
|
|
object* obj = &set->objects[j];
|
|
for (int32_t k = 0; k < obj->meshes_count; k++)
|
|
if (!str_utils_compare(obj->meshes[k].name, mesh_name))
|
|
return k;
|
|
return -1;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
inline object_set* object_storage_get_object_set(uint32_t set_id) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++)
|
|
if (i->set_id == set_id)
|
|
return &i->set;
|
|
return 0;
|
|
}
|
|
|
|
inline ssize_t object_storage_get_object_set_count() {
|
|
return vector_length(object_storage_data);
|
|
}
|
|
|
|
inline int32_t object_storage_get_object_set_load_count(uint32_t set_id) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++)
|
|
if (i->set_id == set_id)
|
|
return i->count;
|
|
return 0;
|
|
}
|
|
|
|
inline object_set* object_storage_get_object_set_by_index(ssize_t index) {
|
|
if (index >= 0 && index < vector_length(object_storage_data))
|
|
return &object_storage_data.begin[index].set;
|
|
return 0;
|
|
}
|
|
|
|
inline int32_t object_storage_get_object_set_load_count_by_index(ssize_t index) {
|
|
if (index >= 0 && index < vector_length(object_storage_data))
|
|
return object_storage_data.begin[index].count;
|
|
return 0;
|
|
}
|
|
|
|
inline ssize_t object_storage_get_object_set_index(uint32_t set_id) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++)
|
|
if (i->set_id == set_id)
|
|
return i - object_storage_data.begin;
|
|
return -1;
|
|
}
|
|
|
|
inline object_skin* object_storage_get_object_skin(object_info obj_info) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++)
|
|
if (i->set_id == obj_info.set_id) {
|
|
object_set* set = &i->set;
|
|
for (int32_t j = 0; j < set->objects_count; j++)
|
|
if (set->objects[j].id == obj_info.id)
|
|
return set->objects[j].skin_init ? &set->objects[j].skin : 0;
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
inline object_index_buffer* object_storage_get_object_index_buffers(uint32_t set_id) {
|
|
object_set* set = object_storage_get_object_set(set_id);
|
|
if (!set || !set->index_buffers)
|
|
return 0;
|
|
|
|
return set->index_buffers;
|
|
}
|
|
|
|
inline object_mesh_index_buffer* object_storage_get_object_mesh_index_buffer(object_info obj_info) {
|
|
object_set* set = object_storage_get_object_set(obj_info.set_id);
|
|
if (!set || !set->index_buffers)
|
|
return 0;
|
|
|
|
for (int32_t i = 0; i < set->objects_count; i++)
|
|
if (set->objects[i].id == obj_info.id)
|
|
return set->index_buffers[i].meshes;
|
|
|
|
return 0;
|
|
}
|
|
|
|
inline object_vertex_buffer* object_storage_get_object_vertex_buffers(uint32_t set_id) {
|
|
object_set* set = object_storage_get_object_set(set_id);
|
|
if (!set || !set->vertex_buffers)
|
|
return 0;
|
|
|
|
return set->vertex_buffers;
|
|
}
|
|
|
|
inline object_mesh_vertex_buffer* object_storage_get_object_mesh_vertex_buffer(object_info obj_info) {
|
|
object_set* set = object_storage_get_object_set(obj_info.set_id);
|
|
if (!set || !set->vertex_buffers)
|
|
return 0;
|
|
|
|
for (int32_t i = 0; i < set->objects_count; i++)
|
|
if (set->objects[i].id == obj_info.id)
|
|
return set->vertex_buffers[i].meshes;
|
|
|
|
return 0;
|
|
}
|
|
|
|
inline GLuint* object_storage_get_textures(uint32_t set_id) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++)
|
|
if (i->set_id == set_id)
|
|
return i->set.textures;
|
|
return 0;
|
|
}
|
|
|
|
inline uint32_t* object_storage_get_texture_ids(uint32_t set_id) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++)
|
|
if (i->set_id == set_id)
|
|
return i->set.texture_ids;
|
|
return 0;
|
|
}
|
|
|
|
inline void object_storage_delete_object_set(uint32_t set_id) {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++)
|
|
if (i->set_id == set_id) {
|
|
i->count--;
|
|
if (i->count > 0)
|
|
break;
|
|
|
|
object_set* set = &i->set;
|
|
for (int32_t j = 0; j < set->texture_ids_count; j++)
|
|
texture_storage_delete_texture(set->texture_ids[j]);
|
|
object_set_free(set);
|
|
|
|
vector_object_storage_erase(&object_storage_data,
|
|
i - object_storage_data.begin, 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
inline void object_storage_free() {
|
|
for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++)
|
|
object_set_free(&i->set);
|
|
vector_object_storage_free(&object_storage_data, 0);
|
|
}
|
|
|
|
static bool object_mesh_index_buffer_load(object_mesh_index_buffer* buffer, object_mesh* mesh) {
|
|
if (!mesh->indices_count || !mesh->vertex) {
|
|
*buffer = 0;
|
|
return true;
|
|
}
|
|
|
|
*buffer = object_mesh_index_buffer_load_data(sizeof(uint16_t) * mesh->indices_count, mesh->indices);
|
|
return true;
|
|
}
|
|
|
|
static GLuint object_mesh_index_buffer_load_data(size_t size, void* data) {
|
|
if (!size)
|
|
return 0;
|
|
|
|
GLuint buffer = 0;
|
|
glGenBuffers(1, &buffer);
|
|
gl_state_bind_element_array_buffer(buffer);
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)size, data, GL_STATIC_DRAW);
|
|
gl_state_bind_element_array_buffer(0);
|
|
return buffer;
|
|
}
|
|
|
|
static void object_mesh_index_buffer_free(object_mesh_index_buffer* buffer) {
|
|
glDeleteBuffers(1, (GLuint*)buffer);
|
|
}
|
|
|
|
static bool object_mesh_vertex_buffer_load(object_mesh_vertex_buffer* buffer, object_mesh* mesh) {
|
|
if (!mesh->vertex_size || !mesh->vertex_count || !mesh->vertex)
|
|
return false;
|
|
|
|
return object_mesh_vertex_buffer_load_data(buffer, (size_t)mesh->vertex_size * mesh->vertex_count,
|
|
mesh->vertex, mesh->flags & OBJECT_MESH_FLAG_1 ? 2 : 1);
|
|
}
|
|
|
|
static bool object_mesh_vertex_buffer_load_data(object_mesh_vertex_buffer* buffer,
|
|
size_t size, void* data, int32_t count) {
|
|
if (!size || count > 3)
|
|
return false;
|
|
|
|
buffer->count = count;
|
|
|
|
glGenBuffers(count, buffer->buffers);
|
|
for (int32_t i = 0; i < count; i++) {
|
|
gl_state_bind_array_buffer(buffer->buffers[i]);
|
|
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)size, data, GL_STATIC_DRAW);
|
|
}
|
|
gl_state_bind_array_buffer(0);
|
|
return true;
|
|
}
|
|
|
|
static void object_mesh_vertex_buffer_free(object_mesh_vertex_buffer* buffer) {
|
|
glDeleteBuffers(buffer->count, buffer->buffers);
|
|
}
|
|
|
|
static bool object_set_index_buffer_load(object_set* set) {
|
|
set->index_buffers_count = set->objects_count;
|
|
set->index_buffers = force_malloc_s(object_index_buffer, set->objects_count);
|
|
if (!set->index_buffers)
|
|
return false;
|
|
|
|
for (int32_t i = 0; i < set->objects_count; i++) {
|
|
object* obj = &set->objects[i];
|
|
object_index_buffer* buffer = &set->index_buffers[i];
|
|
|
|
buffer->meshes_count = obj->meshes_count;
|
|
buffer->meshes = force_malloc_s(object_mesh_index_buffer, obj->meshes_count);
|
|
if (!buffer->meshes)
|
|
return false;
|
|
|
|
for (int32_t j = 0; j < buffer->meshes_count; j++)
|
|
if (!object_mesh_index_buffer_load(&buffer->meshes[j], &obj->meshes[j]))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static void object_set_index_buffer_free(object_set* set) {
|
|
if (!set->index_buffers)
|
|
return;
|
|
|
|
for (int32_t i = 0; i < set->index_buffers_count; i++) {
|
|
object_index_buffer* buffer = &set->index_buffers[i];
|
|
if (buffer->meshes)
|
|
for (int32_t j = 0; j < buffer->meshes_count; j++)
|
|
object_mesh_index_buffer_free(&buffer->meshes[j]);
|
|
free(buffer->meshes);
|
|
}
|
|
free(set->index_buffers);
|
|
set->index_buffers_count = 0;
|
|
}
|
|
|
|
static bool object_set_vertex_buffer_load(object_set* set) {
|
|
set->vertex_buffers_count = set->objects_count;
|
|
set->vertex_buffers = force_malloc_s(object_vertex_buffer, set->objects_count);
|
|
if (!set->vertex_buffers)
|
|
return false;
|
|
|
|
for (int32_t i = 0; i < set->objects_count; i++) {
|
|
object* obj = &set->objects[i];
|
|
object_vertex_buffer* buffer = &set->vertex_buffers[i];
|
|
|
|
buffer->meshes_count = obj->meshes_count;
|
|
buffer->meshes = force_malloc_s(object_mesh_vertex_buffer, obj->meshes_count);
|
|
if (!buffer->meshes)
|
|
return false;
|
|
|
|
for (int32_t j = 0; j < buffer->meshes_count; j++)
|
|
if (!object_mesh_vertex_buffer_load(&buffer->meshes[j], &obj->meshes[j]))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static void object_set_vertex_buffer_free(object_set* set) {
|
|
if (!set->vertex_buffers)
|
|
return;
|
|
|
|
for (int32_t i = 0; i < set->vertex_buffers_count; i++) {
|
|
object_vertex_buffer* buffer = &set->vertex_buffers[i];
|
|
if (buffer->meshes)
|
|
for (int32_t j = 0; j < buffer->meshes_count; j++)
|
|
object_mesh_vertex_buffer_free(&buffer->meshes[j]);
|
|
free(buffer->meshes);
|
|
}
|
|
free(set->vertex_buffers);
|
|
set->vertex_buffers_count = 0;
|
|
}
|
|
|
|
inline static void object_skin_block_constraint_attach_point_load(
|
|
object_skin_block_constraint_attach_point* attach_point,
|
|
object_skin_block_constraint_attach_point_file* attach_point_file) {
|
|
attach_point->affected_by_orientation = attach_point_file->affected_by_orientation;
|
|
attach_point->affected_by_scaling = attach_point_file->affected_by_scaling;
|
|
attach_point->offset = attach_point_file->offset;
|
|
}
|
|
inline static void object_skin_block_constraint_up_vector_load(
|
|
object_skin_block_constraint_up_vector* up_vector,
|
|
object_skin_block_constraint_up_vector_file* up_vector_file) {
|
|
up_vector->active = up_vector_file->active;
|
|
up_vector->roll = up_vector_file->roll;
|
|
up_vector->affected_axis = up_vector_file->affected_axis;
|
|
up_vector->point_at = up_vector_file->point_at;
|
|
string_copy(&up_vector_file->name, &up_vector->name);
|
|
}
|
|
|
|
|
|
inline static void object_skin_block_node_load(object_skin_block_node* node,
|
|
object_skin_block_node_file* node_file) {
|
|
string_copy(&node_file->parent_name, &node->parent_name);
|
|
node->position = node_file->position;
|
|
node->rotation = node_file->rotation;
|
|
node->scale = node_file->scale;
|
|
}
|
|
|
|
inline static void object_skin_block_node_free(object_skin_block_node* node) {
|
|
string_free(&node->parent_name);
|
|
}
|
|
|
|
inline static size_t object_vertex_flags_get_vertex_size(object_vertex_flags flags) {
|
|
size_t size = 0;
|
|
if (flags & OBJECT_VERTEX_POSITION)
|
|
size += 12;
|
|
if (flags & OBJECT_VERTEX_NORMAL)
|
|
size += 12;
|
|
if (flags & OBJECT_VERTEX_TANGENT)
|
|
size += 16;
|
|
if (flags & OBJECT_VERTEX_BINORMAL)
|
|
size += 12;
|
|
if (flags & OBJECT_VERTEX_TEXCOORD0)
|
|
size += 8;
|
|
if (flags & OBJECT_VERTEX_TEXCOORD1)
|
|
size += 8;
|
|
if (flags & OBJECT_VERTEX_TEXCOORD2)
|
|
size += 8;
|
|
if (flags & OBJECT_VERTEX_TEXCOORD3)
|
|
size += 8;
|
|
if (flags & OBJECT_VERTEX_COLOR0)
|
|
size += 16;
|
|
if (flags & OBJECT_VERTEX_COLOR1)
|
|
size += 16;
|
|
if (flags & OBJECT_VERTEX_BONE_DATA)
|
|
size += 32;
|
|
if (flags & OBJECT_VERTEX_UNKNOWN)
|
|
size += 16;
|
|
return size;
|
|
}
|
|
|
|
inline static size_t object_vertex_flags_get_vertex_size_comp(object_vertex_flags flags) {
|
|
size_t size = 0;
|
|
if (flags & OBJECT_VERTEX_POSITION)
|
|
size += 12;
|
|
if (flags & OBJECT_VERTEX_NORMAL)
|
|
size += 8;
|
|
if (flags & OBJECT_VERTEX_TANGENT)
|
|
size += 8;
|
|
if (flags & OBJECT_VERTEX_TEXCOORD0)
|
|
size += 4;
|
|
if (flags & OBJECT_VERTEX_TEXCOORD1)
|
|
size += 4;
|
|
if (flags & OBJECT_VERTEX_TEXCOORD2)
|
|
size += 4;
|
|
if (flags & OBJECT_VERTEX_TEXCOORD3)
|
|
size += 4;
|
|
if (flags & OBJECT_VERTEX_COLOR0)
|
|
size += 8;
|
|
if (flags & OBJECT_VERTEX_BONE_DATA)
|
|
size += 16;
|
|
return size;
|
|
}
|
|
|
|
static bool object_set_load_file(void* data, char* path, char* file, uint32_t hash) {
|
|
data_struct* ds = (void*)((size_t*)data)[0];
|
|
data_ft* d = &ds->data_ft;
|
|
|
|
object_set_info* set_info = (void*)((size_t*)data)[1];
|
|
|
|
farc f;
|
|
farc_init(&f);
|
|
if (!farc_load_file(&f, path, file, hash))
|
|
return false;
|
|
|
|
farc_file* obj = farc_read_file(&f, string_data(&set_info->object_file_name));
|
|
farc_file* tex = farc_read_file(&f, string_data(&set_info->texture_file_name));
|
|
|
|
if (obj && tex) {
|
|
obj_set obj_set;
|
|
obj_init(&obj_set);
|
|
obj_mread(&obj_set, obj->data, obj->size, false);
|
|
|
|
txp_set txp_set;
|
|
txp_set_init(&txp_set);
|
|
txp_set_unpack_file(&txp_set, tex->data, false);
|
|
|
|
if (obj_set.ready) {
|
|
object_set object_set;
|
|
object_set_init(&object_set);
|
|
object_set_load(&object_set, &obj_set, &txp_set, &d->tex_db, &set_info->name, set_info->id, true);
|
|
object_storage_insert_object_set(&object_set, set_info->id);
|
|
}
|
|
|
|
obj_free(&obj_set);
|
|
txp_set_free(&txp_set);
|
|
}
|
|
farc_free(&f);
|
|
return true;
|
|
}
|
|
|
|
static bool object_set_load_file_modern(void* data, char* path, char* file, uint32_t hash) {
|
|
object_database* obj_db = (void*)((size_t*)data)[0];
|
|
texture_database* tex_db = (void*)((size_t*)data)[1];
|
|
|
|
farc f;
|
|
farc_init(&f);
|
|
if (!farc_load_file(&f, path, file, hash))
|
|
return false;
|
|
|
|
char buf[0x100];
|
|
size_t file_len = utf8_length(file);
|
|
if (file_len >= 0x100) {
|
|
farc_free(&f);
|
|
return false;
|
|
}
|
|
|
|
memcpy(buf, file, file_len);
|
|
char* ext = buf + file_len - 5;
|
|
|
|
memcpy(ext, ".osd", 5);
|
|
farc_file* osd = farc_read_file(&f, buf);
|
|
|
|
memcpy(ext, ".txd", 5);
|
|
farc_file* txd = farc_read_file(&f, buf);
|
|
|
|
memcpy(ext, ".osi", 5);
|
|
farc_file* osi = farc_read_file(&f, buf);
|
|
|
|
memcpy(ext, ".txi", 5);
|
|
farc_file* txi = farc_read_file(&f, buf);
|
|
|
|
if (osd && txd && osi && txi) {
|
|
obj_set obj_set;
|
|
obj_init(&obj_set);
|
|
obj_mread(&obj_set, osd->data, osd->size, true);
|
|
|
|
txp_set txp_set;
|
|
txp_set_init(&txp_set);
|
|
txp_set_unpack_file_modern(&txp_set, txd->data, txd->size);
|
|
|
|
object_database_mread(obj_db, osi->data, osi->size, true);
|
|
texture_database_mread(tex_db, txi->data, txi->size, true);
|
|
|
|
string* name = 0;
|
|
if (obj_db->ready)
|
|
for (object_set_info* m = obj_db->object_set.begin; m != obj_db->object_set.end; m++)
|
|
if (m->id == hash) {
|
|
name = &m->name;
|
|
break;
|
|
}
|
|
|
|
if (name && obj_set.ready)
|
|
if (!object_storage_get_object_set(hash)) {
|
|
object_set object_set;
|
|
object_set_init(&object_set);
|
|
object_set_load(&object_set, &obj_set, &txp_set, tex_db, name, hash, true);
|
|
object_storage_insert_object_set(&object_set, hash);
|
|
}
|
|
else
|
|
object_storage_append_object_set(hash);
|
|
|
|
obj_free(&obj_set);
|
|
txp_set_free(&txp_set);
|
|
}
|
|
farc_free(&f);
|
|
return true;
|
|
}
|