Skip to content

Commit

Permalink
Table based warp parameters and new custom warp animations. (#6500)
Browse files Browse the repository at this point in the history
* Made lens flare size proportional to model size.

* Updated fireball_wormhole_intensity function to be smooth and unbreakable

* Added variable frame frate warp and new lens flare animation.

* Last animation changes made since I stopped coding.

* Made cinematic animation, warp-size ratio, and flare-size-ratio parameters configurable by table. New exp_to_line function to be more consistent and to fix a bug.

* Made everything configurable by table.

* Updated default values for cinematic warp animation.

* Fixed the usage of MAX() so that it assigns to the variable.

* Fixed obvious freakin' double to float casting warnings.

* Made requested changes. Flare animation can now be specified with an enum and default else statements will not override earlier entries.

* Changed warp table parameters to Warp flare style and Warp model style.

* Added defaults to switch statements, and made this backwards compatible with older mediavps.

* Removed commented code.

* Opened up flare flickering for table editing.

* Restored cinematic warp flare ratio default.
  • Loading branch information
Gamma39er authored Jan 23, 2025
1 parent 2047bfa commit ab00484
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 20 deletions.
205 changes: 194 additions & 11 deletions code/fireball/fireballs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ static auto WarpOption __UNUSED = options::OptionBuilder<bool>("Graphics.3dWarp"
.importance(65)
.finish();

static float exp_to_line(float t, float start_value, float end_slope, float scale)
{
return -scale * expf(-start_value / scale * t) + end_slope * t + scale;
}

/**
* Play warp in sound for warp effect
*/
Expand Down Expand Up @@ -373,6 +378,110 @@ static void parse_fireball_tbl(const char *table_filename)
// rather than just having the default model that might or might not be used
fi->use_3d_warp = true;
}

if (optional_string("$Warp size ratio:")) {
stuff_float(&fi->warp_size_ratio);
} else if (first_time) {
if (fi->use_3d_warp) {
fi->warp_size_ratio = 1 / 25.0f;
} else {
fi->warp_size_ratio = 1.0f;
}
}

if (optional_string("$Flare size ratio:")) {
stuff_float(&fi->flare_size_ratio);
} else if (first_time) {
fi->flare_size_ratio = 1.0f;
}

if (optional_string("$Flicker magnitude:")) {
stuff_float(&fi->flicker_magnitude);
} else if (first_time) {
fi->flicker_magnitude = 0.10f;
}

if (optional_string("$Warp flare style:")) {
switch (optional_string_one_of(3, "classic", "enhanced", "cinematic")) {
case 0:
fi->warp_flare_style = warp_style::CLASSIC;
break;
case 1:
fi->warp_flare_style = warp_style::ENHANCED;
break;
case 2:
fi->warp_flare_style = warp_style::CINEMATIC;
break;
default:
error_display(0, "Invalid warp flare style. Must be classic, enhanced, or cinematic.");
}

// Set warp flare option
if (optional_string("+Flare size ratio:")) {
stuff_float(&fi->flare_size_ratio);
} else if (fi->warp_flare_style == warp_style::CLASSIC) {
fi->flare_size_ratio = 1.0f;
} else if (fi->warp_flare_style == warp_style::CINEMATIC) {
fi->flare_size_ratio = 5.3f;
}

} else if (first_time) {
fi->warp_flare_style = warp_style::CLASSIC;
}

if (optional_string("$Warp model style:")) {
switch (optional_string_one_of(2, "classic", "cinematic")) {
case 0:
fi->warp_model_style = warp_style::CLASSIC;
break;
case 1:
fi->warp_model_style = warp_style::CINEMATIC;
break;
default:
error_display(0, "Invalid warp model style. Must be classic or cinematic.");
}
} else if (first_time) {
fi->warp_model_style = warp_style::CLASSIC;
}

// Set warp_model_style options if cinematic style is chosen
if (fi->warp_model_style == warp_style::CINEMATIC) {
if (optional_string("+Warp size ratio:")) {
stuff_float(&fi->warp_size_ratio);
} else {
fi->warp_size_ratio = 1.6f;
}

// The first two values need to be implied multiples of PI
// for convenience. These shouldn't need to be faster than a full
// rotation per second, which is already ridiculous.
if (optional_string("+Rotation anim:")) {
stuff_float_list(fi->rot_anim, 3);

CLAMP(fi->rot_anim[0], 0.0f, 2.0f);
CLAMP(fi->rot_anim[1], 0.0f, 2.0f);
fi->rot_anim[2] = MAX(0.0f, fi->rot_anim[2]);
} else {
// PI / 2.75f, PI / 10.0f, 2.0f
fi->rot_anim[0] = 0.365f;
fi->rot_anim[1] = 0.083f;
fi->rot_anim[2] = 2.0f;
}

// Variable frame rate for faster propagation of ripples
if (optional_string("+Frame anim:")) {
stuff_float_list(fi->frame_anim, 3);

// A frame rate that is 4 times the normal speed is ridiculous
CLAMP(fi->frame_anim[0], 0, 4);
CLAMP(fi->frame_anim[1], 1, 4);
fi->frame_anim[2] = MAX(0.0f, fi->frame_anim[2]);
} else {
fi->frame_anim[0] = 1.0f;
fi->frame_anim[1] = 1.0f;
fi->frame_anim[2] = 3.0f;
}
}
}

