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.
This commit is contained in:
kichikuou
2022-12-28 13:18:41 +09:00
parent defeb0ba17
commit 10710e9908
6 changed files with 229 additions and 179 deletions
+1
View File
@@ -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;
+24 -13
View File
@@ -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
+1 -1
View File
@@ -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");
+97 -72
View File
@@ -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)
+92 -81
View File
@@ -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)
+14 -12
View File
@@ -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;