Removed the new Demo Interpolating code and added the improvements to the old one
This commit is contained in:
parent
7e92589332
commit
e3ccb8e6cf
|
@ -1,5 +1,9 @@
|
|||
D1X-Rebirth Changelog
|
||||
|
||||
20100121
|
||||
--------
|
||||
main/newdemo.c: Removed the new Demo Interpolating code and added the improvements to the old one
|
||||
|
||||
20100120
|
||||
--------
|
||||
arch/include/event.h, arch/sdl/event.c, arch/sdl/window.c, main/automap.c, main/game.c, main/gamecntl.c, main/kconfig.c, main/menu.c, main/net_ipx.c, main/net_udp.c, main/newmenu.c, main/state.c: Add EVENT_WINDOW_ACTIVATED, change EVENT_DRAW to EVENT_WINDOW_DRAW and EVENT_CLOSE to EVENT_WINDOW_CLOSE
|
||||
|
|
242
main/newdemo.c
242
main/newdemo.c
|
@ -138,6 +138,8 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
|
||||
#define NORMAL_PLAYBACK 0
|
||||
#define SKIP_PLAYBACK 1
|
||||
#define INTERPOLATE_PLAYBACK 2
|
||||
#define INTERPOL_FACTOR (F1_0 + (F1_0/5))
|
||||
|
||||
#define DEMO_VERSION_SHAREWARE 5
|
||||
#define DEMO_VERSION 13
|
||||
|
@ -2726,90 +2728,129 @@ void newdemo_back_frames(int frames)
|
|||
|
||||
}
|
||||
|
||||
void DoZicoInterpolate (fix recorded_time)
|
||||
/*
|
||||
* routine to interpolate the viewer position. the current position is
|
||||
* stored in the Viewer object. Save this position, and read the next
|
||||
* frame to get all objects read in. Calculate the delta playback and
|
||||
* the delta recording frame times between the two frames, then intepolate
|
||||
* the viewers position accordingly. nd_recorded_time is the time that it
|
||||
* took the recording to render the frame that we are currently looking
|
||||
* at.
|
||||
*/
|
||||
|
||||
void interpolate_frame(fix d_play, fix d_recorded)
|
||||
{
|
||||
static fix delay_time=0;
|
||||
int i = 0, j = 0;
|
||||
object SavObj[MAX_OBJECTS];
|
||||
int SavObjNum;
|
||||
int i, j, num_cur_objs;
|
||||
fix factor;
|
||||
object *cur_objs;
|
||||
static fix InterpolStep = fl2f(.01);
|
||||
|
||||
memset(&SavObj, 0, sizeof(object)*MAX_OBJECTS);
|
||||
|
||||
if (NewdemoFrameCount < 2)
|
||||
InterpolStep -= FrameTime;
|
||||
// This interpolating looks just more crappy on high FPS, so let's not even waste performance on it.
|
||||
if (InterpolStep >= 0)
|
||||
return;
|
||||
InterpolStep = fl2f(.01);
|
||||
|
||||
factor = fixdiv(d_play, d_recorded);
|
||||
if (factor > F1_0)
|
||||
factor = F1_0;
|
||||
|
||||
num_cur_objs = Highest_object_index;
|
||||
cur_objs = (object *)d_malloc(sizeof(object) * (num_cur_objs + 1));
|
||||
if (cur_objs == NULL) {
|
||||
Int3();
|
||||
return;
|
||||
}
|
||||
for (i = 0; i <= num_cur_objs; i++)
|
||||
memcpy(&(cur_objs[i]), &(Objects[i]), sizeof(object));
|
||||
|
||||
// Read in the next Frame and store the objects from it.
|
||||
Newdemo_vcr_state = ND_STATE_PAUSED;
|
||||
if (newdemo_read_frame_information(0) == -1)
|
||||
{
|
||||
if (newdemo_read_frame_information(0) == -1) {
|
||||
d_free(cur_objs);
|
||||
newdemo_stop_playback();
|
||||
return;
|
||||
}
|
||||
Newdemo_vcr_state = ND_STATE_PLAYBACK;
|
||||
for (i=0; i<=Highest_object_index; i++)
|
||||
memcpy(&SavObj[i], &Objects[i], sizeof(object));
|
||||
SavObjNum=Highest_object_index;
|
||||
newdemo_back_frames(1);
|
||||
|
||||
// Do necessary steps to repeat a Demo-Frame if necessary
|
||||
if (recorded_time > FrameTime)
|
||||
{
|
||||
if (delay_time <= 0)
|
||||
{
|
||||
delay_time += recorded_time;
|
||||
}
|
||||
else if (delay_time > 0)
|
||||
{
|
||||
newdemo_back_frames(1);
|
||||
delay_time -= FrameTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Newdemo_do_interpolate)
|
||||
return;
|
||||
|
||||
// Interpolate objects.
|
||||
for (i = 0; i <= SavObjNum; i++)
|
||||
{
|
||||
for (j = 0; j <= Highest_object_index; j++)
|
||||
{
|
||||
if (SavObj[i].signature == Objects[j].signature)
|
||||
{
|
||||
vms_vector fvec1, fvec2, rvec1, rvec2;
|
||||
fix mag1;
|
||||
for (i = 0; i <= num_cur_objs; i++) {
|
||||
for (j = 0; j <= Highest_object_index; j++) {
|
||||
if (cur_objs[i].signature == Objects[j].signature) {
|
||||
sbyte render_type = cur_objs[i].render_type;
|
||||
fix delta_x, delta_y, delta_z;
|
||||
|
||||
/*
|
||||
* HACK: Good 'ol Descent does not check for duplicate signatures when creating objects.
|
||||
* So in case our two objects have a huge distance, we assume they are different.
|
||||
* Interpolating would not make much sense in that case nevertheless.
|
||||
*/
|
||||
if (vm_vec_dist(&SavObj[i].pos, &Objects[j].pos) > (Objects[j].size*2))
|
||||
if (vm_vec_dist(&cur_objs[i].pos, &Objects[j].pos) > (Objects[j].size*2))
|
||||
continue;
|
||||
|
||||
vm_vec_avg(&Objects[j].pos, &SavObj[i].pos, &Objects[j].pos);
|
||||
|
||||
if (!((SavObj[i].render_type == RT_LASER) || (SavObj[i].render_type == RT_FIREBALL) || (SavObj[i].render_type == RT_POWERUP)))
|
||||
{
|
||||
fvec1 = SavObj[i].orient.fvec;
|
||||
// Extract the angles from the object orientation matrix.
|
||||
// Some of this code taken from ai_turn_towards_vector
|
||||
// Don't do the interpolation on certain render types which don't use an orientation matrix
|
||||
|
||||
if (!((render_type == RT_LASER) || (render_type == RT_FIREBALL) || (render_type == RT_POWERUP))) {
|
||||
|
||||
vms_vector fvec1, fvec2, rvec1, rvec2;
|
||||
fix mag1;
|
||||
|
||||
fvec1 = cur_objs[i].orient.fvec;
|
||||
vm_vec_scale(&fvec1, F1_0-factor);
|
||||
fvec2 = Objects[j].orient.fvec;
|
||||
vm_vec_scale(&fvec2, factor);
|
||||
vm_vec_add2(&fvec1, &fvec2);
|
||||
mag1 = vm_vec_normalize_quick(&fvec1);
|
||||
if (mag1 > F1_0/256) {
|
||||
rvec1 = SavObj[i].orient.rvec;
|
||||
rvec1 = cur_objs[i].orient.rvec;
|
||||
vm_vec_scale(&rvec1, F1_0-factor);
|
||||
rvec2 = Objects[j].orient.rvec;
|
||||
vm_vec_scale(&rvec2, factor);
|
||||
vm_vec_add2(&rvec1, &rvec2);
|
||||
vm_vec_normalize_quick(&rvec1);
|
||||
vm_vector_2_matrix(&Objects[j].orient, &fvec1, NULL, &rvec1);
|
||||
vm_vec_normalize_quick(&rvec1); // Note: Doesn't matter if this is null, if null, vm_vector_2_matrix will just use fvec1
|
||||
vm_vector_2_matrix(&cur_objs[i].orient, &fvec1, NULL, &rvec1);
|
||||
}
|
||||
}
|
||||
|
||||
// Interpolate the object position. This is just straight linear
|
||||
// interpolation.
|
||||
|
||||
delta_x = Objects[j].pos.x - cur_objs[i].pos.x;
|
||||
delta_y = Objects[j].pos.y - cur_objs[i].pos.y;
|
||||
delta_z = Objects[j].pos.z - cur_objs[i].pos.z;
|
||||
|
||||
delta_x = fixmul(delta_x, factor);
|
||||
delta_y = fixmul(delta_y, factor);
|
||||
delta_z = fixmul(delta_z, factor);
|
||||
|
||||
cur_objs[i].pos.x += delta_x;
|
||||
cur_objs[i].pos.y += delta_y;
|
||||
cur_objs[i].pos.z += delta_z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get back to original position in the demo file. Reread the current
|
||||
// frame information again to reset all of the object stuff not covered
|
||||
// with Highest_object_index and the object array (previously rendered
|
||||
// objects, etc....)
|
||||
|
||||
newdemo_back_frames(1);
|
||||
newdemo_back_frames(1);
|
||||
if (newdemo_read_frame_information(0) == -1)
|
||||
newdemo_stop_playback();
|
||||
Newdemo_vcr_state = ND_STATE_PLAYBACK;
|
||||
|
||||
for (i = 0; i <= num_cur_objs; i++)
|
||||
memcpy(&(Objects[i]), &(cur_objs[i]), sizeof(object));
|
||||
Highest_object_index = num_cur_objs;
|
||||
d_free(cur_objs);
|
||||
}
|
||||
|
||||
void newdemo_playback_one_frame()
|
||||
{
|
||||
int frames_back, i, level;
|
||||
static fix base_interpol_time = 0;
|
||||
static fix d_recorded = 0;
|
||||
|
||||
for (i = 0; i < MAX_PLAYERS; i++)
|
||||
if (Players[i].flags & PLAYER_FLAGS_CLOAKED)
|
||||
|
@ -2890,9 +2931,9 @@ void newdemo_playback_one_frame()
|
|||
else {
|
||||
|
||||
// First, uptate the total playback time to date. Then we check to see
|
||||
// if we need to change the playback style to skip frames.
|
||||
// In the end, interpolate between current and next frame and repeat frames
|
||||
// if FPS are higher than recorded FPS.
|
||||
// if we need to change the playback style to interpolate frames or
|
||||
// skip frames based on where the playback time is relative to the
|
||||
// recorded time.
|
||||
|
||||
if (NewdemoFrameCount <= 0)
|
||||
nd_playback_total = nd_recorded_total; // baseline total playback time
|
||||
|
@ -2903,24 +2944,97 @@ void newdemo_playback_one_frame()
|
|||
{
|
||||
if (nd_playback_total > nd_recorded_total)
|
||||
playback_style = SKIP_PLAYBACK;
|
||||
|
||||
//if ((nd_playback_total * INTERPOL_FACTOR) < nd_recorded_total) // no matte rhow we look at it: this does not make ANY sense!
|
||||
if (nd_recorded_total > 0 && nd_recorded_time > 0)
|
||||
{
|
||||
playback_style = INTERPOLATE_PLAYBACK;
|
||||
nd_playback_total = nd_recorded_total + FrameTime; // baseline playback time
|
||||
base_interpol_time = nd_recorded_total;
|
||||
d_recorded = nd_recorded_time; // baseline delta recorded
|
||||
}
|
||||
}
|
||||
|
||||
if (newdemo_read_frame_information(0) == -1) {
|
||||
newdemo_stop_playback();
|
||||
|
||||
if ((playback_style == INTERPOLATE_PLAYBACK) && Newdemo_do_interpolate) {
|
||||
fix d_play = 0;
|
||||
|
||||
if (nd_recorded_total - nd_playback_total < FrameTime) {
|
||||
d_recorded = nd_recorded_total - nd_playback_total;
|
||||
|
||||
while (nd_recorded_total - nd_playback_total < FrameTime) {
|
||||
object *cur_objs;
|
||||
int i, j, num_objs, level;
|
||||
|
||||
num_objs = Highest_object_index;
|
||||
cur_objs = (object *)d_malloc(sizeof(object) * (num_objs + 1));
|
||||
if (cur_objs == NULL) {
|
||||
Warning ("Couldn't get %d bytes for objects in interpolate playback\n", sizeof(object) * num_objs);
|
||||
break;
|
||||
}
|
||||
for (i = 0; i <= num_objs; i++)
|
||||
memcpy(&(cur_objs[i]), &(Objects[i]), sizeof(object));
|
||||
|
||||
level = Current_level_num;
|
||||
if (newdemo_read_frame_information(0) == -1) {
|
||||
d_free(cur_objs);
|
||||
newdemo_stop_playback();
|
||||
return;
|
||||
}
|
||||
if (level != Current_level_num) {
|
||||
d_free(cur_objs);
|
||||
if (newdemo_read_frame_information(0) == -1)
|
||||
newdemo_stop_playback();
|
||||
break;
|
||||
}
|
||||
|
||||
// for each new object in the frame just read in, determine if there is
|
||||
// a corresponding object that we have been interpolating. If so, then
|
||||
// copy that interpolated object to the new Objects array so that the
|
||||
// interpolated position and orientation can be preserved.
|
||||
|
||||
for (i = 0; i <= num_objs; i++) {
|
||||
for (j = 0; j <= Highest_object_index; j++) {
|
||||
if (cur_objs[i].signature == Objects[j].signature) {
|
||||
/*
|
||||
* HACK: Good 'ol Descent does not check for duplicate signatures when creating objects.
|
||||
* So in case our two objects have a huge distance, we assume they are different.
|
||||
* Interpolating would not make much sense in that case nevertheless.
|
||||
*/
|
||||
if (vm_vec_dist(&cur_objs[i].pos, &Objects[j].pos) > (Objects[j].size*2))
|
||||
continue;
|
||||
|
||||
memcpy(&(Objects[j].orient), &(cur_objs[i].orient), sizeof(vms_matrix));
|
||||
memcpy(&(Objects[j].pos), &(cur_objs[i].pos), sizeof(vms_vector));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
d_free(cur_objs);
|
||||
d_recorded += nd_recorded_time;
|
||||
base_interpol_time = nd_playback_total - FrameTime;
|
||||
}
|
||||
}
|
||||
|
||||
d_play = nd_playback_total - base_interpol_time;
|
||||
interpolate_frame(d_play, d_recorded);
|
||||
return;
|
||||
}
|
||||
if (playback_style == SKIP_PLAYBACK) {
|
||||
while (nd_playback_total > nd_recorded_total) {
|
||||
if (newdemo_read_frame_information(0) == -1) {
|
||||
newdemo_stop_playback();
|
||||
return;
|
||||
else {
|
||||
if (newdemo_read_frame_information(0) == -1) {
|
||||
newdemo_stop_playback();
|
||||
return;
|
||||
}
|
||||
if (playback_style == SKIP_PLAYBACK) {
|
||||
while (nd_playback_total > nd_recorded_total) {
|
||||
if (newdemo_read_frame_information(0) == -1) {
|
||||
newdemo_stop_playback();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Newdemo_vcr_state == ND_STATE_PLAYBACK)
|
||||
DoZicoInterpolate(nd_recorded_time);
|
||||
}
|
||||
|
||||
void newdemo_start_recording()
|
||||
|
|
Loading…
Reference in a new issue