(src), \
MAX(0, MAXSTRLEN(dst) - strlen(dst))))
+#define TIME_TO_MS(t) ((int) ((t) * 1000.0f))
+#define MS_TO_TIME(m) ((m) * 0.001f)
+
int read_line(char **, fs_file);
char *strip_newline(char *);
#include "solid.h"
#include "base_config.h"
#include "binary.h"
+#include "common.h"
#include "fs.h"
enum
get_index(fin, &pp->f);
get_index(fin, &pp->s);
+ pp->tm = TIME_TO_MS(pp->t);
+ pp->t = MS_TO_TIME(pp->tm);
+
if (sol_version >= SOL_VER_PATH_FLAGS)
get_index(fin, &pp->fl);
get_index(fin, &xp->f0);
get_index(fin, &xp->f);
get_index(fin, &xp->i);
+
+ xp->t0m = TIME_TO_MS(xp->t0);
+ xp->tm = TIME_TO_MS(xp->t);
+
+ xp->t0 = MS_TO_TIME(xp->t0m);
+ xp->t = MS_TO_TIME(xp->tm);
}
static void sol_load_bill(fs_file fin, struct s_bill *rp)
float p[3]; /* starting position */
float e[4]; /* orientation (quaternion) */
float t; /* travel time */
+ int tm; /* milliseconds */
int pi;
int f; /* enable flag */
struct s_body
{
float t; /* time on current path */
+ int tm; /* milliseconds */
GLuint ol; /* opaque geometry list */
GLuint tl; /* transparent geometry list */
int pi; /* the linked path */
float t0; /* default timer */
+ int t0m; /* milliseconds */
float t; /* current timer */
+ int tm; /* milliseconds */
int f0; /* default state */
int f; /* current state */
int i; /* is invisible? */
/*
* Compute the states of all switches after DT seconds have passed.
*/
-void sol_swch_step(struct s_file *fp, float dt)
+void sol_swch_step(struct s_file *fp, float dt, int ms)
{
int xi;
{
struct s_swch *xp = fp->xv + xi;
- volatile float t = xp->t;
-
- if (t < xp->t0)
+ if (xp->tm < xp->t0m)
{
- xp->t = (t += dt);
+ xp->t += dt;
+ xp->tm += ms;
- if (t >= xp->t0)
+ if (xp->tm >= xp->t0m)
{
sol_path_loop(fp, xp->pi, xp->f0);
/*
* Compute the positions of all bodies after DT seconds have passed.
*/
-void sol_body_step(struct s_file *fp, float dt)
+void sol_body_step(struct s_file *fp, float dt, int ms)
{
int i;
struct s_body *bp = fp->bv + i;
struct s_path *pp = fp->pv + bp->pi;
- volatile float t = bp->t;
-
if (bp->pi >= 0 && pp->f)
{
- bp->t = (t += dt);
+ bp->t += dt;
+ bp->tm += ms;
- if (t >= pp->t)
+ if (bp->tm >= pp->tm)
{
bp->t = 0;
+ bp->tm = 0;
bp->pi = pp->pi;
cmd.type = CMD_BODY_TIME;
/* FIXME enter/exit events don't work for timed switches */
- if (xp->t0 == 0 || xp->f == xp->f0)
+ if (xp->t0m == 0 || xp->f == xp->f0)
{
float d, r[3];
{
/* The ball enters. */
- if (xp->t0 == 0)
+ if (xp->t0m == 0)
{
xp->e = 1;
/* It toggled to non-default state, start the timer. */
if (xp->f != xp->f0)
+ {
xp->t = 0.0f;
+ xp->tm = 0;
+ }
/* If visible, set the result. */
const float a[3],
const float g[3], float dt);
-void sol_swch_step(struct s_file *fp, float dt);
-void sol_body_step(struct s_file *fp, float dt);
+void sol_swch_step(struct s_file *fp, float dt, int ms);
+void sol_body_step(struct s_file *fp, float dt, int ms);
void sol_ball_step(struct s_file *fp, float dt);
enum
/*---------------------------------------------------------------------------*/
/*
+ * Track simulation steps in integer milliseconds.
+ */
+
+static float ms_accum;
+
+static void ms_init(void)
+{
+ ms_accum = 0.0f;
+}
+
+static int ms_step(float dt)
+{
+ int ms = 0;
+
+ ms_accum += dt;
+
+ while (ms_accum >= 0.001f)
+ {
+ ms_accum -= 0.001f;
+ ms += 1;
+ }
+
+ return ms;
+}
+
+static int ms_peek(float dt)
+{
+ int ms = 0;
+ float at;
+
+ at = ms_accum + dt;
+
+ while (at >= 0.001f)
+ {
+ at -= 0.001f;
+ ms += 1;
+ }
+
+ return ms;
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*
* Step the physics forward DT seconds under the influence of gravity
* vector G. If the ball gets pinched between two moving solids, this
* loop might not terminate. It is better to do something physically
for (c = 16; c > 0 && tt > 0; c--)
{
float st;
- int bi;
+ int bi, ms;
/* HACK: avoid stepping across path changes. */
if (!pp->f)
continue;
- if (bp->t + st > pp->t)
- st = pp->t - bp->t;
+ if (bp->tm + ms_peek(st) > pp->tm)
+ st = MS_TO_TIME(pp->tm - bp->tm);
}
}
cmd.stepsim.dt = nt;
sol_cmd_enq(&cmd);
- sol_body_step(fp, nt);
- sol_swch_step(fp, nt);
+ ms = ms_step(nt);
+
+ sol_body_step(fp, nt, ms);
+ sol_swch_step(fp, nt, ms);
sol_ball_step(fp, nt);
if (nt < st)
void sol_init_sim(struct s_file *fp)
{
- return;
+ ms_init();
}
void sol_quit_sim(void)