Convert all path-related (body, switch) logic to use integer milliseconds
authorparasti <parasti@78b8d119-cf0a-0410-b17c-f493084dd1d7>
Sun, 23 Jan 2011 16:06:31 +0000 (16:06 +0000)
committerparasti <parasti@78b8d119-cf0a-0410-b17c-f493084dd1d7>
Sun, 23 Jan 2011 16:06:31 +0000 (16:06 +0000)
This is an experimental change, so keep an eye out for problems.  It
will almost certainly break maps that expect higher time granularity
than 1 millisecond (0.001 second), any such maps will need to be fixed
manually.

git-svn-id: https://s.snth.net/svn/neverball/trunk@3454 78b8d119-cf0a-0410-b17c-f493084dd1d7

share/common.h
share/solid.c
share/solid.h
share/solid_all.c
share/solid_all.h
share/solid_sim_sol.c

index ed9c356..7f1c2f6 100644 (file)
@@ -41,6 +41,9 @@
                                    (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 *);
 
index 4e25564..c45bb72 100644 (file)
@@ -19,6 +19,7 @@
 #include "solid.h"
 #include "base_config.h"
 #include "binary.h"
+#include "common.h"
 #include "fs.h"
 
 enum
@@ -129,6 +130,9 @@ static void sol_load_path(fs_file fin, struct s_path *pp)
     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);
 
@@ -174,6 +178,12 @@ static void sol_load_swch(fs_file fin, struct s_swch *xp)
     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)
index 5700bd7..23d1ae1 100644 (file)
@@ -181,6 +181,7 @@ struct s_path
     float p[3];                                /* starting position          */
     float e[4];                                /* orientation (quaternion)   */
     float t;                                   /* travel time                */
+    int   tm;                                  /* milliseconds               */
 
     int pi;
     int f;                                     /* enable flag                */
@@ -194,6 +195,7 @@ struct s_path
 struct s_body
 {
     float t;                                   /* time on current path       */
+    int   tm;                                  /* milliseconds               */
 
     GLuint ol;                                 /* opaque geometry list       */
     GLuint tl;                                 /* transparent geometry list  */
@@ -228,7 +230,9 @@ struct s_swch
     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?              */
index 957ab75..ea2836c 100644 (file)
@@ -305,7 +305,7 @@ static void sol_path_loop(struct s_file *fp, int p0, int f)
 /*
  * 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;
 
@@ -315,13 +315,12 @@ void sol_swch_step(struct s_file *fp, float dt)
     {
         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);
 
@@ -338,7 +337,7 @@ void sol_swch_step(struct s_file *fp, float dt)
 /*
  * 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;
 
@@ -349,15 +348,15 @@ void sol_body_step(struct s_file *fp, float dt)
         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;
@@ -512,7 +511,7 @@ int sol_swch_test(struct s_file *fp, int ui)
 
         /* 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];
 
@@ -538,7 +537,7 @@ int sol_swch_test(struct s_file *fp, int ui)
                 {
                     /* The ball enters. */
 
-                    if (xp->t0 == 0)
+                    if (xp->t0m == 0)
                     {
                         xp->e = 1;
 
@@ -560,7 +559,10 @@ int sol_swch_test(struct s_file *fp, int ui)
                     /* 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. */
 
index 5887750..56ecbfc 100644 (file)
@@ -16,8 +16,8 @@ void sol_pendulum(struct s_ball *up,
                   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
index 7c0a350..8990867 100644 (file)
@@ -631,6 +631,50 @@ static float sol_test_file(float dt,
 /*---------------------------------------------------------------------------*/
 
 /*
+ * 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
@@ -695,7 +739,7 @@ float sol_step(struct s_file *fp, const float *g, float dt, int ui, int *m)
         for (c = 16; c > 0 && tt > 0; c--)
         {
             float st;
-            int bi;
+            int bi, ms;
 
             /* HACK: avoid stepping across path changes. */
 
@@ -712,8 +756,8 @@ float sol_step(struct s_file *fp, const float *g, float dt, int ui, int *m)
                     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);
                 }
             }
 
@@ -728,8 +772,10 @@ float sol_step(struct s_file *fp, const float *g, float dt, int ui, int *m)
             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)
@@ -751,7 +797,7 @@ float sol_step(struct s_file *fp, const float *g, float dt, int ui, int *m)
 
 void sol_init_sim(struct s_file *fp)
 {
-    return;
+    ms_init();
 }
 
 void sol_quit_sim(void)