required_string("#End");
Expand Down Expand Up @@ -539,7 +648,13 @@ void fireball_set_framenum(int num)
}

if ( fb->fireball_render_type == FIREBALL_WARP_EFFECT ) {
framenum = bm_get_anim_frame(fl->bitmap_id, fb->time_elapsed, 0.0f, true);
float new_time = fb->time_elapsed;
if (fd->warp_model_style == warp_style::CINEMATIC) {
float duration_ratio = 2.0f / fb->warp_open_duration;
new_time = exp_to_line(fb->time_elapsed, fd->frame_anim[0] * duration_ratio, fd->frame_anim[1], fd->frame_anim[2] * duration_ratio);
}

framenum = bm_get_anim_frame(fl->bitmap_id, new_time, 0.0f, true);

if ( fb->orient ) {
// warp out effect plays backwards
Expand Down Expand Up @@ -1030,22 +1145,48 @@ int fireball_asteroid_explosion_type(asteroid_info *aip)
return index;
}

static float cutscene_wormhole(float t) {
float a = 25.0f * powf(t, 4.0f);
return a / (a + 1.0f);
}

float fireball_wormhole_intensity(fireball *fb)
{
float t = fb->time_elapsed;
float rad;

if ( t < fb->warp_open_duration ) {
rad = (float)pow(t / fb->warp_open_duration, 0.4f);
} else if ( t < fb->total_time - fb->warp_close_duration ) {
rad = 1.0f;
float rad = cutscene_wormhole(t / fb->warp_open_duration);

fireball_info* fi = &Fireball_info[fb->fireball_info_index];

if (fi->warp_model_style == warp_style::CINEMATIC) {
rad *= cutscene_wormhole((fb->total_time - t) / fb->warp_close_duration);
rad /= cutscene_wormhole(fb->total_time / (2.0f * fb->warp_open_duration));
rad /= cutscene_wormhole(fb->total_time / (2.0f * fb->warp_close_duration));
} else {
rad = (float)pow((fb->total_time - t) / fb->warp_close_duration, 0.4f);
if (t < fb->warp_open_duration) {
rad = (float)pow(t / fb->warp_open_duration, 0.4f);
} else if (t < fb->total_time - fb->warp_close_duration) {
rad = 1.0f;
} else {
rad = (float)pow((fb->total_time - t) / fb->warp_close_duration, 0.4f);
}
}

return rad;
}

static float fireball_wormhole_flare_radius(fireball* fb) {
float t = fb->time_elapsed;
float d1 = fb->warp_open_duration;
float d2 = fb->warp_close_duration;

float rad = 2 * (1.0f - exp(-4.0f * powf(1.7f * t/d1, 3.0f))) - (1.0f - exp(-2.0f * powf(1.7f * t/d1, 3.0f)));
rad *= (1.0f - exp(-2.0f * (fb->total_time - t) / d2));

return rad;
}

extern void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, bool warp_3d, int warp_glow_bitmap, int warp_ball_bitmap, int warp_model_id);
extern void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float flare_rad, float flicker_magnitude, float max_radius, bool warp_3d, int warp_glow_bitmap, int warp_ball_bitmap, int warp_model_id);

