From 10710e9908155da67ed860f36feaf3f604f8377e Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sun, 18 Dec 2022 22:51:42 +0900 Subject: [PATCH] ReignEngine: Cache parsed particle effects Now parsed particle-effect definitions are cached in a hash map in the plugin object. To make it possible, static part of `struct particle_effect` and `struct particle_object` are factored out to `struct pae` and `struct pae_object` respectively. --- include/reign.h | 1 + src/3d/3d_internal.h | 37 +++++---- src/3d/debug.c | 2 +- src/3d/particle.c | 169 ++++++++++++++++++++++++------------------ src/3d/reign.c | 173 +++++++++++++++++++++++-------------------- src/3d/renderer.c | 26 ++++--- 6 files changed, 229 insertions(+), 179 deletions(-) diff --git a/include/reign.h b/include/reign.h index c03e4c7..a98e1f2 100644 --- a/include/reign.h +++ b/include/reign.h @@ -85,6 +85,7 @@ struct RE_plugin { struct RE_instance **instances; struct archive *aar; struct hash_table *model_cache; + struct hash_table *pae_cache; struct RE_renderer *renderer; struct RE_camera camera; mat4 proj_transform; diff --git a/src/3d/3d_internal.h b/src/3d/3d_internal.h index ff078f0..38e4e21 100644 --- a/src/3d/3d_internal.h +++ b/src/3d/3d_internal.h @@ -272,7 +272,14 @@ struct particle_position { struct particle_position_unit units[NR_PARTICLE_POSITION_UNITS]; }; -struct particle_object { +struct pae { + char *path; + struct hash_table *textures; // name -> struct billboard_texture* + int nr_objects; + struct pae_object *objects; +}; + +struct pae_object { char *name; enum particle_type type; enum particle_move_type move_type; @@ -325,9 +332,18 @@ struct particle_object { float offset_x; float offset_y; - // Runtime data struct model *model; - struct particle_instance *instances; +}; + +struct particle_effect { + struct pae *pae; + struct particle_object *objects; // pae->nr_objects elements + bool camera_quake_enabled; +}; + +struct particle_object { + struct pae_object *pae_obj; + struct particle_instance *instances; // pae_obj->nr_particles elements vec3_range pos; vec3 move_vec, move_ortho; }; @@ -340,20 +356,15 @@ struct particle_instance { float pitch_angle; }; -struct particle_effect { - char *path; - struct hash_table *textures; // name -> struct billboard_texture* - int nr_objects; - struct particle_object *objects; - bool camera_quake_enabled; -}; +struct pae *pae_load(struct archive *aar, const char *path); +void pae_free(struct pae *pae); +void pae_calc_frame_range(struct pae *pae, struct motion *motion); +float pae_object_calc_alpha(struct pae_object *po, struct particle_instance *pi, float frame); -struct particle_effect *particle_effect_load(struct archive *aar, const char *path); +struct particle_effect *particle_effect_create(struct pae *pae); void particle_effect_free(struct particle_effect *effect); -void particle_effect_calc_frame_range(struct particle_effect *effect, struct motion *motion); void particle_effect_update(struct RE_instance *inst); void particle_object_calc_local_transform(struct RE_instance *inst, struct particle_object *po, struct particle_instance *pi, float frame, mat4 dest); -float particle_object_calc_alpha(struct particle_object *po, struct particle_instance *pi, float frame); // parser.c diff --git a/src/3d/debug.c b/src/3d/debug.c index 0552eee..2379b4f 100644 --- a/src/3d/debug.c +++ b/src/3d/debug.c @@ -101,7 +101,7 @@ static void print_instance(struct RE_instance *inst, int index, int indent) if (inst->motion_blend) indent_printf(indent, "motion_blend_rate = %f,\n", inst->motion_blend_rate); if (inst->effect) - indent_printf(indent, "path = \"%s\",\n", inst->effect->path); + indent_printf(indent, "path = \"%s\",\n", inst->effect->pae->path); indent--; indent_printf(indent, "},\n"); diff --git a/src/3d/particle.c b/src/3d/particle.c index b9ac076..723cf20 100644 --- a/src/3d/particle.c +++ b/src/3d/particle.c @@ -239,10 +239,10 @@ static struct particle_position *parse_position(char **ptext) return epos; } -static struct particle_effect *parse_pae(char *text) +static struct pae *parse_pae(char *text) { - struct particle_effect *pae = xcalloc(1, sizeof(struct particle_effect)); - struct particle_object *current_object = NULL; + struct pae *pae = xcalloc(1, sizeof(struct pae)); + struct pae_object *current_object = NULL; for (;;) { // Skip whitespaces and comments @@ -269,7 +269,7 @@ static struct particle_effect *parse_pae(char *text) if (!*text) { // EOF return pae; } else if (MATCH("オブジェクト " QUOTED_STRING " = {", string_buf)) { - pae->objects = xrealloc_array(pae->objects, pae->nr_objects, pae->nr_objects + 1, sizeof(struct particle_object)); + pae->objects = xrealloc_array(pae->objects, pae->nr_objects, pae->nr_objects + 1, sizeof(struct pae_object)); current_object = &pae->objects[pae->nr_objects++]; current_object->name = utf2sjis(string_buf, 0); // Default values. @@ -449,15 +449,15 @@ static struct particle_effect *parse_pae(char *text) } } err: - particle_effect_free(pae); + pae_free(pae); return NULL; } -static void load_textures(struct particle_effect *effect, struct archive *aar) +static void load_textures(struct pae *effect, struct archive *aar) { effect->textures = ht_create(16); for (int i = 0; i < effect->nr_objects; i++) { - struct particle_object *po = &effect->objects[i]; + struct pae_object *po = &effect->objects[i]; for (int j = 0; j < po->nr_textures; j++) { const char *name = po->textures[j]; if (ht_get(effect->textures, name, NULL)) @@ -587,7 +587,7 @@ static void eval_pos_for_instance(struct particle_position *pp, vec3 dest) } } -static float eval_child_slope(struct particle_object *po) +static float eval_child_slope(struct pae_object *po) { float slope = glm_lerp(po->child_begin_slope, po->child_end_slope, randf()); if (slope > 1.0) @@ -607,29 +607,30 @@ static void interpolate_pos(vec3 begin, vec3 end, float move_curve, float t, vec static void init_particle_instances(struct particle_object *po) { - po->instances = xcalloc(po->nr_particles, sizeof(struct particle_instance)); + struct pae_object *pae_obj = po->pae_obj; + po->instances = xcalloc(pae_obj->nr_particles, sizeof(struct particle_instance)); - for (int i = 0; i < po->nr_particles; i++) { + for (int i = 0; i < pae_obj->nr_particles; i++) { struct particle_instance *pi = &po->instances[i]; - switch (po->move_type) { + switch (pae_obj->move_type) { case PARTICLE_MOVE_FIXED: case PARTICLE_MOVE_LINEAR: - pi->begin_frame = po->begin_frame; - pi->end_frame = po->end_frame; + pi->begin_frame = pae_obj->begin_frame; + pi->end_frame = pae_obj->end_frame; break; case PARTICLE_MOVE_EMITTER: - pi->begin_frame = glm_lerp(po->child_create_begin_frame, po->child_create_end_frame, (float)i / po->nr_particles); - pi->end_frame = pi->begin_frame + po->child_frame; - pi->roll_angle = eval_child_slope(po); + pi->begin_frame = glm_lerp(pae_obj->child_create_begin_frame, pae_obj->child_create_end_frame, (float)i / pae_obj->nr_particles); + pi->end_frame = pi->begin_frame + pae_obj->child_frame; + pi->roll_angle = eval_child_slope(pae_obj); pi->pitch_angle = randf() * (2.0f * GLM_PIf); break; } - eval_pos_for_instance(po->position[0], pi->random_offset.begin); - eval_pos_for_instance(po->position[1], pi->random_offset.end); + eval_pos_for_instance(pae_obj->position[0], pi->random_offset.begin); + eval_pos_for_instance(pae_obj->position[1], pi->random_offset.end); } } -struct particle_effect *particle_effect_load(struct archive *aar, const char *path) +struct pae *pae_load(struct archive *aar, const char *path) { const char *basename = strrchr(path, '\\'); basename = basename ? basename + 1 : path; @@ -653,20 +654,19 @@ struct particle_effect *particle_effect_load(struct archive *aar, const char *pa // clarity. char *text = sjis2utf(sjis_text, dfile->size); free(sjis_text); - struct particle_effect *effect = parse_pae(text); + struct pae *pae = parse_pae(text); free(text); - if (!effect) { + if (!pae) { WARNING("could not parse %s", dfile->name); archive_free_data(dfile); return NULL; } archive_free_data(dfile); - effect->path = strdup(path); - effect->camera_quake_enabled = true; - load_textures(effect, aar); - for (int i = 0; i < effect->nr_objects; i++) { - struct particle_object *po = &effect->objects[i]; + pae->path = strdup(path); + load_textures(pae, aar); + for (int i = 0; i < pae->nr_objects; i++) { + struct pae_object *po = &pae->objects[i]; if (po->polygon_name && *po->polygon_name) { char *pol_path = xmalloc(strlen(path) + strlen(po->polygon_name) + 2); @@ -674,10 +674,22 @@ struct particle_effect *particle_effect_load(struct archive *aar, const char *pa po->model = model_load(aar, pol_path); free(pol_path); } - - init_particle_instances(po); } + return pae; +} + +struct particle_effect *particle_effect_create(struct pae *pae) +{ + struct particle_effect *effect = xcalloc(1, sizeof(struct particle_effect)); + effect->pae = pae; + effect->objects = xcalloc(pae->nr_objects, sizeof(struct particle_object)); + effect->camera_quake_enabled = true; + for (int i = 0; i < pae->nr_objects; i++) { + struct particle_object *po = &effect->objects[i]; + po->pae_obj = &pae->objects[i]; + init_particle_instances(po); + } return effect; } @@ -699,10 +711,10 @@ static void particle_position_free(struct particle_position *pos) free(pos); } -void particle_effect_free(struct particle_effect *effect) +void pae_free(struct pae *pae) { - for (int i = 0; i < effect->nr_objects; i++) { - struct particle_object *po = &effect->objects[i]; + for (int i = 0; i < pae->nr_objects; i++) { + struct pae_object *po = &pae->objects[i]; free(po->name); for (int j = 0; j < NR_PARTICLE_POSITIONS; j++) particle_position_free(po->position[j]); @@ -719,21 +731,30 @@ void particle_effect_free(struct particle_effect *effect) free(po->damages); if (po->model) model_free(po->model); - free(po->instances); } - ht_foreach_value(effect->textures, free_billboard_texture); - ht_free(effect->textures); + ht_foreach_value(pae->textures, free_billboard_texture); + ht_free(pae->textures); + free(pae->objects); + free(pae->path); + free(pae); +} + +void particle_effect_free(struct particle_effect *effect) +{ + for (int i = 0; i < effect->pae->nr_objects; i++) { + struct particle_object *obj = &effect->objects[i]; + free(obj->instances); + } free(effect->objects); - free(effect->path); free(effect); } -void particle_effect_calc_frame_range(struct particle_effect *effect, struct motion *motion) +void pae_calc_frame_range(struct pae *pae, struct motion *motion) { int begin_frame = INT_MAX; int end_frame = INT_MIN; - for (int i = 0; i < effect->nr_objects; i++) { - struct particle_object *po = &effect->objects[i]; + for (int i = 0; i < pae->nr_objects; i++) { + struct pae_object *po = &pae->objects[i]; int obj_begin = po->begin_frame; int obj_end = max(po->end_frame, po->child_create_end_frame + po->child_frame); if (begin_frame > obj_begin) @@ -745,7 +766,7 @@ void particle_effect_calc_frame_range(struct particle_effect *effect, struct mot motion->frame_end = motion->loop_frame_end = end_frame; } -static void update_camera_quake(struct RE_instance *inst, struct particle_object *po) +static void update_camera_quake(struct RE_instance *inst, struct pae_object *po) { float frame = inst->motion->current_frame - po->begin_frame; float total_frames = po->end_frame - po->begin_frame; @@ -769,19 +790,20 @@ void particle_effect_update(struct RE_instance *inst) struct particle_effect *effect = inst->effect; if (!effect) return; - for (int i = 0; i < effect->nr_objects; i++) { + for (int i = 0; i < effect->pae->nr_objects; i++) { struct particle_object *po = &effect->objects[i]; - if (po->type == PARTICLE_TYPE_CAMERA_QUAKE) { + struct pae_object *pae_obj = po->pae_obj; + if (pae_obj->type == PARTICLE_TYPE_CAMERA_QUAKE) { if (effect->camera_quake_enabled) - update_camera_quake(inst, po); + update_camera_quake(inst, pae_obj); continue; } // These cannot be precomputed, because they may depend on the target's // *current* bone matrix. - eval_pos_for_object(inst, po->position[0], po->pos.begin); - eval_pos_for_object(inst, po->position[1], po->pos.end); + eval_pos_for_object(inst, pae_obj->position[0], po->pos.begin); + eval_pos_for_object(inst, pae_obj->position[1], po->pos.end); glm_vec3_sub(po->pos.end, po->pos.begin, po->move_vec); - switch (po->dir_type) { + switch (pae_obj->dir_type) { case PARTICLE_DIR_TYPE_NORMAL: glm_vec3_normalize(po->move_vec); glm_vec3_ortho(po->move_vec, po->move_ortho); @@ -798,45 +820,47 @@ void particle_effect_update(struct RE_instance *inst) static void calc_emitter_pos(struct particle_object *po, struct particle_instance *pi, float t, vec3 dest, vec3 move_vec) { + struct pae_object *pae_obj = po->pae_obj; vec3 begin, end; glm_vec3_add(po->pos.begin, pi->random_offset.begin, begin); glm_vec3_add(po->pos.end, pi->random_offset.end, end); - interpolate_pos(begin, end, po->move_curve, t, dest); + interpolate_pos(begin, end, pae_obj->move_curve, t, dest); if (move_vec) glm_vec3_sub(end, begin, move_vec); // Orbital rotation. vec3 angle, dist; - glm_vec3_lerp(po->revolution_angle.begin, po->revolution_angle.end, t, angle); - glm_vec3_lerp(po->revolution_distance.begin, po->revolution_distance.end, t, dist); + glm_vec3_lerp(pae_obj->revolution_angle.begin, pae_obj->revolution_angle.end, t, angle); + glm_vec3_lerp(pae_obj->revolution_distance.begin, pae_obj->revolution_distance.end, t, dist); glm_vec3_scale(angle, GLM_PIf / 180.0f, angle); // deg -> rad - if (po->revolution_angle.begin[0] != 0.0f || po->revolution_angle.end[0] != 0.0f) { + if (pae_obj->revolution_angle.begin[0] != 0.0f || pae_obj->revolution_angle.end[0] != 0.0f) { dest[1] += dist[0] * sinf(angle[0]); dest[2] -= dist[0] * cosf(angle[0]); } - if (po->revolution_angle.begin[1] != 0.0f || po->revolution_angle.end[1] != 0.0f) { + if (pae_obj->revolution_angle.begin[1] != 0.0f || pae_obj->revolution_angle.end[1] != 0.0f) { dest[0] += dist[1] * sinf(angle[1]); dest[2] -= dist[1] * cosf(angle[1]); } - if (po->revolution_angle.begin[2] != 0.0f || po->revolution_angle.end[2] != 0.0f) { + if (pae_obj->revolution_angle.begin[2] != 0.0f || pae_obj->revolution_angle.end[2] != 0.0f) { dest[1] += dist[2] * sinf(angle[2]); dest[0] += dist[2] * cosf(angle[2]); } // Apply the curve. - glm_vec3_muladds(po->curve_length, 4.9f * t * (1.0f - t), dest); + glm_vec3_muladds(pae_obj->curve_length, 4.9f * t * (1.0f - t), dest); } static void calc_pos_and_up_vector(struct particle_object *po, struct particle_instance *pi, float t, vec3 pos, vec3 up_vector) { - switch (po->move_type) { + struct pae_object *pae_obj = po->pae_obj; + switch (pae_obj->move_type) { case PARTICLE_MOVE_FIXED: glm_vec3_add(po->pos.begin, pi->random_offset.begin, pos); glm_vec3_copy(GLM_YUP, up_vector); break; case PARTICLE_MOVE_LINEAR: calc_emitter_pos(po, pi, t, pos, up_vector); - switch (po->up_vector_type) { + switch (pae_obj->up_vector_type) { case PARTICLE_UP_VECTOR_Y_AXIS: case PARTICLE_UP_VECTOR_INSTANCE_MOVE: glm_vec3_copy(GLM_YUP, up_vector); @@ -852,12 +876,12 @@ static void calc_pos_and_up_vector(struct particle_object *po, struct particle_i case PARTICLE_MOVE_EMITTER: { // Calculate the instance's initial and final position. - float t0 = glm_clamp_zo(glm_percent(po->begin_frame, po->end_frame, pi->begin_frame)); + float t0 = glm_clamp_zo(glm_percent(pae_obj->begin_frame, pae_obj->end_frame, pi->begin_frame)); vec3_range inst_pos; calc_emitter_pos(po, pi, t0, inst_pos.begin, NULL); vec3 inst_move; glm_vec3_copy(po->move_vec, inst_move); - switch (po->dir_type) { + switch (pae_obj->dir_type) { case PARTICLE_DIR_TYPE_NORMAL: glm_vec3_rotate(inst_move, pi->roll_angle, po->move_ortho); glm_vec3_rotate(inst_move, pi->pitch_angle, po->move_vec); @@ -867,12 +891,12 @@ static void calc_pos_and_up_vector(struct particle_object *po, struct particle_i break; } glm_vec3_copy(inst_pos.begin, inst_pos.end); - switch (po->child_move_dir_type) { + switch (pae_obj->child_move_dir_type) { case PARTICLE_CHILD_MOVE_DIR_NORMAL: - glm_vec3_muladds(inst_move, po->child_length, inst_pos.end); + glm_vec3_muladds(inst_move, pae_obj->child_length, inst_pos.end); break; case PARTICLE_CHILD_MOVE_DIR_REVERSE: - glm_vec3_muladds(inst_move, po->child_length, inst_pos.begin); + glm_vec3_muladds(inst_move, pae_obj->child_length, inst_pos.begin); glm_vec3_negate(inst_move); break; } @@ -880,7 +904,7 @@ static void calc_pos_and_up_vector(struct particle_object *po, struct particle_i glm_vec3_lerp(inst_pos.begin, inst_pos.end, t, pos); // Calculate the up vector. - switch (po->up_vector_type) { + switch (pae_obj->up_vector_type) { case PARTICLE_UP_VECTOR_Y_AXIS: glm_vec3_copy(GLM_YUP, up_vector); break; @@ -888,13 +912,13 @@ static void calc_pos_and_up_vector(struct particle_object *po, struct particle_i glm_vec3_copy(po->move_vec, up_vector); break; case PARTICLE_UP_VECTOR_INSTANCE_MOVE: - if (po->child_length != 0.0f) + if (pae_obj->child_length != 0.0f) glm_vec3_copy(inst_move, up_vector); else glm_vec3_copy(GLM_XUP, up_vector); break; } - if (po->dir_type == PARTICLE_DIR_TYPE_XY_PLANE) { + if (pae_obj->dir_type == PARTICLE_DIR_TYPE_XY_PLANE) { mat3 rot = {{ inst_move[1], -inst_move[0], 0.0f }, { inst_move[0], inst_move[1], 0.0f }, { 0.0f, 0.0f, 1.0f }}; @@ -905,7 +929,7 @@ static void calc_pos_and_up_vector(struct particle_object *po, struct particle_i } } -static void calc_scale(struct particle_object *po, int frame, vec3 dest) +static void calc_scale(struct pae_object *po, int frame, vec3 dest) { glm_vec3_broadcast(po->sizes2[min(frame, po->nr_sizes2 - 1)], dest); if (po->nr_sizes_x) @@ -916,6 +940,7 @@ static void calc_scale(struct particle_object *po, int frame, vec3 dest) void particle_object_calc_local_transform(struct RE_instance *inst, struct particle_object *po, struct particle_instance *pi, float frame, mat4 dest) { + struct pae_object *pae_obj = po->pae_obj; float t = glm_percent(pi->begin_frame, pi->end_frame, frame); vec3 pos, up_vector; @@ -927,7 +952,7 @@ void particle_object_calc_local_transform(struct RE_instance *inst, struct parti float step_frac = rel_frame - cur_step; glm_translate_make(dest, pos); - if (po->type == PARTICLE_TYPE_BILLBOARD) { + if (pae_obj->type == PARTICLE_TYPE_BILLBOARD) { mat4 view_mat; RE_calc_view_matrix(&inst->plugin->camera, up_vector, view_mat); mat3 rot; @@ -936,7 +961,7 @@ void particle_object_calc_local_transform(struct RE_instance *inst, struct parti } vec3 angles; - glm_vec3_lerp(po->rotation.begin, po->rotation.end, t, angles); + glm_vec3_lerp(pae_obj->rotation.begin, pae_obj->rotation.end, t, angles); angles[0] *= -GLM_PIf / 180.0f; angles[1] *= -GLM_PIf / 180.0f; angles[2] *= GLM_PIf / 180.0f; @@ -944,21 +969,21 @@ void particle_object_calc_local_transform(struct RE_instance *inst, struct parti glm_euler_zxy(angles, rotation_mat); glm_mat4_mul(dest, rotation_mat, dest); - if (po->nr_sizes2 > 0) { + if (pae_obj->nr_sizes2 > 0) { vec3 scale, scale2; - calc_scale(po, cur_step, scale); - calc_scale(po, next_step, scale2); + calc_scale(pae_obj, cur_step, scale); + calc_scale(pae_obj, next_step, scale2); glm_vec3_lerp(scale, scale2, step_frac, scale); glm_scale(dest, scale); } else { - glm_scale_uni(dest, glm_lerp(po->size[0], po->size[1], t)); + glm_scale_uni(dest, glm_lerp(pae_obj->size[0], pae_obj->size[1], t)); } - glm_translate_x(dest, -po->offset_x); - glm_translate_y(dest, -po->offset_y); + glm_translate_x(dest, -pae_obj->offset_x); + glm_translate_y(dest, -pae_obj->offset_y); } -float particle_object_calc_alpha(struct particle_object *po, struct particle_instance *pi, float frame) +float pae_object_calc_alpha(struct pae_object *po, struct particle_instance *pi, float frame) { frame -= pi->begin_frame; if (frame < po->alpha_fadein_frame) diff --git a/src/3d/reign.c b/src/3d/reign.c index b647775..42e7027 100644 --- a/src/3d/reign.c +++ b/src/3d/reign.c @@ -217,6 +217,7 @@ struct RE_plugin *RE_plugin_new(void) plugin->instances = xcalloc(plugin->nr_instances, sizeof(struct RE_instance *)); plugin->aar = aar; plugin->model_cache = ht_create(32); + plugin->pae_cache = ht_create(32); for (int i = 0; i < RE_NR_BACK_CGS; i++) RE_back_cg_init(&plugin->back_cg[i]); plugin->fog_type = RE_FOG_NONE; @@ -236,6 +237,8 @@ void RE_plugin_free(struct RE_plugin *plugin) archive_free(plugin->aar); ht_foreach_value(plugin->model_cache, (void(*)(void*))model_free); ht_free(plugin->model_cache); + ht_foreach_value(plugin->pae_cache, (void(*)(void*))pae_free); + ht_free(plugin->pae_cache); if (plugin->renderer) RE_renderer_free(plugin->renderer); for (int i = 0; i < RE_NR_BACK_CGS; i++) @@ -376,6 +379,7 @@ bool RE_instance_load(struct RE_instance *instance, const char *name) if (name[0] == '\0') return false; + struct pae *pae; switch (instance->type) { case RE_ITYPE_STATIC: case RE_ITYPE_SKINNED: @@ -389,13 +393,20 @@ bool RE_instance_load(struct RE_instance *instance, const char *name) instance->bone_transforms = xcalloc(instance->model->nr_bones, sizeof(mat4)); return !!instance->model; case RE_ITYPE_PARTICLE_EFFECT: - instance->effect = particle_effect_load(instance->plugin->aar, name); + pae = ht_get(instance->plugin->pae_cache, name, NULL); + if (!pae) { + pae = pae_load(instance->plugin->aar, name); + if (!pae) + return false; + ht_put(instance->plugin->pae_cache, name, pae); + } + instance->effect = particle_effect_create(pae); if (!instance->motion) { instance->motion = xcalloc(1, sizeof(struct motion)); instance->motion->instance = instance; - particle_effect_calc_frame_range(instance->effect, instance->motion); + pae_calc_frame_range(instance->effect->pae, instance->motion); } - return !!instance->effect; + return true; default: WARNING("Invalid instance type %d", instance->type); return false; @@ -574,7 +585,7 @@ bool RE_motion_set_loop_frame_range(struct motion *motion, float begin, float en int RE_effect_get_num_object(struct particle_effect *effect) { - return effect ? effect->nr_objects : 0; + return effect ? effect->pae->nr_objects : 0; } bool RE_effect_get_camera_quake_flag(struct particle_effect *effect) @@ -592,47 +603,47 @@ bool RE_effect_set_camera_quake_flag(struct particle_effect *effect, bool enable struct particle_object *RE_get_effect_object(struct particle_effect *effect, unsigned object) { - if (!effect || object >= (unsigned)effect->nr_objects) + if (!effect || object >= (unsigned)effect->pae->nr_objects) return NULL; return &effect->objects[object]; } int RE_particle_get_type(struct particle_object *po) { - return po ? po->type : 0; + return po ? po->pae_obj->type : 0; } int RE_particle_get_move_type(struct particle_object *po) { - return po ? po->move_type : 0; + return po ? po->pae_obj->move_type : 0; } int RE_particle_get_up_vec_type(struct particle_object *po) { - return po ? po->up_vector_type : 0; + return po ? po->pae_obj->up_vector_type : 0; } float RE_particle_get_move_curve(struct particle_object *po) { - return po ? po->move_curve : 0.0; + return po ? po->pae_obj->move_curve : 0.0; } void RE_particle_get_frame(struct particle_object *po, int *begin_frame, int *end_frame) { if (!po) return; - *begin_frame = po->begin_frame; - *end_frame = po->end_frame; + *begin_frame = po->pae_obj->begin_frame; + *end_frame = po->pae_obj->end_frame; } int RE_particle_get_stop_frame(struct particle_object *po) { - return po ? po->stop_frame : 0; + return po ? po->pae_obj->stop_frame : 0; } const char *RE_particle_get_name(struct particle_object *po) { - return po ? po->name : NULL; + return po ? po->pae_obj->name : NULL; } int RE_particle_get_num_pos(struct particle_object *po) @@ -647,9 +658,9 @@ int RE_particle_get_num_pos_unit(struct particle_object *po, int pos) static struct particle_position_unit *get_position_unit(struct particle_object *po, int pos, int unit) { - if (!po || pos >= NR_PARTICLE_POSITIONS || !po->position[pos] || unit >= NR_PARTICLE_POSITION_UNITS) + if (!po || pos >= NR_PARTICLE_POSITIONS || !po->pae_obj->position[pos] || unit >= NR_PARTICLE_POSITION_UNITS) return NULL; - return &po->position[pos]->units[unit]; + return &po->pae_obj->position[pos]->units[unit]; } int RE_particle_get_pos_unit_type(struct particle_object *po, int pos, int unit) @@ -675,298 +686,298 @@ int RE_particle_get_pos_unit_index(struct particle_object *po, int pos, int unit int RE_particle_get_num_texture(struct particle_object *po) { - return po ? po->nr_textures : 0; + return po ? po->pae_obj->nr_textures : 0; } const char *RE_particle_get_texture(struct particle_object *po, int texture) { - if (!po || texture >= po->nr_textures) + if (!po || texture >= po->pae_obj->nr_textures) return NULL; - return po->textures[texture]; + return po->pae_obj->textures[texture]; } bool RE_particle_get_size(struct particle_object *po, float *begin_size, float *end_size) { if (!po) return false; - *begin_size = po->size[0]; - *end_size = po->size[1]; + *begin_size = po->pae_obj->size[0]; + *end_size = po->pae_obj->size[1]; return true; } bool RE_particle_get_size2(struct particle_object *po, int frame, float *size) { - if (!po || frame >= po->nr_sizes2) + if (!po || frame >= po->pae_obj->nr_sizes2) return false; - *size = po->sizes2[frame]; + *size = po->pae_obj->sizes2[frame]; return true; } bool RE_particle_get_size_x(struct particle_object *po, int frame, float *size) { - if (!po || frame >= po->nr_sizes_x) + if (!po || frame >= po->pae_obj->nr_sizes_x) return false; - *size = po->sizes_x[frame]; + *size = po->pae_obj->sizes_x[frame]; return true; } bool RE_particle_get_size_y(struct particle_object *po, int frame, float *size) { - if (!po || frame >= po->nr_sizes_y) + if (!po || frame >= po->pae_obj->nr_sizes_y) return false; - *size = po->sizes_y[frame]; + *size = po->pae_obj->sizes_y[frame]; return true; } bool RE_particle_get_size_type(struct particle_object *po, int frame, int *type) { - if (!po || frame >= po->nr_size_types) + if (!po || frame >= po->pae_obj->nr_size_types) return false; - *type = po->size_types[frame]; + *type = po->pae_obj->size_types[frame]; return true; } bool RE_particle_get_size_x_type(struct particle_object *po, int frame, int *type) { - if (!po || frame >= po->nr_size_x_types) + if (!po || frame >= po->pae_obj->nr_size_x_types) return false; - *type = po->size_x_types[frame]; + *type = po->pae_obj->size_x_types[frame]; return true; } bool RE_particle_get_size_y_type(struct particle_object *po, int frame, int *type) { - if (!po || frame >= po->nr_size_y_types) + if (!po || frame >= po->pae_obj->nr_size_y_types) return false; - *type = po->size_y_types[frame]; + *type = po->pae_obj->size_y_types[frame]; return true; } int RE_particle_get_num_size2(struct particle_object *po) { - return po ? po->nr_sizes2 : 0; + return po ? po->pae_obj->nr_sizes2 : 0; } int RE_particle_get_num_size_x(struct particle_object *po) { - return po ? po->nr_sizes_x : 0; + return po ? po->pae_obj->nr_sizes_x : 0; } int RE_particle_get_num_size_y(struct particle_object *po) { - return po ? po->nr_sizes_y : 0; + return po ? po->pae_obj->nr_sizes_y : 0; } int RE_particle_get_num_size_type(struct particle_object *po) { - return po ? po->nr_size_types : 0; + return po ? po->pae_obj->nr_size_types : 0; } int RE_particle_get_num_size_x_type(struct particle_object *po) { - return po ? po->nr_size_x_types : 0; + return po ? po->pae_obj->nr_size_x_types : 0; } int RE_particle_get_num_size_y_type(struct particle_object *po) { - return po ? po->nr_size_y_types : 0; + return po ? po->pae_obj->nr_size_y_types : 0; } int RE_particle_get_blend_type(struct particle_object *po) { - return po ? po->blend_type : 0; + return po ? po->pae_obj->blend_type : 0; } const char *RE_particle_get_polygon_name(struct particle_object *po) { - return po ? po->polygon_name : NULL; + return po ? po->pae_obj->polygon_name : NULL; } int RE_particle_get_num_particles(struct particle_object *po) { - return po ? po->nr_particles : 0; + return po ? po->pae_obj->nr_particles : 0; } int RE_particle_get_alpha_fadein_time(struct particle_object *po) { - return po ? po->alpha_fadein_time : 0; + return po ? po->pae_obj->alpha_fadein_time : 0; } int RE_particle_get_alpha_fadeout_time(struct particle_object *po) { - return po ? po->alpha_fadeout_time : 0; + return po ? po->pae_obj->alpha_fadeout_time : 0; } int RE_particle_get_texture_anime_time(struct particle_object *po) { - return po ? po->texture_anime_time : 0; + return po ? po->pae_obj->texture_anime_time : 0; } float RE_particle_get_alpha_fadein_frame(struct particle_object *po) { - return po ? po->alpha_fadein_frame : 0.0; + return po ? po->pae_obj->alpha_fadein_frame : 0.0; } float RE_particle_get_alpha_fadeout_frame(struct particle_object *po) { - return po ? po->alpha_fadeout_frame : 0.0; + return po ? po->pae_obj->alpha_fadeout_frame : 0.0; } float RE_particle_get_texture_anime_frame(struct particle_object *po) { - return po ? po->texture_anime_frame : 0.0; + return po ? po->pae_obj->texture_anime_frame : 0.0; } int RE_particle_get_frame_ref_type(struct particle_object *po) { - return po ? po->frame_ref_type : 0; + return po ? po->pae_obj->frame_ref_type : 0; } int RE_particle_get_frame_ref_param(struct particle_object *po) { - return po ? po->frame_ref_param : 0; + return po ? po->pae_obj->frame_ref_param : 0; } void RE_particle_get_x_rotation_angle(struct particle_object *po, float *begin_angle, float *end_angle) { if (!po) return; - *begin_angle = po->rotation.begin[0]; - *end_angle = po->rotation.end[0]; + *begin_angle = po->pae_obj->rotation.begin[0]; + *end_angle = po->pae_obj->rotation.end[0]; } void RE_particle_get_y_rotation_angle(struct particle_object *po, float *begin_angle, float *end_angle) { if (!po) return; - *begin_angle = po->rotation.begin[1]; - *end_angle = po->rotation.end[1]; + *begin_angle = po->pae_obj->rotation.begin[1]; + *end_angle = po->pae_obj->rotation.end[1]; } void RE_particle_get_z_rotation_angle(struct particle_object *po, float *begin_angle, float *end_angle) { if (!po) return; - *begin_angle = po->rotation.begin[2]; - *end_angle = po->rotation.end[2]; + *begin_angle = po->pae_obj->rotation.begin[2]; + *end_angle = po->pae_obj->rotation.end[2]; } void RE_particle_get_x_revolution_angle(struct particle_object *po, float *begin_angle, float *end_angle) { if (!po) return; - *begin_angle = po->revolution_angle.begin[0]; - *end_angle = po->revolution_angle.end[0]; + *begin_angle = po->pae_obj->revolution_angle.begin[0]; + *end_angle = po->pae_obj->revolution_angle.end[0]; } void RE_particle_get_x_revolution_distance(struct particle_object *po, float *begin_distance, float *end_distance) { if (!po) return; - *begin_distance = po->revolution_distance.begin[0]; - *end_distance = po->revolution_distance.end[0]; + *begin_distance = po->pae_obj->revolution_distance.begin[0]; + *end_distance = po->pae_obj->revolution_distance.end[0]; } void RE_particle_get_y_revolution_angle(struct particle_object *po, float *begin_angle, float *end_angle) { if (!po) return; - *begin_angle = po->revolution_angle.begin[1]; - *end_angle = po->revolution_angle.end[1]; + *begin_angle = po->pae_obj->revolution_angle.begin[1]; + *end_angle = po->pae_obj->revolution_angle.end[1]; } void RE_particle_get_y_revolution_distance(struct particle_object *po, float *begin_distance, float *end_distance) { if (!po) return; - *begin_distance = po->revolution_distance.begin[1]; - *end_distance = po->revolution_distance.end[1]; + *begin_distance = po->pae_obj->revolution_distance.begin[1]; + *end_distance = po->pae_obj->revolution_distance.end[1]; } void RE_particle_get_z_revolution_angle(struct particle_object *po, float *begin_angle, float *end_angle) { if (!po) return; - *begin_angle = po->revolution_angle.begin[2]; - *end_angle = po->revolution_angle.end[2]; + *begin_angle = po->pae_obj->revolution_angle.begin[2]; + *end_angle = po->pae_obj->revolution_angle.end[2]; } void RE_particle_get_z_revolution_distance(struct particle_object *po, float *begin_distance, float *end_distance) { if (!po) return; - *begin_distance = po->revolution_distance.begin[2]; - *end_distance = po->revolution_distance.end[2]; + *begin_distance = po->pae_obj->revolution_distance.begin[2]; + *end_distance = po->pae_obj->revolution_distance.end[2]; } bool RE_particle_get_curve_length(struct particle_object *po, vec3 out) { if (!po) return false; - glm_vec3_copy(po->curve_length, out); + glm_vec3_copy(po->pae_obj->curve_length, out); return true; } int RE_particle_get_child_frame(struct particle_object *po) { - return po ? po->child_frame : 0; + return po ? po->pae_obj->child_frame : 0; } float RE_particle_get_child_length(struct particle_object *po) { - return po ? po->child_length : 0.0; + return po ? po->pae_obj->child_length : 0.0; } float RE_particle_get_child_begin_slope(struct particle_object *po) { - return po ? po->child_begin_slope : 0.0; + return po ? po->pae_obj->child_begin_slope : 0.0; } float RE_particle_get_child_end_slope(struct particle_object *po) { - return po ? po->child_end_slope : 0.0; + return po ? po->pae_obj->child_end_slope : 0.0; } float RE_particle_get_child_create_begin_frame(struct particle_object *po) { - return po ? po->child_create_begin_frame : 0.0; + return po ? po->pae_obj->child_create_begin_frame : 0.0; } float RE_particle_get_child_create_end_frame(struct particle_object *po) { - return po ? po->child_create_end_frame : 0.0; + return po ? po->pae_obj->child_create_end_frame : 0.0; } int RE_particle_get_child_move_dir_type(struct particle_object *po) { - return po ? po->child_move_dir_type : 0; + return po ? po->pae_obj->child_move_dir_type : 0; } int RE_particle_get_dir_type(struct particle_object *po) { - return po ? po->dir_type : 0; + return po ? po->pae_obj->dir_type : 0; } int RE_particle_get_num_damage(struct particle_object *po) { - return po ? po->nr_damages : 0; + return po ? po->pae_obj->nr_damages : 0; } int RE_particle_get_damage(struct particle_object *po, int frame) { - if (!po || frame >= po->nr_damages) + if (!po || frame >= po->pae_obj->nr_damages) return 0; - return po->damages[frame]; + return po->pae_obj->damages[frame]; } float RE_particle_get_offset_x(struct particle_object *po) { - return po ? po->offset_x : 0.0; + return po ? po->pae_obj->offset_x : 0.0; } float RE_particle_get_offset_y(struct particle_object *po) { - return po ? po->offset_y : 0.0; + return po ? po->pae_obj->offset_y : 0.0; } bool RE_effect_get_frame_range(struct RE_instance *instance, int *begin_frame, int *end_frame) diff --git a/src/3d/renderer.c b/src/3d/renderer.c index ef8974e..f17f2cd 100644 --- a/src/3d/renderer.c +++ b/src/3d/renderer.c @@ -490,7 +490,8 @@ static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, ma static void render_billboard_particles(struct RE_renderer *r, struct RE_instance *inst, struct particle_object *po, float frame) { - if (po->nr_textures == 0) + struct pae_object *pae_obj = po->pae_obj; + if (pae_obj->nr_textures == 0) return; glUniform1i(r->diffuse_type, DIFFUSE_EMISSIVE); @@ -500,19 +501,19 @@ static void render_billboard_particles(struct RE_renderer *r, struct RE_instance glUniform1i(r->texture, 0); glBindVertexArray(r->billboard_vao); - for (int index = 0; index < po->nr_particles; index++) { + for (int index = 0; index < pae_obj->nr_particles; index++) { struct particle_instance *pi = &po->instances[index]; if (frame < pi->begin_frame || pi->end_frame < frame) continue; - int step = (int)((frame - pi->begin_frame) / po->texture_anime_frame); - struct billboard_texture *bt = ht_get(inst->effect->textures, po->textures[step % po->nr_textures], NULL); + int step = (int)((frame - pi->begin_frame) / pae_obj->texture_anime_frame); + struct billboard_texture *bt = ht_get(inst->effect->pae->textures, pae_obj->textures[step % pae_obj->nr_textures], NULL); if (!bt) continue; glBindTexture(GL_TEXTURE_2D, bt->texture); - float alpha = particle_object_calc_alpha(po, pi, frame); - if (po->blend_type == PARTICLE_BLEND_ADDITIVE && !bt->has_alpha) + float alpha = pae_object_calc_alpha(pae_obj, pi, frame); + if (pae_obj->blend_type == PARTICLE_BLEND_ADDITIVE && !bt->has_alpha) alpha *= alpha; // why... glUniform1f(r->alpha_mod, alpha); @@ -530,19 +531,20 @@ static void render_billboard_particles(struct RE_renderer *r, struct RE_instance static void render_polygon_particles(struct RE_renderer *r, struct RE_instance *inst, struct particle_object *po, float frame) { - struct model *model = po->model; + struct pae_object *pae_obj = po->pae_obj; + struct model *model = pae_obj->model; if (!model) return; glUniform1i(r->diffuse_type, DIFFUSE_NORMAL); glUniform1i(r->fog_type, inst->plugin->fog_mode ? inst->plugin->fog_type : 0); - for (int index = 0; index < po->nr_particles; index++) { + for (int index = 0; index < pae_obj->nr_particles; index++) { struct particle_instance *pi = &po->instances[index]; if (frame < pi->begin_frame || pi->end_frame < frame) continue; - float alpha = particle_object_calc_alpha(po, pi, frame); + float alpha = pae_object_calc_alpha(pae_obj, pi, frame); glUniform1f(r->alpha_mod, alpha); mat4 local_transform; @@ -588,10 +590,10 @@ static void render_particle_effect(struct RE_instance *inst, struct RE_renderer glDepthMask(GL_FALSE); - for (int i = 0; i < inst->effect->nr_objects; i++) { + for (int i = 0; i < inst->effect->pae->nr_objects; i++) { struct particle_object *po = &inst->effect->objects[i]; - switch (po->blend_type) { + switch (po->pae_obj->blend_type) { case PARTICLE_BLEND_NORMAL: glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); break; @@ -600,7 +602,7 @@ static void render_particle_effect(struct RE_instance *inst, struct RE_renderer break; } - switch (po->type) { + switch (po->pae_obj->type) { case PARTICLE_TYPE_BILLBOARD: render_billboard_particles(r, inst, po, inst->motion->current_frame); break;