/** * After a long period with no updates (map setup), calling this will reset * the tictimer so that no time seems to have passed. */ void Net_ResetTimer(void) { int i; firstNetUpdate = true; for(i = 0; i < DDMAXPLAYERS; ++i) { if(/*!clients[i].connected ||*/ !clients[i].smoother) continue; Smoother_Clear(clients[i].smoother); } }
void Smoother_AddPos(Smoother *sm, float time, coord_t x, coord_t y, coord_t z, dd_bool onFloor) { pos_t *last; DENG_ASSERT(sm); // Is it the same point? last = &sm->points[SM_NUM_POINTS - 1]; if(last->time == time) { if(last->xyz[VX] == x && last->xyz[VY] == y && last->xyz[VZ] == z) { // Ignore it. return; } // Readjusting a previously set value? goto replaceLastPoint; } if(time <= sm->now.time) { // The new point would be in the past, this is no good. #ifdef _DEBUG LOG_DEBUG("Smoother_AddPos: DISCARDING new pos, time=%f, now=%f.") << time << sm->now.time; #endif Smoother_Clear(sm); return; } // If we are about to discard an unused future point, we will force // the current interpolation into the future. if(Smoother_IsValid(sm) && sm->points[0].time > sm->now.time) { coord_t mid[3]; float remaining; // Move the past forward in time so that the interpolation remains continuous. remaining = sm->now.time - sm->at; Smoother_Evaluate(sm, mid); sm->at = sm->past.time = sm->points[0].time - remaining; sm->past.xyz[VX] = mid[VX]; sm->past.xyz[VY] = mid[VY]; sm->past.xyz[VZ] = mid[VZ]; // Replace the now with the point about to be discarded. memcpy(&sm->now, &sm->points[0], sizeof(pos_t)); } // Rotate the old points. memmove(&sm->points[0], &sm->points[1], sizeof(pos_t) * (SM_NUM_POINTS - 1)); replaceLastPoint: last = &sm->points[SM_NUM_POINTS - 1]; last->time = time; last->xyz[VX] = x; last->xyz[VY] = y; last->xyz[VZ] = z; last->onFloor = onFloor; // Is this the first one? if(sm->now.time == 0) { sm->at = time; memcpy(&sm->past, last, sizeof(pos_t)); memcpy(&sm->now, last, sizeof(pos_t)); } }