void fireball_render(object* obj, model_draw_list *scene)
{
Expand Down Expand Up @@ -1087,11 +1228,53 @@ void fireball_render(object* obj, model_draw_list *scene)
break;

case FIREBALL_WARP_EFFECT: {
fireball_info* fi = &Fireball_info[fb->fireball_info_index];
float percent_life = fb->time_elapsed / fb->total_time;
float rad = obj->radius * fireball_wormhole_intensity(fb);
float rad = obj->radius * fireball_wormhole_intensity(fb) * fi->warp_size_ratio;

float flare_rad = obj->radius * fi->flare_size_ratio;

matrix* warp_orientation;

// Flare animation selection
if (fi->warp_flare_style == warp_style::ENHANCED) {
flare_rad += powf((2.0f * percent_life) - 1.0f, 24.0f) * obj->radius * 1.5f * fi->flare_size_ratio;
} else if (fi->warp_flare_style == warp_style::CINEMATIC) {
flare_rad *= fireball_wormhole_flare_radius(fb);
} else {
flare_rad *= fireball_wormhole_intensity(fb);
}

if (fi->warp_model_style == warp_style::CINEMATIC) {
matrix m = ZERO_MATRIX;
matrix dest = ZERO_MATRIX;

float duration_ratio = 2.0f / fb->warp_open_duration;

float angle = exp_to_line(fb->time_elapsed, PI * fi->rot_anim[0] * duration_ratio,
PI * fi->rot_anim[1],
fi->rot_anim[2] * duration_ratio);

matrix* bank_angle = vm_angle_2_matrix(&m, angle, 1);
warp_orientation = vm_matrix_x_matrix(&dest, &obj->orient, bank_angle);
} else {
warp_orientation = &obj->orient;
}

fireball_info *fi = &Fireball_info[fb->fireball_info_index];
warpin_queue_render(scene, obj, &obj->orient, &obj->pos, fb->current_bitmap, rad, percent_life, obj->radius, fi->use_3d_warp || (fb->flags & FBF_WARP_3D) != 0, fi->warp_glow_bitmap, fi->warp_ball_bitmap, fi->warp_model_id);
warpin_queue_render(scene,
obj,
warp_orientation,
&obj->pos,
fb->current_bitmap,
rad,
percent_life,
flare_rad,
fi->flicker_magnitude,
obj->radius,
fi->use_3d_warp || (fb->flags & FBF_WARP_3D) != 0,
fi->warp_glow_bitmap,
fi->warp_ball_bitmap,
fi->warp_model_id);
}
break;

Expand Down
20 changes: 20 additions & 0 deletions code/fireball/fireballs.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ class asteroid_info;

#define FIREBALL_NUM_LARGE_EXPLOSIONS 2

// Gamma39er: Flare animation enum. Add new animation types here.
enum class warp_style
{
CLASSIC,
ENHANCED,
CINEMATIC
};

// all this moved here by Goober5000 because it makes more sense in the H file
typedef struct fireball_lod {
char filename[MAX_FILENAME_LEN];
Expand All @@ -56,6 +64,18 @@ typedef struct fireball_info {
bool use_3d_warp;
bool fireball_used;

warp_style warp_flare_style;
warp_style warp_model_style;

// Customize how large the warp and it's flare are.
float warp_size_ratio;
float flare_size_ratio;
float flicker_magnitude;

// Cinematic Warp stuff
float rot_anim[3];
float frame_anim[3];

char warp_glow[NAME_LENGTH];
int warp_glow_bitmap;
char warp_ball[NAME_LENGTH];
Expand Down
13 changes: 4 additions & 9 deletions code/fireball/warpineffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void warpin_batch_draw_face( int texture, vertex *v1, vertex *v2, vertex *v3 )
batching_add_tri(texture, vertlist); // TODO render as emissive
}

void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, bool warp_3d, int warp_glow_bitmap, int warp_ball_bitmap, int warp_model_id)
void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float flare_rad, float flicker_magnitude, float max_radius, bool warp_3d, int warp_glow_bitmap, int warp_ball_bitmap, int warp_model_id)
{
vec3d center;
vec3d vecs[5];
Expand All @@ -76,17 +76,12 @@ void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, ve
verts[1] = verts[2] = verts[3] = verts[4] = verts[0];

if (warp_glow_bitmap >= 0) {
float r = flare_rad;

float r = radius;
// Add in noise
int noise_frame = fl2i(Missiontime/15.0f) % NOISE_NUM_FRAMES;

r *= (0.40f + Noise[noise_frame] * 0.30f);

// Bobboau's warp thingie, toggled by cmdline
if (warpin_show_flash()) {
r += powf((2.0f * life_percent) - 1.0f, 24.0f) * max_radius * 1.5f;
}
r *= (0.40f + Noise[noise_frame] * flicker_magnitude);

vecs[4] = center;
verts[4].texture_position.u = 0.5f; verts[4].texture_position.v = 0.5f;
Expand All @@ -103,7 +98,7 @@ void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, ve
if ( (warp_model_id >= 0) && (warp_3d) ) {
model_render_params render_info;

float scale = radius / 25.0f;
float scale = radius;

vec3d warp_scale;

Expand Down

0 comments on commit ab00484

Please sign in to comment.