ReignEngine: Implement camera quake effect

This commit is contained in:
kichikuou
2022-10-01 16:24:13 +09:00
parent 8d0cf7cdcb
commit 773cce03eb
6 changed files with 64 additions and 12 deletions
+3
View File
@@ -55,6 +55,7 @@ extern struct RE_options RE_options;
struct RE_camera {
vec3 pos;
float pitch, roll, yaw; // in degrees
float quake_pitch, quake_yaw;
};
struct RE_back_cg {
@@ -183,6 +184,8 @@ bool RE_motion_set_frame_range(struct motion *motion, float begin, float end);
bool RE_motion_set_loop_frame_range(struct motion *motion, float begin, float end);
int RE_effect_get_num_object(struct particle_effect *effect);
bool RE_effect_get_camera_quake_flag(struct particle_effect *effect);
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);
int RE_particle_get_type(struct particle_object *po);
int RE_particle_get_move_type(struct particle_object *po);
+2 -2
View File
@@ -190,7 +190,7 @@ enum particle_type {
PARTICLE_TYPE_BILLBOARD = 0,
PARTICLE_TYPE_POLYGON_OBJECT = 1,
PARTICLE_TYPE_SWORD_BLUR = 2,
PARTICLE_TYPE_CAMERA_VIBRATION = 3,
PARTICLE_TYPE_CAMERA_QUAKE = 3,
};
enum particle_move_type {
@@ -331,9 +331,9 @@ struct particle_instance {
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 particle_effect *particle_effect_load(struct archive *aar, const char *path);
+26 -1
View File
@@ -46,7 +46,7 @@ static enum particle_type parse_particle_type(const char *s)
else if (!strcmp(s, "剣ブラー"))
return PARTICLE_TYPE_SWORD_BLUR;
else if (!strcmp(s, "カメラ振動"))
return PARTICLE_TYPE_CAMERA_VIBRATION;
return PARTICLE_TYPE_CAMERA_QUAKE;
WARNING("unknown object type \"%s\"", s);
return (enum particle_type)-1;
}
@@ -663,6 +663,7 @@ struct particle_effect *particle_effect_load(struct archive *aar, const char *pa
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];
@@ -744,6 +745,25 @@ void particle_effect_calc_frame_range(struct particle_effect *effect, struct mot
motion->frame_end = end_frame;
}
static void update_camera_quake(struct RE_instance *inst, struct particle_object *po)
{
float frame = inst->motion->current_frame - po->begin_frame;
float total_frames = po->end_frame - po->begin_frame;
if (frame < 0 || frame >= total_frames)
return;
const float ease_in_duration = 4.0f;
const float ease_out_duration = 4.0f;
float amplitude = 1.0f;
if (total_frames - frame < ease_out_duration)
amplitude *= (total_frames - frame) / ease_out_duration;
else if (frame < ease_in_duration)
amplitude *= frame / ease_in_duration;
inst->plugin->camera.quake_pitch = sinf(frame * 1.1) * amplitude * -8.0f;
inst->plugin->camera.quake_yaw = sinf(frame * 1.7) * amplitude * 12.0f;
}
void particle_effect_update(struct RE_instance *inst)
{
struct particle_effect *effect = inst->effect;
@@ -751,6 +771,11 @@ void particle_effect_update(struct RE_instance *inst)
return;
for (int i = 0; i < effect->nr_objects; i++) {
struct particle_object *po = &effect->objects[i];
if (po->type == PARTICLE_TYPE_CAMERA_QUAKE) {
if (effect->camera_quake_enabled)
update_camera_quake(inst, po);
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);
+15
View File
@@ -236,6 +236,8 @@ bool RE_build_model(struct RE_plugin *plugin, int elapsed_ms)
if (!plugin)
return false;
plugin->camera.quake_pitch = plugin->camera.quake_yaw = 0.0;
for (int i = 0; i < plugin->nr_instances; i++) {
struct RE_instance *inst = plugin->instances[i];
if (!inst)
@@ -521,6 +523,19 @@ int RE_effect_get_num_object(struct particle_effect *effect)
return effect ? effect->nr_objects : 0;
}
bool RE_effect_get_camera_quake_flag(struct particle_effect *effect)
{
return effect && effect->camera_quake_enabled;
}
bool RE_effect_set_camera_quake_flag(struct particle_effect *effect, bool enable)
{
if (!effect)
return false;
effect->camera_quake_enabled = enable;
return true;
}
struct particle_object *RE_get_effect_object(struct particle_effect *effect, unsigned object)
{
if (!effect || object >= (unsigned)effect->nr_objects)
+4 -3
View File
@@ -259,8 +259,8 @@ void RE_calc_view_matrix(struct RE_camera *camera, vec3 up, mat4 out)
{
vec3 front = { 0.0, 0.0, -1.0 };
vec3 euler = {
glm_rad(camera->pitch),
glm_rad(camera->yaw),
glm_rad(camera->pitch + camera->quake_pitch),
glm_rad(camera->yaw + camera->quake_yaw),
glm_rad(camera->roll)
};
mat4 rot;
@@ -538,7 +538,8 @@ static void render_particle_effect(struct RE_instance *inst, struct RE_renderer
case PARTICLE_TYPE_POLYGON_OBJECT:
render_polygon_particles(r, inst, po, inst->motion->current_frame);
break;
case PARTICLE_TYPE_SWORD_BLUR: // unused
case PARTICLE_TYPE_SWORD_BLUR: // unused
case PARTICLE_TYPE_CAMERA_QUAKE: // handled in particle_effect_update()
break;
}
}
+14 -6
View File
@@ -1022,10 +1022,18 @@ static float ReignEngine_GetEffectObjectOffsetY(int plugin, int instance, int ob
//bool ReignEngine_SetEffectObjectOffsetX(int plugin, int instance, int nObject, float fOffsetX);
//bool ReignEngine_SetEffectObjectOffsetY(int plugin, int instance, int nObject, float fOffsetY);
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, GetCameraQuakeEffectFlag, int plugin, int instance);
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetCameraQuakeEffectFlag, int plugin, int instance, bool flag);
bool ReignEngine_SetCameraPos(int plugin, float x, float y, float z)
static bool ReignEngine_GetCameraQuakeEffectFlag(int plugin, int instance)
{
return RE_effect_get_camera_quake_flag(get_effect(plugin, instance));
}
static bool ReignEngine_SetCameraQuakeEffectFlag(int plugin, int instance, bool flag)
{
return RE_effect_set_camera_quake_flag(get_effect(plugin, instance), flag);
}
static bool ReignEngine_SetCameraPos(int plugin, float x, float y, float z)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
@@ -1036,7 +1044,7 @@ bool ReignEngine_SetCameraPos(int plugin, float x, float y, float z)
return true;
}
bool ReignEngine_SetCameraAngle(int plugin, float angle)
static bool ReignEngine_SetCameraAngle(int plugin, float angle)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
@@ -1045,7 +1053,7 @@ bool ReignEngine_SetCameraAngle(int plugin, float angle)
return true;
}
bool ReignEngine_SetCameraAngleP(int plugin, float angle_p)
static bool ReignEngine_SetCameraAngleP(int plugin, float angle_p)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
@@ -1054,7 +1062,7 @@ bool ReignEngine_SetCameraAngleP(int plugin, float angle_p)
return true;
}
bool ReignEngine_SetCameraAngleB(int plugin, float angle_b)
static bool ReignEngine_SetCameraAngleB(int plugin, float angle_b)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)