diff --git a/include/reign.h b/include/reign.h index 5325ed7..a5cb8ed 100644 --- a/include/reign.h +++ b/include/reign.h @@ -17,7 +17,6 @@ #ifndef SYSTEM4_REIGN_H #define SYSTEM4_REIGN_H -#define RE_MAX_INSTANCES 32 #define RE_NR_BACK_CGS 16 #include @@ -66,7 +65,8 @@ struct RE_back_cg { struct RE_plugin { struct draw_plugin plugin; int sprite; - struct RE_instance *instances[RE_MAX_INSTANCES]; + int nr_instances; + struct RE_instance **instances; struct archive *aar; struct RE_renderer *renderer; struct RE_camera camera; @@ -142,6 +142,8 @@ bool RE_instance_load_motion(struct RE_instance *instance, const char *name); bool RE_instance_load_next_motion(struct RE_instance *instance, const char *name); bool RE_instance_free_next_motion(struct RE_instance *instance); bool RE_instance_set_vertex_pos(struct RE_instance *instance, int index, float x, float y, float z); +int RE_instance_get_bone_index(struct RE_instance *instance, const char *name); +bool RE_instance_trans_local_pos_to_world_pos_by_bone(struct RE_instance *instance, int bone, vec3 offset, vec3 out); int RE_motion_get_state(struct motion *motion); bool RE_motion_set_state(struct motion *motion, int state); diff --git a/src/3d/3d_internal.h b/src/3d/3d_internal.h index 4215f73..55dddb0 100644 --- a/src/3d/3d_internal.h +++ b/src/3d/3d_internal.h @@ -121,6 +121,10 @@ struct billboard_texture { GLuint texture; }; +// reign.c + +void RE_instance_update_local_transform(struct RE_instance *inst); + // model.c struct model *model_load(struct archive *aar, const char *path, struct RE_renderer *renderer); diff --git a/src/3d/debug.c b/src/3d/debug.c index 3de2782..8cb14dc 100644 --- a/src/3d/debug.c +++ b/src/3d/debug.c @@ -120,7 +120,7 @@ void RE_debug_print(struct sact_sprite *sp, int indent) indent_printf(indent, "camera = {x=%f, y=%f, z=%f, pitch=%f, roll=%f, yaw=%f},\n", SPREAD_VEC3(p->camera.pos), p->camera.pitch, p->camera.roll, p->camera.yaw); - for (int i = 0; i < RE_MAX_INSTANCES; i++) + for (int i = 0; i < p->nr_instances; i++) print_instance(p->instances[i], i, indent); for (int i = 0; i < RE_NR_BACK_CGS; i++) diff --git a/src/3d/reign.c b/src/3d/reign.c index 8c9e5a2..92fe549 100644 --- a/src/3d/reign.c +++ b/src/3d/reign.c @@ -173,6 +173,8 @@ struct RE_plugin *RE_plugin_new(void) plugin->plugin.name = "ReignEngine"; plugin->plugin.update = RE_render; plugin->plugin.debug_print = RE_debug_print; + plugin->nr_instances = 16; + plugin->instances = xcalloc(plugin->nr_instances, sizeof(struct RE_instance *)); plugin->aar = aar; for (int i = 0; i < RE_NR_BACK_CGS; i++) RE_back_cg_init(&plugin->back_cg[i]); @@ -181,10 +183,11 @@ struct RE_plugin *RE_plugin_new(void) void RE_plugin_free(struct RE_plugin *plugin) { - for (int i = 0; i < RE_MAX_INSTANCES; i++) { + for (int i = 0; i < plugin->nr_instances; i++) { if (plugin->instances[i]) free_instance(plugin->instances[i]); } + free(plugin->instances); archive_free(plugin->aar); if (plugin->renderer) RE_renderer_free(plugin->renderer); @@ -221,10 +224,8 @@ bool RE_build_model(struct RE_plugin *plugin, int elapsed_ms) { if (!plugin) return false; - if (elapsed_ms <= 0) - return true; - for (int i = 0; i < RE_MAX_INSTANCES; i++) { + for (int i = 0; i < plugin->nr_instances; i++) { if (plugin->instances[i]) animate(plugin->instances[i], elapsed_ms); } @@ -243,14 +244,17 @@ int RE_create_instance(struct RE_plugin *plugin) { if (!plugin) return -1; - for (int i = 0; i < RE_MAX_INSTANCES; i++) { + for (int i = 0; i < plugin->nr_instances; i++) { if (!plugin->instances[i]) { plugin->instances[i] = create_instance(plugin); return i; } } - WARNING("too many instances"); - return -1; + int old_size = plugin->nr_instances; + plugin->nr_instances *= 2; + plugin->instances = xrealloc_array(plugin->instances, old_size, plugin->nr_instances, sizeof(struct RE_instance *)); + plugin->instances[old_size] = create_instance(plugin); + return old_size; } bool RE_release_instance(struct RE_plugin *plugin, int instance) @@ -346,6 +350,52 @@ bool RE_instance_set_vertex_pos(struct RE_instance *instance, int index, float x return false; } +int RE_instance_get_bone_index(struct RE_instance *instance, const char *name) +{ + if (!instance || !instance->model) + return -1; + for (int i = 0; i < instance->model->nr_bones; i++) { + if (!strcmp(instance->model->bones[i].name, name)) + return i; + } + return -1; +} + +bool RE_instance_trans_local_pos_to_world_pos_by_bone(struct RE_instance *instance, int bone, vec3 offset, vec3 out) +{ + if (!instance || !instance->bone_transforms || (unsigned)bone >= (unsigned)instance->model->nr_bones) + return false; + + if (instance->local_transform_needs_update) + RE_instance_update_local_transform(instance); + + glm_mat4_mulv3(instance->bone_transforms[bone], offset, 1.0, out); + glm_mat4_mulv3(instance->local_transform, out, 1.0, out); + return true; +} + +void RE_instance_update_local_transform(struct RE_instance *inst) +{ + vec3 euler = { + glm_rad(inst->pitch), + glm_rad(inst->yaw), + glm_rad(inst->roll) + }; + mat4 rot; + glm_euler(euler, rot); + + glm_translate_make(inst->local_transform, inst->pos); + glm_mat4_mul(inst->local_transform, rot, inst->local_transform); + glm_scale(inst->local_transform, inst->scale); + + mat3 normal; + glm_mat4_pick3(inst->local_transform, normal); + glm_mat3_inv(normal, normal); + glm_mat3_transpose_to(normal, inst->normal_transform); + + inst->local_transform_needs_update = false; +} + int RE_motion_get_state(struct motion *motion) { return motion ? motion->state : RE_MOTION_STATE_STOP; diff --git a/src/3d/renderer.c b/src/3d/renderer.c index 39b3e6e..ae7d479 100644 --- a/src/3d/renderer.c +++ b/src/3d/renderer.c @@ -175,28 +175,6 @@ static void calc_view_matrix(struct RE_camera *camera, mat4 out) glm_look(camera->pos, front, up, out); } -static void update_local_transform(struct RE_instance *inst) -{ - vec3 euler = { - glm_rad(inst->pitch), - glm_rad(inst->yaw), - glm_rad(inst->roll) - }; - mat4 rot; - glm_euler(euler, rot); - - glm_translate_make(inst->local_transform, inst->pos); - glm_mat4_mul(inst->local_transform, rot, inst->local_transform); - glm_scale(inst->local_transform, inst->scale); - - mat3 normal; - glm_mat4_pick3(inst->local_transform, normal); - glm_mat3_inv(normal, normal); - glm_mat3_transpose_to(normal, inst->normal_transform); - - inst->local_transform_needs_update = false; -} - static void render_model(struct RE_instance *inst, struct RE_renderer *r) { struct model *model = inst->model; @@ -204,7 +182,7 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r) return; if (inst->local_transform_needs_update) - update_local_transform(inst); + RE_instance_update_local_transform(inst); glUniformMatrix4fv(r->local_transform, 1, GL_FALSE, inst->local_transform[0]); glUniformMatrix3fv(r->normal_transform, 1, GL_FALSE, inst->normal_transform[0]); @@ -343,7 +321,7 @@ static void setup_lights(struct RE_plugin *plugin) struct RE_renderer *r = plugin->renderer; glUniform3fv(r->view_pos, 1, plugin->camera.pos); int light_index = 0; - for (int i = 0; i < RE_MAX_INSTANCES; i++) { + for (int i = 0; i < plugin->nr_instances; i++) { struct RE_instance *inst = plugin->instances[i]; if (!inst) continue; @@ -419,7 +397,7 @@ void RE_render(struct sact_sprite *sp) setup_lights(plugin); - for (int i = 0; i < RE_MAX_INSTANCES; i++) { + for (int i = 0; i < plugin->nr_instances; i++) { struct RE_instance *inst = plugin->instances[i]; if (!inst || !inst->draw) continue; diff --git a/src/hll/ReignEngine.c b/src/hll/ReignEngine.c index ea503cc..711724e 100644 --- a/src/hll/ReignEngine.c +++ b/src/hll/ReignEngine.c @@ -40,7 +40,7 @@ static struct RE_instance *get_instance(unsigned plugin, unsigned instance) struct RE_plugin *rp = get_plugin(plugin); if (!rp) return NULL; - return instance < RE_MAX_INSTANCES ? rp->instances[instance] : NULL; + return instance < (unsigned)rp->nr_instances ? rp->instances[instance] : NULL; } static struct motion *get_motion(unsigned plugin, unsigned instance) @@ -463,8 +463,22 @@ static bool ReignEngine_SetInstanceFPS(int plugin, int instance, float fps) return true; } -HLL_WARN_UNIMPLEMENTED(0, int, ReignEngine, GetInstanceBoneIndex, int plugin, int instance, struct string *name); -HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, TransInstanceLocalPosToWorldPosByBone, int plugin, int instance, int bone, float offset_x, float offset_y, float offset_z, float *x, float *y, float *z); +static int ReignEngine_GetInstanceBoneIndex(int plugin, int instance, struct string *name) +{ + return RE_instance_get_bone_index(get_instance(plugin, instance), name->text); +} + +static bool ReignEngine_TransInstanceLocalPosToWorldPosByBone(int plugin, int instance, int bone, float offset_x, float offset_y, float offset_z, float *x, float *y, float *z) +{ + vec3 offset = {offset_x, offset_y, -offset_z}, result; + if (!RE_instance_trans_local_pos_to_world_pos_by_bone(get_instance(plugin, instance), bone, offset, result)) + return false; + *x = result[0]; + *y = result[1]; + *z = -result[2]; + return true; +} + //int ReignEngine_GetInstanceNumofPolygon(int plugin, int instance); //int ReignEngine_GetInstanceTextureMemorySize(int plugin, int instance); //void ReignEngine_GetInstanceInfoText(int plugin, int instance, struct string **pIText);