Split SOL data structures into base, varying and rendering parts
authorparasti <parasti@78b8d119-cf0a-0410-b17c-f493084dd1d7>
Thu, 10 Feb 2011 18:59:50 +0000 (18:59 +0000)
committerparasti <parasti@78b8d119-cf0a-0410-b17c-f493084dd1d7>
Thu, 10 Feb 2011 18:59:50 +0000 (18:59 +0000)
git-svn-id: https://s.snth.net/svn/neverball/trunk@3485 78b8d119-cf0a-0410-b17c-f493084dd1d7

33 files changed:
Makefile
ball/demo.c
ball/game_client.c
ball/game_client.h
ball/game_common.c
ball/game_common.h
ball/game_draw.c
ball/game_draw.h
ball/game_server.c
ball/game_server.h
ball/level.c
ball/st_demo.c
putt/game.c
share/ball.c
share/geom.c
share/geom.h
share/item.c
share/item.h
share/mapc.c
share/solid.c [deleted file]
share/solid.h [deleted file]
share/solid_all.c
share/solid_all.h
share/solid_base.c [new file with mode: 0644]
share/solid_base.h [new file with mode: 0644]
share/solid_draw.c [new file with mode: 0644]
share/solid_draw.h [new file with mode: 0644]
share/solid_gl.c [deleted file]
share/solid_gl.h [deleted file]
share/solid_sim.h
share/solid_sim_sol.c
share/solid_vary.c [new file with mode: 0644]
share/solid_vary.h [new file with mode: 0644]

index 3579a60..169b9f8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -166,7 +166,7 @@ endif
 MAPC_OBJS := \
        share/vec3.o        \
        share/base_image.o  \
-       share/solid.o       \
+       share/solid_base.o  \
        share/binary.o      \
        share/base_config.o \
        share/common.o      \
@@ -183,8 +183,9 @@ BALL_OBJS := \
        share/vec3.o        \
        share/base_image.o  \
        share/image.o       \
-       share/solid.o       \
-       share/solid_gl.o    \
+       share/solid_base.o  \
+       share/solid_vary.o  \
+       share/solid_draw.o  \
        share/solid_cmd.o   \
        share/solid_all.o   \
        share/part.o        \
@@ -252,8 +253,9 @@ PUTT_OBJS := \
        share/vec3.o        \
        share/base_image.o  \
        share/image.o       \
-       share/solid.o       \
-       share/solid_gl.o    \
+       share/solid_base.o  \
+       share/solid_vary.o  \
+       share/solid_draw.o  \
        share/solid_cmd.o   \
        share/solid_all.o   \
        share/part.o        \
index 9f18cd0..b843e56 100644 (file)
@@ -20,7 +20,6 @@
 
 #include "demo.h"
 #include "audio.h"
-#include "solid.h"
 #include "config.h"
 #include "binary.h"
 #include "common.h"
index 0a53260..631d95b 100644 (file)
 #include "ball.h"
 #include "image.h"
 #include "audio.h"
-#include "solid_gl.h"
 #include "config.h"
 #include "video.h"
 
+#include "solid_draw.h"
+
 #include "game_client.h"
 #include "game_common.h"
 #include "game_proxy.h"
@@ -42,7 +43,7 @@ int game_compat_map;                    /* Client/server map compat flag     */
 
 /*---------------------------------------------------------------------------*/
 
-static struct game_draw dr;
+static struct game_draw gd;
 
 static float timer  = 0.0f;             /* Clock time                        */
 static int   status = GAME_NONE;        /* Outcome of the game               */
@@ -70,11 +71,11 @@ static int got_tilt_axes;
 
 static void game_run_cmd(const union cmd *cmd)
 {
-    if (dr.state)
+    if (gd.state)
     {
-        struct s_file *fp = &dr.file;
-        struct s_item *hp;
-        struct s_ball *up;
+        struct s_vary *vary = &gd.file.vary;
+        struct v_item *hp;
+        struct v_ball *up;
 
         float v[3];
         float dt;
@@ -95,9 +96,9 @@ static void game_run_cmd(const union cmd *cmd)
             /* Compute gravity for particle effects. */
 
             if (status == GAME_GOAL)
-                game_tilt_grav(v, GRAVITY_UP, &dr.tilt);
+                game_tilt_grav(v, GRAVITY_UP, &gd.tilt);
             else
-                game_tilt_grav(v, GRAVITY_DN, &dr.tilt);
+                game_tilt_grav(v, GRAVITY_DN, &gd.tilt);
 
             /* Step particle, goal and jump effects. */
 
@@ -105,15 +106,15 @@ static void game_run_cmd(const union cmd *cmd)
             {
                 dt = 1.0f / (float) ups;
 
-                if (dr.goal_e && dr.goal_k < 1.0f)
-                    dr.goal_k += dt;
+                if (gd.goal_e && gd.goal_k < 1.0f)
+                    gd.goal_k += dt;
 
-                if (dr.jump_b)
+                if (gd.jump_b)
                 {
-                    dr.jump_dt += dt;
+                    gd.jump_dt += dt;
 
-                    if (1.0f < dr.jump_dt)
-                        dr.jump_b = 0;
+                    if (1.0f < gd.jump_dt)
+                        gd.jump_b = 0;
                 }
 
                 part_step(v, dt);
@@ -124,29 +125,29 @@ static void game_run_cmd(const union cmd *cmd)
         case CMD_MAKE_BALL:
             /* Allocate a new ball and mark it as the current ball. */
 
-            if ((up = realloc(fp->uv, sizeof (*up) * (fp->uc + 1))))
+            if ((up = realloc(vary->uv, sizeof (*up) * (vary->uc + 1))))
             {
-                fp->uv = up;
-                curr_ball = fp->uc;
-                fp->uc++;
+                vary->uv = up;
+                curr_ball = vary->uc;
+                vary->uc++;
             }
             break;
 
         case CMD_MAKE_ITEM:
             /* Allocate and initialise a new item. */
 
-            if ((hp = realloc(fp->hv, sizeof (*hp) * (fp->hc + 1))))
+            if ((hp = realloc(vary->hv, sizeof (*hp) * (vary->hc + 1))))
             {
-                struct s_item h;
+                struct v_item h;
 
                 v_cpy(h.p, cmd->mkitem.p);
 
                 h.t = cmd->mkitem.t;
                 h.n = cmd->mkitem.n;
 
-                fp->hv = hp;
-                fp->hv[fp->hc] = h;
-                fp->hc++;
+                vary->hv = hp;
+                vary->hv[vary->hc] = h;
+                vary->hc++;
             }
 
             break;
@@ -154,9 +155,9 @@ static void game_run_cmd(const union cmd *cmd)
         case CMD_PICK_ITEM:
             /* Set up particle effects and discard the item. */
 
-            assert(cmd->pkitem.hi < fp->hc);
+            assert(cmd->pkitem.hi < vary->hc);
 
-            hp = fp->hv + cmd->pkitem.hi;
+            hp = vary->hv + cmd->pkitem.hi;
 
             item_color(hp, v);
             part_burst(hp->p, v);
@@ -167,10 +168,10 @@ static void game_run_cmd(const union cmd *cmd)
 
         case CMD_TILT_ANGLES:
             if (!got_tilt_axes)
-                game_tilt_axes(&dr.tilt, dr.view.e);
+                game_tilt_axes(&gd.tilt, gd.view.e);
 
-            dr.tilt.rx = cmd->tiltangles.x;
-            dr.tilt.rz = cmd->tiltangles.z;
+            gd.tilt.rx = cmd->tiltangles.x;
+            gd.tilt.rz = cmd->tiltangles.z;
             break;
 
         case CMD_SOUND:
@@ -194,21 +195,21 @@ static void game_run_cmd(const union cmd *cmd)
             break;
 
         case CMD_JUMP_ENTER:
-            dr.jump_b  = 1;
-            dr.jump_e  = 0;
-            dr.jump_dt = 0.0f;
+            gd.jump_b  = 1;
+            gd.jump_e  = 0;
+            gd.jump_dt = 0.0f;
             break;
 
         case CMD_JUMP_EXIT:
-            dr.jump_e = 1;
+            gd.jump_e = 1;
             break;
 
         case CMD_BODY_PATH:
-            fp->bv[cmd->bodypath.bi].pi = cmd->bodypath.pi;
+            vary->bv[cmd->bodypath.bi].pi = cmd->bodypath.pi;
             break;
 
         case CMD_BODY_TIME:
-            fp->bv[cmd->bodytime.bi].t = cmd->bodytime.t;
+            vary->bv[cmd->bodytime.bi].t = cmd->bodytime.t;
             break;
 
         case CMD_GOAL_OPEN:
@@ -217,23 +218,23 @@ static void game_run_cmd(const union cmd *cmd)
              * this is the first update.
              */
 
-            if (!dr.goal_e)
+            if (!gd.goal_e)
             {
-                dr.goal_e = 1;
-                dr.goal_k = first_update ? 1.0f : 0.0f;
+                gd.goal_e = 1;
+                gd.goal_k = first_update ? 1.0f : 0.0f;
             }
             break;
 
         case CMD_SWCH_ENTER:
-            fp->xv[cmd->swchenter.xi].e = 1;
+            vary->xv[cmd->swchenter.xi].e = 1;
             break;
 
         case CMD_SWCH_TOGGLE:
-            fp->xv[cmd->swchtoggle.xi].f = !fp->xv[cmd->swchtoggle.xi].f;
+            vary->xv[cmd->swchtoggle.xi].f = !vary->xv[cmd->swchtoggle.xi].f;
             break;
 
         case CMD_SWCH_EXIT:
-            fp->xv[cmd->swchexit.xi].e = 0;
+            vary->xv[cmd->swchexit.xi].e = 0;
             break;
 
         case CMD_UPDATES_PER_SECOND:
@@ -241,35 +242,35 @@ static void game_run_cmd(const union cmd *cmd)
             break;
 
         case CMD_BALL_RADIUS:
-            fp->uv[curr_ball].r = cmd->ballradius.r;
+            vary->uv[curr_ball].r = cmd->ballradius.r;
             break;
 
         case CMD_CLEAR_ITEMS:
-            if (fp->hv)
+            if (vary->hv)
             {
-                free(fp->hv);
-                fp->hv = NULL;
+                free(vary->hv);
+                vary->hv = NULL;
             }
-            fp->hc = 0;
+            vary->hc = 0;
             break;
 
         case CMD_CLEAR_BALLS:
-            if (fp->uv)
+            if (vary->uv)
             {
-                free(fp->uv);
-                fp->uv = NULL;
+                free(vary->uv);
+                vary->uv = NULL;
             }
-            fp->uc = 0;
+            vary->uc = 0;
             break;
 
         case CMD_BALL_POSITION:
-            up = fp->uv + curr_ball;
+            up = vary->uv + curr_ball;
 
             v_cpy(up->p, cmd->ballpos.p);
             break;
 
         case CMD_BALL_BASIS:
-            up = fp->uv + curr_ball;
+            up = vary->uv + curr_ball;
 
             v_cpy(up->e[0], cmd->ballbasis.e[0]);
             v_cpy(up->e[1], cmd->ballbasis.e[1]);
@@ -277,7 +278,7 @@ static void game_run_cmd(const union cmd *cmd)
             break;
 
         case CMD_BALL_PEND_BASIS:
-            up = fp->uv + curr_ball;
+            up = vary->uv + curr_ball;
 
             v_cpy(up->E[0], cmd->ballpendbasis.E[0]);
             v_cpy(up->E[1], cmd->ballpendbasis.E[1]);
@@ -285,17 +286,17 @@ static void game_run_cmd(const union cmd *cmd)
             break;
 
         case CMD_VIEW_POSITION:
-            v_cpy(dr.view.p, cmd->viewpos.p);
+            v_cpy(gd.view.p, cmd->viewpos.p);
             break;
 
         case CMD_VIEW_CENTER:
-            v_cpy(dr.view.c, cmd->viewcenter.c);
+            v_cpy(gd.view.c, cmd->viewcenter.c);
             break;
 
         case CMD_VIEW_BASIS:
-            v_cpy(dr.view.e[0], cmd->viewbasis.e[0]);
-            v_cpy(dr.view.e[1], cmd->viewbasis.e[1]);
-            v_crs(dr.view.e[2], dr.view.e[0], dr.view.e[1]);
+            v_cpy(gd.view.e[0], cmd->viewbasis.e[0]);
+            v_cpy(gd.view.e[1], cmd->viewbasis.e[1]);
+            v_crs(gd.view.e[2], gd.view.e[0], gd.view.e[1]);
             break;
 
         case CMD_CURRENT_BALL:
@@ -303,7 +304,7 @@ static void game_run_cmd(const union cmd *cmd)
             break;
 
         case CMD_PATH_FLAG:
-            fp->pv[cmd->pathflag.pi].f = cmd->pathflag.f;
+            vary->pv[cmd->pathflag.pi].f = cmd->pathflag.f;
             break;
 
         case CMD_STEP_SIMULATION:
@@ -321,10 +322,10 @@ static void game_run_cmd(const union cmd *cmd)
 
             dt = cmd->stepsim.dt;
 
-            for (i = 0; i < fp->bc; i++)
+            for (i = 0; i < vary->bc; i++)
             {
-                struct s_body *bp = fp->bv + i;
-                struct s_path *pp = fp->pv + bp->pi;
+                struct v_body *bp = vary->bv + i;
+                struct v_path *pp = vary->pv + bp->pi;
 
                 if (bp->pi >= 0 && pp->f)
                     bp->t += dt;
@@ -342,8 +343,8 @@ static void game_run_cmd(const union cmd *cmd)
 
         case CMD_TILT_AXES:
             got_tilt_axes = 1;
-            v_cpy(dr.tilt.x, cmd->tiltaxes.x);
-            v_cpy(dr.tilt.z, cmd->tiltaxes.z);
+            v_cpy(gd.tilt.x, cmd->tiltaxes.x);
+            v_cpy(gd.tilt.z, cmd->tiltaxes.z);
             break;
 
         case CMD_NONE:
@@ -377,39 +378,39 @@ int  game_client_init(const char *file_name)
     coins  = 0;
     status = GAME_NONE;
 
-    if (dr.state)
+    if (gd.state)
         game_client_free();
 
-    if (!sol_load_gl(&dr.file, file_name, config_get_d(CONFIG_SHADOW)))
-        return (dr.state = 0);
+    if (!sol_load_full(&gd.file, file_name, config_get_d(CONFIG_SHADOW)))
+        return (gd.state = 0);
 
-    dr.reflective = sol_reflective(&dr.file);
+    gd.reflective = sol_reflective(&gd.file.draw);
 
-    dr.state = 1;
+    gd.state = 1;
 
-    game_tilt_init(&dr.tilt);
+    game_tilt_init(&gd.tilt);
 
     /* Initialize jump and goal states. */
 
-    dr.jump_e = 1;
-    dr.jump_b = 0;
+    gd.jump_e = 1;
+    gd.jump_b = 0;
 
-    dr.goal_e = 0;
-    dr.goal_k = 0.0f;
+    gd.goal_e = 0;
+    gd.goal_k = 0.0f;
 
     /* Initialise the level, background, particles, fade, and view. */
 
-    dr.fade_k =  1.0f;
-    dr.fade_d = -2.0f;
+    gd.fade_k =  1.0f;
+    gd.fade_d = -2.0f;
 
 
     version.x = 0;
     version.y = 0;
 
-    for (i = 0; i < dr.file.dc; i++)
+    for (i = 0; i < gd.file.base.dc; i++)
     {
-        char *k = dr.file.av + dr.file.dv[i].ai;
-        char *v = dr.file.av + dr.file.dv[i].aj;
+        char *k = gd.file.base.av + gd.file.base.dv[i].ai;
+        char *v = gd.file.base.av + gd.file.base.dv[i].aj;
 
         if (strcmp(k, "back") == 0) back_name = v;
         if (strcmp(k, "grad") == 0) grad_name = v;
@@ -433,28 +434,28 @@ int  game_client_init(const char *file_name)
     first_update = 1;
 
     back_init(grad_name);
-    sol_load_gl(&dr.back, back_name, 0);
+    sol_load_full(&gd.back, back_name, 0);
 
-    return dr.state;
+    return gd.state;
 }
 
 void game_client_free(void)
 {
-    if (dr.state)
+    if (gd.state)
     {
         game_proxy_clr();
-        sol_free_gl(&dr.file);
-        sol_free_gl(&dr.back);
+        sol_free_full(&gd.file);
+        sol_free_full(&gd.back);
         back_free();
     }
-    dr.state = 0;
+    gd.state = 0;
 }
 
 /*---------------------------------------------------------------------------*/
 
 void game_client_draw(int pose, float t)
 {
-    game_draw(&dr, pose, t);
+    game_draw(&gd, pose, t);
 }
 
 /*---------------------------------------------------------------------------*/
@@ -479,47 +480,47 @@ int curr_status(void)
 
 void game_look(float phi, float theta)
 {
-    dr.view.c[0] = dr.view.p[0] + fsinf(V_RAD(theta)) * fcosf(V_RAD(phi));
-    dr.view.c[1] = dr.view.p[1] +                       fsinf(V_RAD(phi));
-    dr.view.c[2] = dr.view.p[2] - fcosf(V_RAD(theta)) * fcosf(V_RAD(phi));
+    gd.view.c[0] = gd.view.p[0] + fsinf(V_RAD(theta)) * fcosf(V_RAD(phi));
+    gd.view.c[1] = gd.view.p[1] +                       fsinf(V_RAD(phi));
+    gd.view.c[2] = gd.view.p[2] - fcosf(V_RAD(theta)) * fcosf(V_RAD(phi));
 }
 
 /*---------------------------------------------------------------------------*/
 
 void game_kill_fade(void)
 {
-    dr.fade_k = 0.0f;
-    dr.fade_d = 0.0f;
+    gd.fade_k = 0.0f;
+    gd.fade_d = 0.0f;
 }
 
 void game_step_fade(float dt)
 {
-    if ((dr.fade_k < 1.0f && dr.fade_d > 0.0f) ||
-        (dr.fade_k > 0.0f && dr.fade_d < 0.0f))
-        dr.fade_k += dr.fade_d * dt;
+    if ((gd.fade_k < 1.0f && gd.fade_d > 0.0f) ||
+        (gd.fade_k > 0.0f && gd.fade_d < 0.0f))
+        gd.fade_k += gd.fade_d * dt;
 
-    if (dr.fade_k < 0.0f)
+    if (gd.fade_k < 0.0f)
     {
-        dr.fade_k = 0.0f;
-        dr.fade_d = 0.0f;
+        gd.fade_k = 0.0f;
+        gd.fade_d = 0.0f;
     }
-    if (dr.fade_k > 1.0f)
+    if (gd.fade_k > 1.0f)
     {
-        dr.fade_k = 1.0f;
-        dr.fade_d = 0.0f;
+        gd.fade_k = 1.0f;
+        gd.fade_d = 0.0f;
     }
 }
 
 void game_fade(float d)
 {
-    dr.fade_d = d;
+    gd.fade_d = d;
 }
 
 /*---------------------------------------------------------------------------*/
 
 void game_client_fly(float k)
 {
-    game_view_fly(&dr.view, &dr.file, k);
+    game_view_fly(&gd.view, &gd.file.vary, k);
 }
 
 /*---------------------------------------------------------------------------*/
index b3c64a9..4e28b18 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef GAME_CLIENT_H
 #define GAME_CLIENT_H
 
-#include <stdio.h>
-#include "solid.h"
 #include "fs.h"
 
 /*---------------------------------------------------------------------------*/
index 7675609..5788d73 100644 (file)
@@ -15,7 +15,7 @@
 #include "game_common.h"
 #include "vec3.h"
 #include "config.h"
-#include "solid.h"
+#include "solid_vary.h"
 
 /*---------------------------------------------------------------------------*/
 
@@ -113,7 +113,7 @@ void game_view_init(struct game_view *view)
     view->e[2][2] = 1.0f;
 }
 
-void game_view_fly(struct game_view *view, const struct s_file *fp, float k)
+void game_view_fly(struct game_view *view, const struct s_vary *vary, float k)
 {
     /* float  x[3] = { 1.f, 0.f, 0.f }; */
     float  y[3] = { 0.f, 1.f, 0.f };
@@ -128,10 +128,10 @@ void game_view_fly(struct game_view *view, const struct s_file *fp, float k)
 
     /* k = 0.0 view is at the ball. */
 
-    if (fp->uc > 0)
+    if (vary->uc > 0)
     {
-        v_cpy(c0, fp->uv[0].p);
-        v_cpy(p0, fp->uv[0].p);
+        v_cpy(c0, vary->uv[0].p);
+        v_cpy(p0, vary->uv[0].p);
     }
 
     v_mad(p0, p0, y, view->dp);
@@ -140,18 +140,18 @@ void game_view_fly(struct game_view *view, const struct s_file *fp, float k)
 
     /* k = +1.0 view is s_view 0 */
 
-    if (k >= 0 && fp->wc > 0)
+    if (k >= 0 && vary->base->wc > 0)
     {
-        v_cpy(p1, fp->wv[0].p);
-        v_cpy(c1, fp->wv[0].q);
+        v_cpy(p1, vary->base->wv[0].p);
+        v_cpy(c1, vary->base->wv[0].q);
     }
 
     /* k = -1.0 view is s_view 1 */
 
-    if (k <= 0 && fp->wc > 1)
+    if (k <= 0 && vary->base->wc > 1)
     {
-        v_cpy(p1, fp->wv[1].p);
-        v_cpy(c1, fp->wv[1].q);
+        v_cpy(p1, vary->base->wv[1].p);
+        v_cpy(c1, vary->base->wv[1].q);
     }
 
     /* Interpolate the views. */
index 103d0e8..f958b1e 100644 (file)
@@ -2,7 +2,7 @@
 #define GAME_COMMON_H
 
 #include "lang.h"
-#include "solid.h"
+#include "solid_vary.h"
 
 /*---------------------------------------------------------------------------*/
 
@@ -89,7 +89,7 @@ struct game_view
 };
 
 void game_view_init(struct game_view *);
-void game_view_fly(struct game_view *, const struct s_file *, float);
+void game_view_fly(struct game_view *, const struct s_vary *, float);
 
 /*---------------------------------------------------------------------------*/
 
index 7f00267..f3d8384 100644 (file)
  * General Public License for more details.
  */
 
-#include "solid.h"
 #include "vec3.h"
 #include "glext.h"
 #include "ball.h"
 #include "item.h"
 #include "part.h"
 #include "geom.h"
-#include "solid_gl.h"
 #include "config.h"
 #include "back.h"
 #include "video.h"
 
+#include "solid_draw.h"
+
 #include "game_draw.h"
 
 /*---------------------------------------------------------------------------*/
 
-static void game_draw_balls(const struct s_file *fp,
+static void game_draw_balls(const struct s_vary *vary,
                             const float *bill_M, float t)
 {
     float c[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
@@ -36,18 +36,18 @@ static void game_draw_balls(const struct s_file *fp,
     float ball_M[16];
     float pend_M[16];
 
-    m_basis(ball_M, fp->uv[0].e[0], fp->uv[0].e[1], fp->uv[0].e[2]);
-    m_basis(pend_M, fp->uv[0].E[0], fp->uv[0].E[1], fp->uv[0].E[2]);
+    m_basis(ball_M, vary->uv[0].e[0], vary->uv[0].e[1], vary->uv[0].e[2]);
+    m_basis(pend_M, vary->uv[0].E[0], vary->uv[0].E[1], vary->uv[0].E[2]);
 
     glPushAttrib(GL_LIGHTING_BIT);
     glPushMatrix();
     {
-        glTranslatef(fp->uv[0].p[0],
-                     fp->uv[0].p[1] + BALL_FUDGE,
-                     fp->uv[0].p[2]);
-        glScalef(fp->uv[0].r,
-                 fp->uv[0].r,
-                 fp->uv[0].r);
+        glTranslatef(vary->uv[0].p[0],
+                     vary->uv[0].p[1] + BALL_FUDGE,
+                     vary->uv[0].p[2]);
+        glScalef(vary->uv[0].r,
+                 vary->uv[0].r,
+                 vary->uv[0].r);
 
         glColor4fv(c);
         ball_draw(ball_M, pend_M, bill_M, t);
@@ -56,7 +56,7 @@ static void game_draw_balls(const struct s_file *fp,
     glPopAttrib();
 }
 
-static void game_draw_items(const struct s_file *fp, float t)
+static void game_draw_items(const struct s_vary *vary, float t)
 {
     float r = 360.f * t;
     int hi;
@@ -65,17 +65,17 @@ static void game_draw_items(const struct s_file *fp, float t)
     {
         item_push(ITEM_COIN);
         {
-            for (hi = 0; hi < fp->hc; hi++)
+            for (hi = 0; hi < vary->hc; hi++)
 
-                if (fp->hv[hi].t == ITEM_COIN && fp->hv[hi].n > 0)
+                if (vary->hv[hi].t == ITEM_COIN && vary->hv[hi].n > 0)
                 {
                     glPushMatrix();
                     {
-                        glTranslatef(fp->hv[hi].p[0],
-                                     fp->hv[hi].p[1],
-                                     fp->hv[hi].p[2]);
+                        glTranslatef(vary->hv[hi].p[0],
+                                     vary->hv[hi].p[1],
+                                     vary->hv[hi].p[2]);
                         glRotatef(r, 0.0f, 1.0f, 0.0f);
-                        item_draw(&fp->hv[hi], r);
+                        item_draw(&vary->hv[hi], r);
                     }
                     glPopMatrix();
                 }
@@ -84,17 +84,17 @@ static void game_draw_items(const struct s_file *fp, float t)
 
         item_push(ITEM_SHRINK);
         {
-            for (hi = 0; hi < fp->hc; hi++)
+            for (hi = 0; hi < vary->hc; hi++)
 
-                if (fp->hv[hi].t == ITEM_SHRINK)
+                if (vary->hv[hi].t == ITEM_SHRINK)
                 {
                     glPushMatrix();
                     {
-                        glTranslatef(fp->hv[hi].p[0],
-                                     fp->hv[hi].p[1],
-                                     fp->hv[hi].p[2]);
+                        glTranslatef(vary->hv[hi].p[0],
+                                     vary->hv[hi].p[1],
+                                     vary->hv[hi].p[2]);
                         glRotatef(r, 0.0f, 1.0f, 0.0f);
-                        item_draw(&fp->hv[hi], r);
+                        item_draw(&vary->hv[hi], r);
                     }
                     glPopMatrix();
                 }
@@ -103,17 +103,17 @@ static void game_draw_items(const struct s_file *fp, float t)
 
         item_push(ITEM_GROW);
         {
-            for (hi = 0; hi < fp->hc; hi++)
+            for (hi = 0; hi < vary->hc; hi++)
 
-                if (fp->hv[hi].t == ITEM_GROW)
+                if (vary->hv[hi].t == ITEM_GROW)
                 {
                     glPushMatrix();
                     {
-                        glTranslatef(fp->hv[hi].p[0],
-                                     fp->hv[hi].p[1],
-                                     fp->hv[hi].p[2]);
+                        glTranslatef(vary->hv[hi].p[0],
+                                     vary->hv[hi].p[1],
+                                     vary->hv[hi].p[2]);
                         glRotatef(r, 0.0f, 1.0f, 0.0f);
-                        item_draw(&fp->hv[hi], r);
+                        item_draw(&vary->hv[hi], r);
                     }
                     glPopMatrix();
                 }
@@ -123,11 +123,12 @@ static void game_draw_items(const struct s_file *fp, float t)
     glPopAttrib();
 }
 
-static void game_draw_goals(const struct game_draw *dr,
-                            const struct s_file *fp,
+static void game_draw_goals(const struct game_draw *gd,
                             const float *M, float t)
 {
-    if (dr->goal_e)
+    const struct s_base *base = &gd->file.base;
+
+    if (gd->goal_e)
     {
         int zi;
 
@@ -135,15 +136,15 @@ static void game_draw_goals(const struct game_draw *dr,
 
         glEnable(GL_TEXTURE_2D);
         {
-            for (zi = 0; zi < fp->zc; zi++)
+            for (zi = 0; zi < base->zc; zi++)
             {
                 glPushMatrix();
                 {
-                    glTranslatef(fp->zv[zi].p[0],
-                                 fp->zv[zi].p[1],
-                                 fp->zv[zi].p[2]);
+                    glTranslatef(base->zv[zi].p[0],
+                                 base->zv[zi].p[1],
+                                 base->zv[zi].p[2]);
 
-                    part_draw_goal(M, fp->zv[zi].r, dr->goal_k, t);
+                    part_draw_goal(M, base->zv[zi].r, gd->goal_k, t);
                 }
                 glPopMatrix();
             }
@@ -152,17 +153,17 @@ static void game_draw_goals(const struct game_draw *dr,
 
         /* Draw the goal column. */
 
-        for (zi = 0; zi < fp->zc; zi++)
+        for (zi = 0; zi < base->zc; zi++)
         {
             glPushMatrix();
             {
-                glTranslatef(fp->zv[zi].p[0],
-                             fp->zv[zi].p[1],
-                             fp->zv[zi].p[2]);
+                glTranslatef(base->zv[zi].p[0],
+                             base->zv[zi].p[1],
+                             base->zv[zi].p[2]);
 
-                glScalef(fp->zv[zi].r,
-                         dr->goal_k,
-                         fp->zv[zi].r);
+                glScalef(base->zv[zi].r,
+                         gd->goal_k,
+                         base->zv[zi].r);
 
                 goal_draw();
             }
@@ -171,65 +172,68 @@ static void game_draw_goals(const struct game_draw *dr,
     }
 }
 
-static void game_draw_jumps(const struct game_draw *dr,
-                            const struct s_file *fp,
+static void game_draw_jumps(const struct game_draw *gd,
                             const float *M, float t)
 {
+    const struct s_base *base = &gd->file.base;
+
     int ji;
 
     glEnable(GL_TEXTURE_2D);
     {
-        for (ji = 0; ji < fp->jc; ji++)
+        for (ji = 0; ji < base->jc; ji++)
         {
             glPushMatrix();
             {
-                glTranslatef(fp->jv[ji].p[0],
-                             fp->jv[ji].p[1],
-                             fp->jv[ji].p[2]);
+                glTranslatef(base->jv[ji].p[0],
+                             base->jv[ji].p[1],
+                             base->jv[ji].p[2]);
 
-                part_draw_jump(M, fp->jv[ji].r, 1.0f, t);
+                part_draw_jump(M, base->jv[ji].r, 1.0f, t);
             }
             glPopMatrix();
         }
     }
     glDisable(GL_TEXTURE_2D);
 
-    for (ji = 0; ji < fp->jc; ji++)
+    for (ji = 0; ji < base->jc; ji++)
     {
         glPushMatrix();
         {
-            glTranslatef(fp->jv[ji].p[0],
-                         fp->jv[ji].p[1],
-                         fp->jv[ji].p[2]);
-            glScalef(fp->jv[ji].r,
+            glTranslatef(base->jv[ji].p[0],
+                         base->jv[ji].p[1],
+                         base->jv[ji].p[2]);
+            glScalef(base->jv[ji].r,
                      1.0f,
-                     fp->jv[ji].r);
+                     base->jv[ji].r);
 
-            jump_draw(!dr->jump_e);
+            jump_draw(!gd->jump_e);
         }
         glPopMatrix();
     }
 }
 
-static void game_draw_swchs(const struct s_file *fp)
+static void game_draw_swchs(const struct s_vary *vary)
 {
     int xi;
 
-    for (xi = 0; xi < fp->xc; xi++)
+    for (xi = 0; xi < vary->xc; xi++)
     {
-        if (fp->xv[xi].i)
+        struct v_swch *xp = vary->xv + xi;
+
+        if (xp->base->i)
             continue;
 
         glPushMatrix();
         {
-            glTranslatef(fp->xv[xi].p[0],
-                         fp->xv[xi].p[1],
-                         fp->xv[xi].p[2]);
-            glScalef(fp->xv[xi].r,
+            glTranslatef(xp->base->p[0],
+                         xp->base->p[1],
+                         xp->base->p[2]);
+            glScalef(xp->base->r,
                      1.0f,
-                     fp->xv[xi].r);
+                     xp->base->r);
 
-            swch_draw(fp->xv[xi].f, fp->xv[xi].e);
+            swch_draw(xp->f, xp->e);
         }
         glPopMatrix();
     }
@@ -237,10 +241,10 @@ static void game_draw_swchs(const struct s_file *fp)
 
 /*---------------------------------------------------------------------------*/
 
-static void game_draw_tilt(const struct game_draw *dr, int d)
+static void game_draw_tilt(const struct game_draw *gd, int d)
 {
-    const struct game_tilt *tilt = &dr->tilt;
-    const float *ball_p = dr->file.uv->p;
+    const struct game_tilt *tilt = &gd->tilt;
+    const float *ball_p = gd->file.vary.uv[0].p;
 
     /* Rotate the environment about the position of the ball. */
 
@@ -250,15 +254,15 @@ static void game_draw_tilt(const struct game_draw *dr, int d)
     glTranslatef(-ball_p[0], -ball_p[1] * d, -ball_p[2]);
 }
 
-static void game_refl_all(const struct game_draw *dr)
+static void game_refl_all(const struct game_draw *gd)
 {
     glPushMatrix();
     {
-        game_draw_tilt(dr, 1);
+        game_draw_tilt(gd, 1);
 
         /* Draw the floor. */
 
-        sol_refl(&dr->file);
+        sol_refl(&gd->file.draw);
     }
     glPopMatrix();
 }
@@ -289,30 +293,32 @@ static void game_draw_light(void)
     glLightfv(GL_LIGHT1, GL_SPECULAR, light_c[1]);
 }
 
-static void game_draw_back(const struct game_draw *dr, int pose, int d, float t)
+static void game_draw_back(const struct game_draw *gd, int pose, int d, float t)
 {
     if (pose == POSE_BALL)
         return;
 
     glPushMatrix();
     {
+        const struct game_view *view = &gd->view;
+
         if (d < 0)
         {
-            const struct game_tilt *tilt = &dr->tilt;
+            const struct game_tilt *tilt = &gd->tilt;
 
             glRotatef(tilt->rz * 2, tilt->z[0], tilt->z[1], tilt->z[2]);
             glRotatef(tilt->rx * 2, tilt->x[0], tilt->x[1], tilt->x[2]);
         }
 
-        glTranslatef(dr->view.p[0], dr->view.p[1] * d, dr->view.p[2]);
+        glTranslatef(view->p[0], view->p[1] * d, view->p[2]);
 
         if (config_get_d(CONFIG_BACKGROUND))
         {
             /* Draw all background layers back to front. */
 
-            sol_back(&dr->back, BACK_DIST, FAR_DIST,  t);
+            sol_back(&gd->back.draw, BACK_DIST, FAR_DIST,  t);
             back_draw(0);
-            sol_back(&dr->back,         0, BACK_DIST, t);
+            sol_back(&gd->back.draw,         0, BACK_DIST, t);
         }
         else back_draw(0);
     }
@@ -333,7 +339,7 @@ static void game_clip_refl(int d)
     glClipPlane(GL_CLIP_PLANE0, e);
 }
 
-static void game_clip_ball(const struct game_draw *dr, int d, const float *p)
+static void game_clip_ball(const struct game_draw *gd, int d, const float *p)
 {
     GLdouble r, c[3], pz[4], nz[4];
 
@@ -343,9 +349,9 @@ static void game_clip_ball(const struct game_draw *dr, int d, const float *p)
     c[1] = p[1] * d;
     c[2] = p[2];
 
-    pz[0] = dr->view.p[0] - c[0];
-    pz[1] = dr->view.p[1] - c[1];
-    pz[2] = dr->view.p[2] - c[2];
+    pz[0] = gd->view.p[0] - c[0];
+    pz[1] = gd->view.p[1] - c[1];
+    pz[2] = gd->view.p[2] - c[2];
 
     r = sqrt(pz[0] * pz[0] + pz[1] * pz[1] + pz[2] * pz[2]);
 
@@ -372,25 +378,25 @@ static void game_clip_ball(const struct game_draw *dr, int d, const float *p)
     glClipPlane(GL_CLIP_PLANE2, pz);
 }
 
-static void game_draw_fore(const struct game_draw *dr,
+static void game_draw_fore(const struct game_draw *gd,
                            int pose, const float *M,
                            int d, float t)
 {
-    const float *ball_p = dr->file.uv->p;
-    const float  ball_r = dr->file.uv->r;
+    const float *ball_p = gd->file.vary.uv[0].p;
+    const float  ball_r = gd->file.vary.uv[0].r;
 
-    const struct s_file *fp = &dr->file;
+    const struct s_draw *draw = &gd->file.draw;
 
     glPushMatrix();
     {
         /* Rotate the environment about the position of the ball. */
 
-        game_draw_tilt(dr, d);
+        game_draw_tilt(gd, d);
 
         /* Compute clipping planes for reflection and ball facing. */
 
         game_clip_refl(d);
-        game_clip_ball(dr, d, ball_p);
+        game_clip_ball(gd, d, ball_p);
 
         if (d < 0)
             glEnable(GL_CLIP_PLANE0);
@@ -398,17 +404,17 @@ static void game_draw_fore(const struct game_draw *dr,
         switch (pose)
         {
         case POSE_LEVEL:
-            sol_draw(fp, 0, 1);
+            sol_draw(draw, 0, 1);
             break;
 
         case POSE_NONE:
             /* Draw the coins. */
 
-            game_draw_items(fp, t);
+            game_draw_items(draw->vary, t);
 
             /* Draw the floor. */
 
-            sol_draw(fp, 0, 1);
+            sol_draw(draw, 0, 1);
 
             /* Fall through. */
 
@@ -419,13 +425,13 @@ static void game_draw_fore(const struct game_draw *dr,
             if (d > 0 && config_get_d(CONFIG_SHADOW))
             {
                 shad_draw_set(ball_p, ball_r);
-                sol_shad(fp);
+                sol_shad(draw);
                 shad_draw_clr();
             }
 
             /* Draw the ball. */
 
-            game_draw_balls(fp, M, t);
+            game_draw_balls(draw->vary, M, t);
 
             break;
         }
@@ -438,14 +444,14 @@ static void game_draw_fore(const struct game_draw *dr,
         {
             glColor3f(1.0f, 1.0f, 1.0f);
 
-            sol_bill(fp, M, t);
+            sol_bill(draw, M, t);
             part_draw_coin(M, t);
 
             glDisable(GL_TEXTURE_2D);
             {
-                game_draw_goals(dr, fp, M, t);
-                game_draw_jumps(dr, fp, M, t);
-                game_draw_swchs(fp);
+                game_draw_goals(gd, M, t);
+                game_draw_jumps(gd, M, t);
+                game_draw_swchs(draw->vary);
             }
             glEnable(GL_TEXTURE_2D);
 
@@ -463,15 +469,15 @@ static void game_draw_fore(const struct game_draw *dr,
 
 /*---------------------------------------------------------------------------*/
 
-void game_draw(const struct game_draw *dr, int pose, float t)
+void game_draw(const struct game_draw *gd, int pose, float t)
 {
     float fov = (float) config_get_d(CONFIG_VIEW_FOV);
 
-    if (dr->jump_b) fov *= 2.f * fabsf(dr->jump_dt - 0.5);
+    if (gd->jump_b) fov *= 2.f * fabsf(gd->jump_dt - 0.5);
 
-    if (dr->state)
+    if (gd->state)
     {
-        const struct game_view *view = &dr->view;
+        const struct game_view *view = &gd->view;
 
         video_push_persp(fov, 0.1f, FAR_DIST);
         glPushMatrix();
@@ -498,7 +504,7 @@ void game_draw(const struct game_draw *dr, int pose, float t)
             glMultMatrixf(M);
             glTranslatef(-view->c[0], -view->c[1], -view->c[2]);
 
-            if (dr->reflective && config_get_d(CONFIG_REFLECTION))
+            if (gd->reflective && config_get_d(CONFIG_REFLECTION))
             {
                 glEnable(GL_STENCIL_TEST);
                 {
@@ -509,7 +515,7 @@ void game_draw(const struct game_draw *dr, int pose, float t)
                     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
                     glDepthMask(GL_FALSE);
 
-                    game_refl_all(dr);
+                    game_refl_all(gd);
 
                     glDepthMask(GL_TRUE);
                     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@@ -524,8 +530,8 @@ void game_draw(const struct game_draw *dr, int pose, float t)
                         glScalef(+1.0f, -1.0f, +1.0f);
 
                         game_draw_light();
-                        game_draw_back(dr, pose,    -1, t);
-                        game_draw_fore(dr, pose, U, -1, t);
+                        game_draw_back(gd, pose,    -1, t);
+                        game_draw_fore(gd, pose, U, -1, t);
                     }
                     glPopMatrix();
                     glFrontFace(GL_CCW);
@@ -537,7 +543,7 @@ void game_draw(const struct game_draw *dr, int pose, float t)
 
             game_draw_light();
 
-            if (dr->reflective)
+            if (gd->reflective)
             {
                 if (config_get_d(CONFIG_REFLECTION))
                 {
@@ -546,19 +552,19 @@ void game_draw(const struct game_draw *dr, int pose, float t)
                     glEnable(GL_STENCIL_TEST);
                     {
                         glStencilFunc(GL_NOTEQUAL, 1, 0xFFFFFFFF);
-                        game_draw_back(dr, pose, +1, t);
+                        game_draw_back(gd, pose, +1, t);
                     }
                     glDisable(GL_STENCIL_TEST);
 
                     /* Draw mirrors. */
 
-                    game_refl_all(dr);
+                    game_refl_all(gd);
                 }
                 else
                 {
                     /* Draw background. */
 
-                    game_draw_back(dr, pose, +1, t);
+                    game_draw_back(gd, pose, +1, t);
 
                     /*
                      * Draw mirrors, first fully opaque with a custom
@@ -571,28 +577,28 @@ void game_draw(const struct game_draw *dr, int pose, float t)
                     glEnable(GL_COLOR_MATERIAL);
                     {
                         glColor4f(0.0, 0.0, 0.05, 1.0);
-                        game_refl_all(dr);
+                        game_refl_all(gd);
                         glColor4f(1.0,  1.0,  1.0,  1.0);
                     }
                     glDisable(GL_COLOR_MATERIAL);
 
-                    game_refl_all(dr);
+                    game_refl_all(gd);
                 }
             }
             else
             {
-                game_draw_back(dr, pose, +1, t);
-                game_refl_all(dr);
+                game_draw_back(gd, pose, +1, t);
+                game_refl_all(gd);
             }
 
-            game_draw_fore(dr, pose, T, +1, t);
+            game_draw_fore(gd, pose, T, +1, t);
         }
         glPopMatrix();
         video_pop_matrix();
 
         /* Draw the fade overlay. */
 
-        fade_draw(dr->fade_k);
+        fade_draw(gd->fade_k);
     }
 }
 
index bb4930d..5228e1a 100644 (file)
@@ -1,15 +1,15 @@
 #ifndef GAME_DRAW_H
 #define GAME_DRAW_H
 
-#include "solid.h"
+#include "solid_draw.h"
 #include "game_common.h"
 
 struct game_draw
 {
     int state;
 
-    struct s_file file;
-    struct s_file back;
+    struct s_full file;
+    struct s_full back;
 
     int reflective;                     /* Reflective geometry used?         */
 
index 8fa65fe..0d7b1ab 100644 (file)
@@ -36,7 +36,8 @@
 
 static int server_state = 0;
 
-static struct s_file file;
+static struct s_base base;
+static struct s_vary file;
 
 static float timer      = 0.f;          /* Clock time                        */
 static int   timer_down = 1;            /* Timer go up or down?              */
@@ -322,11 +323,11 @@ static int   got_orig = 0;              /* Do we know original ball size?    */
 
 static int   grow_state = 0;            /* Current state (values -1, 0, +1)  */
 
-static void grow_init(const struct s_file *fp, int type)
+static void grow_init(const struct s_vary *vary, int type)
 {
     if (!got_orig)
     {
-        grow_orig  = fp->uv->r;
+        grow_orig  = vary->uv->r;
         grow_goal  = grow_orig;
         grow_strt  = grow_orig;
 
@@ -383,11 +384,11 @@ static void grow_init(const struct s_file *fp, int type)
     if (grow)
     {
         grow_t = 0.0;
-        grow_strt = fp->uv->r;
+        grow_strt = vary->uv->r;
     }
 }
 
-static void grow_step(const struct s_file *fp, float dt)
+static void grow_step(const struct s_vary *vary, float dt)
 {
     float dr;
 
@@ -408,8 +409,8 @@ static void grow_step(const struct s_file *fp, float dt)
 
     /* No sinking through the floor! Keeps ball's bottom constant. */
 
-    fp->uv->p[1] += (dr - fp->uv->r);
-    fp->uv->r     =  dr;
+    vary->uv->p[1] += (dr - vary->uv->r);
+    vary->uv->r     =  dr;
 
     game_cmd_ballradius();
 }
@@ -435,7 +436,10 @@ int game_server_init(const char *file_name, int t, int e)
     if (server_state)
         game_server_free();
 
-    if (!sol_load_only_file(&file, file_name))
+    if (!sol_load_base(&base, file_name))
+        return (server_state = 0);
+
+    if (!sol_load_vary(&file, &base))
         return (server_state = 0);
 
     server_state = 1;
@@ -443,10 +447,10 @@ int game_server_init(const char *file_name, int t, int e)
     version.x = 0;
     version.y = 0;
 
-    for (i = 0; i < file.dc; i++)
+    for (i = 0; i < file.base->dc; i++)
     {
-        char *k = file.av + file.dv[i].ai;
-        char *v = file.av + file.dv[i].aj;
+        char *k = file.base->av + file.base->dv[i].ai;
+        char *v = file.base->av + file.base->dv[i].aj;
 
         if (strcmp(k, "version") == 0)
             sscanf(v, "%d.%d", &version.x, &version.y);
@@ -512,7 +516,7 @@ void game_server_free(void)
     if (server_state)
     {
         sol_quit_sim();
-        sol_free(&file);
+        sol_free_vary(&file);
         server_state = 0;
     }
 }
@@ -622,21 +626,21 @@ static void game_update_time(float dt, int b)
 
 static int game_update_state(int bt)
 {
-    struct s_file *fp = &file;
-    struct s_goal *zp;
+    struct s_vary *vary = &file;
+    struct b_goal *zp;
     int hi;
 
     float p[3];
 
     /* Test for an item. */
 
-    if (bt && (hi = sol_item_test(fp, p, ITEM_RADIUS)) != -1)
+    if (bt && (hi = sol_item_test(vary, p, ITEM_RADIUS)) != -1)
     {
-        struct s_item *hp = &file.hv[hi];
+        struct v_item *hp = file.hv + hi;
 
         game_cmd_pkitem(hi);
 
-        grow_init(fp, hp->t);
+        grow_init(vary, hp->t);
 
         if (hp->t == ITEM_COIN)
         {
@@ -653,26 +657,26 @@ static int game_update_state(int bt)
 
     /* Test for a switch. */
 
-    if (sol_swch_test(fp, 0) == SWCH_TRIGGER)
+    if (sol_swch_test(vary, 0) == SWCH_TRIGGER)
         audio_play(AUD_SWITCH, 1.f);
 
     /* Test for a jump. */
 
-    if (jump_e == 1 && jump_b == 0 && (sol_jump_test(fp, jump_p, 0) ==
+    if (jump_e == 1 && jump_b == 0 && (sol_jump_test(vary, jump_p, 0) ==
                                        JUMP_TRIGGER))
     {
         jump_b  = 1;
         jump_e  = 0;
         jump_dt = 0.f;
 
-        v_sub(jump_w, jump_p, fp->uv->p);
+        v_sub(jump_w, jump_p, vary->uv->p);
         v_add(jump_w, view.p, jump_w);
 
         audio_play(AUD_JUMP, 1.f);
 
         game_cmd_jump(1);
     }
-    if (jump_e == 0 && jump_b == 0 && (sol_jump_test(fp, jump_p, 0) ==
+    if (jump_e == 0 && jump_b == 0 && (sol_jump_test(vary, jump_p, 0) ==
                                        JUMP_OUTSIDE))
     {
         jump_e = 1;
@@ -681,7 +685,7 @@ static int game_update_state(int bt)
 
     /* Test for a goal. */
 
-    if (bt && goal_e && (zp = sol_goal_test(fp, p, 0)))
+    if (bt && goal_e && (zp = sol_goal_test(vary, p, 0)))
     {
         audio_play(AUD_GOAL, 1.0f);
         return GAME_GOAL;
@@ -697,7 +701,7 @@ static int game_update_state(int bt)
 
     /* Test for fall-out. */
 
-    if (bt && fp->uv[0].p[1] < fp->vv[0].p[1])
+    if (bt && vary->uv[0].p[1] < vary->base->vv[0].p[1])
     {
         audio_play(AUD_FALL, 1.0f);
         return GAME_FALL;
@@ -710,7 +714,7 @@ static int game_step(const float g[3], float dt, int bt)
 {
     if (server_state)
     {
-        struct s_file *fp = &file;
+        struct s_vary *vary = &file;
 
         float h[3];
 
@@ -724,7 +728,7 @@ static int game_step(const float g[3], float dt, int bt)
         game_cmd_tiltaxes();
         game_cmd_tiltangles();
 
-        grow_step(fp, dt);
+        grow_step(vary, dt);
 
         game_tilt_grav(h, g, &tilt);
 
@@ -736,8 +740,8 @@ static int game_step(const float g[3], float dt, int bt)
 
             if (0.5f < jump_dt)
             {
-                v_cpy(fp->uv->p, jump_p);
-                v_cpy(view.p,    jump_w);
+                v_cpy(vary->uv->p, jump_p);
+                v_cpy(view.p,      jump_w);
             }
             if (1.0f < jump_dt)
                 jump_b = 0;
@@ -746,7 +750,7 @@ static int game_step(const float g[3], float dt, int bt)
         {
             /* Run the sim. */
 
-            float b = sol_step(fp, h, dt, 0, NULL);
+            float b = sol_step(vary, h, dt, 0, NULL);
 
             /* Mix the sound of a ball bounce. */
 
@@ -756,9 +760,9 @@ static int game_step(const float g[3], float dt, int bt)
 
                 if (got_orig)
                 {
-                    if      (fp->uv->r > grow_orig) audio_play(AUD_BUMPL, k);
-                    else if (fp->uv->r < grow_orig) audio_play(AUD_BUMPS, k);
-                    else                            audio_play(AUD_BUMPM, k);
+                    if      (vary->uv->r > grow_orig) audio_play(AUD_BUMPL, k);
+                    else if (vary->uv->r < grow_orig) audio_play(AUD_BUMPS, k);
+                    else                              audio_play(AUD_BUMPM, k);
                 }
                 else audio_play(AUD_BUMPM, k);
             }
index d069c95..07137b1 100644 (file)
@@ -1,9 +1,6 @@
 #ifndef GAME_SERVER_H
 #define GAME_SERVER_H
 
-#include "solid.h"
-#include "fs.h"
-
 /*---------------------------------------------------------------------------*/
 
 #define RESPONSE    0.05f              /* Input smoothing time               */
index 6026620..ac733ca 100644 (file)
 #include <math.h>
 #include <assert.h>
 
+#include "solid_base.h"
+
 #include "common.h"
-#include "solid.h"
 #include "config.h"
 #include "level.h"
 #include "set.h"
 
 /*---------------------------------------------------------------------------*/
 
-static void scan_level_attribs(struct level *l, const struct s_file *fp)
+static void scan_level_attribs(struct level *l, const struct s_base *base)
 {
     int i;
 
@@ -37,10 +38,10 @@ static void scan_level_attribs(struct level *l, const struct s_file *fp)
     int need_goal_easy = 0;
     int need_coin_easy = 0;
 
-    for (i = 0; i < fp->dc; i++)
+    for (i = 0; i < base->dc; i++)
     {
-        char *k = fp->av + fp->dv[i].ai;
-        char *v = fp->av + fp->dv[i].aj;
+        char *k = base->av + base->dv[i].ai;
+        char *v = base->av + base->dv[i].aj;
 
         if (strcmp(k, "message") == 0)
             SAFECPY(l->message, v);
@@ -124,12 +125,12 @@ static void scan_level_attribs(struct level *l, const struct s_file *fp)
 
 int level_load(const char *filename, struct level *level)
 {
-    struct s_file sol;
+    struct s_base base;
 
     memset(level, 0, sizeof (struct level));
-    memset(&sol,  0, sizeof (sol));
+    memset(&base, 0, sizeof (base));
 
-    if (!sol_load_only_head(&sol, filename))
+    if (!sol_load_meta(&base, filename))
     {
         fprintf(stderr, L_("Failure to load level file '%s'\n"), filename);
         return 0;
@@ -142,9 +143,9 @@ int level_load(const char *filename, struct level *level)
     score_init_hs(&level->scores[SCORE_GOAL], 59999, 0);
     score_init_hs(&level->scores[SCORE_COIN], 59999, 0);
 
-    scan_level_attribs(level, &sol);
+    scan_level_attribs(level, &base);
 
-    sol_free(&sol);
+    sol_free_base(&base);
 
     return 1;
 }
index dbe331d..cb13b1f 100644 (file)
@@ -20,7 +20,6 @@
 #include "demo.h"
 #include "progress.h"
 #include "audio.h"
-#include "solid.h"
 #include "config.h"
 #include "util.h"
 #include "common.h"
index 44d1537..746edbb 100644 (file)
 #include "config.h"
 #include "video.h"
 
-#include "solid_gl.h"
+#include "solid_draw.h"
 #include "solid_sim.h"
 #include "solid_all.h"
 
 /*---------------------------------------------------------------------------*/
 
-static struct s_file file;
+static struct s_full file;
 static int           ball;
 
 static float view_a;                    /* Ideal view rotation about Y axis  */
@@ -94,13 +94,13 @@ void game_init(const char *s)
     idle_t = 1.0f;
 
     view_init();
-    sol_load_gl(&file, s, config_get_d(CONFIG_SHADOW));
-    sol_init_sim(&file);
+    sol_load_full(&file, s, config_get_d(CONFIG_SHADOW));
+    sol_init_sim(&file.vary);
 
-    for (i = 0; i < file.dc; i++)
+    for (i = 0; i < file.base.dc; i++)
     {
-        const char *k = file.av + file.dv[i].ai;
-        const char *v = file.av + file.dv[i].aj;
+        const char *k = file.base.av + file.base.dv[i].ai;
+        const char *v = file.base.av + file.base.dv[i].aj;
 
         if (strcmp(k, "idle") == 0)
         {
@@ -115,12 +115,12 @@ void game_init(const char *s)
 void game_free(void)
 {
     sol_quit_sim();
-    sol_free_gl(&file);
+    sol_free_full(&file);
 }
 
 /*---------------------------------------------------------------------------*/
 
-static void game_draw_vect_prim(const struct s_file *fp, GLenum mode)
+static void game_draw_vect_prim(const struct s_vary *fp, GLenum mode)
 {
     float p[3];
     float x[3];
@@ -153,7 +153,7 @@ static void game_draw_vect_prim(const struct s_file *fp, GLenum mode)
     glEnd();
 }
 
-static void game_draw_vect(const struct s_file *fp)
+static void game_draw_vect(const struct s_vary *fp)
 {
     if (view_m > 0.f)
     {
@@ -180,7 +180,7 @@ static void game_draw_vect(const struct s_file *fp)
     }
 }
 
-static void game_draw_balls(const struct s_file *fp,
+static void game_draw_balls(const struct s_vary *fp,
                             const float *bill_M, float t)
 {
     static const GLfloat color[5][4] = {
@@ -242,7 +242,7 @@ static void game_draw_balls(const struct s_file *fp,
     glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
 }
 
-static void game_draw_goals(const struct s_file *fp)
+static void game_draw_goals(const struct s_base *fp)
 {
     int zi;
 
@@ -259,7 +259,7 @@ static void game_draw_goals(const struct s_file *fp)
     }
 }
 
-static void game_draw_jumps(const struct s_file *fp)
+static void game_draw_jumps(const struct s_base *fp)
 {
     int ji;
 
@@ -278,23 +278,25 @@ static void game_draw_jumps(const struct s_file *fp)
     }
 }
 
-static void game_draw_swchs(const struct s_file *fp)
+static void game_draw_swchs(const struct s_vary *fp)
 {
     int xi;
 
     for (xi = 0; xi < fp->xc; xi++)
     {
-        if (fp->xv[xi].i)
+        struct v_swch *xp = fp->xv + xi;
+
+        if (xp->base->i)
             continue;
 
         glPushMatrix();
         {
-            glTranslatef(fp->xv[xi].p[0],
-                         fp->xv[xi].p[1],
-                         fp->xv[xi].p[2]);
+            glTranslatef(xp->base->p[0],
+                         xp->base->p[1],
+                         xp->base->p[2]);
 
-            glScalef(fp->xv[xi].r, 1.f, fp->xv[xi].r);
-            swch_draw(fp->xv[xi].f, fp->xv[xi].e);
+            glScalef(xp->base->r, 1.f, xp->base->r);
+            swch_draw(xp->f, xp->e);
         }
         glPopMatrix();
     }
@@ -311,7 +313,7 @@ void game_draw(int pose, float t)
 
     const float light_p[4] = { 8.f, 32.f, 8.f, 0.f };
 
-    const struct s_file *fp = &file;
+    const struct s_draw *fp = &file.draw;
 
     float fov = FOV;
 
@@ -353,7 +355,7 @@ void game_draw(int pose, float t)
 
         if (config_get_d(CONFIG_SHADOW) && !pose)
         {
-            shad_draw_set(fp->uv[ball].p, fp->uv[ball].r);
+            shad_draw_set(fp->vary->uv[ball].p, fp->vary->uv[ball].r);
             sol_shad(fp);
             shad_draw_clr();
         }
@@ -365,8 +367,8 @@ void game_draw(int pose, float t)
 
         if (pose == 0)
         {
-            game_draw_balls(fp, T, t);
-            game_draw_vect(fp);
+            game_draw_balls(fp->vary, T, t);
+            game_draw_vect(fp->vary);
         }
 
         glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,   a);
@@ -374,15 +376,15 @@ void game_draw(int pose, float t)
         glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION,  e);
         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, h);
 
-        game_draw_goals(fp);
+        game_draw_goals(fp->base);
 
         glEnable(GL_COLOR_MATERIAL);
         glDisable(GL_LIGHTING);
         glDisable(GL_TEXTURE_2D);
         glDepthMask(GL_FALSE);
         {
-            game_draw_jumps(fp);
-            game_draw_swchs(fp);
+            game_draw_jumps(fp->base);
+            game_draw_swchs(fp->vary);
         }
         glDepthMask(GL_TRUE);
         glEnable(GL_TEXTURE_2D);
@@ -409,8 +411,8 @@ void game_update_view(float dt)
 
     /* Center the view about the ball. */
 
-    v_cpy(view_c, file.uv[ball].p);
-    v_inv(view_v, file.uv[ball].v);
+    v_cpy(view_c, file.vary.uv[ball].p);
+    v_inv(view_v, file.vary.uv[ball].v);
 
     switch (config_get_d(CONFIG_CAMERA))
     {
@@ -467,7 +469,7 @@ static int game_update_state(float dt)
 {
     static float t = 0.f;
 
-    struct s_file *fp = &file;
+    struct s_vary *fp = &file.vary;
     float p[3];
 
     if (dt > 0.f)
@@ -536,7 +538,7 @@ static int game_update_state(float dt)
 
 int game_step(const float g[3], float dt)
 {
-    struct s_file *fp = &file;
+    struct s_vary *fp = &file.vary;
 
     static float s = 0.f;
     static float t = 0.f;
@@ -602,9 +604,9 @@ void game_putt(void)
      * friction too early and stopping the ball prematurely.
      */
 
-    file.uv[ball].v[0] = -4.f * view_e[2][0] * view_m;
-    file.uv[ball].v[1] = -4.f * view_e[2][1] * view_m + BALL_FUDGE;
-    file.uv[ball].v[2] = -4.f * view_e[2][2] * view_m;
+    file.vary.uv[ball].v[0] = -4.f * view_e[2][0] * view_m;
+    file.vary.uv[ball].v[1] = -4.f * view_e[2][1] * view_m + BALL_FUDGE;
+    file.vary.uv[ball].v[2] = -4.f * view_e[2][2] * view_m;
 
     view_m = 0.f;
 }
@@ -631,7 +633,7 @@ void game_set_mag(int d)
 
 void game_set_fly(float k)
 {
-    struct s_file *fp = &file;
+    struct s_vary *fp = &file.vary;
 
     float  x[3] = { 1.f, 0.f, 0.f };
     float  y[3] = { 0.f, 1.f, 0.f };
@@ -644,7 +646,7 @@ void game_set_fly(float k)
 
     v_cpy(view_e[0], x);
     v_cpy(view_e[1], y);
-    v_sub(view_e[2], fp->uv[ball].p, fp->zv[0].p);
+    v_sub(view_e[2], fp->uv[ball].p, fp->base->zv[0].p);
 
     if (fabs(v_dot(view_e[1], view_e[2])) > 0.999)
         v_cpy(view_e[2], z);
@@ -668,18 +670,18 @@ void game_set_fly(float k)
 
     /* k = +1.0 view is s_view 0 */
 
-    if (k >= 0 && fp->wc > 0)
+    if (k >= 0 && fp->base->wc > 0)
     {
-        v_cpy(p1, fp->wv[0].p);
-        v_cpy(c1, fp->wv[0].q);
+        v_cpy(p1, fp->base->wv[0].p);
+        v_cpy(c1, fp->base->wv[0].q);
     }
 
     /* k = -1.0 view is s_view 1 */
 
-    if (k <= 0 && fp->wc > 1)
+    if (k <= 0 && fp->base->wc > 1)
     {
-        v_cpy(p1, fp->wv[1].p);
-        v_cpy(c1, fp->wv[1].q);
+        v_cpy(p1, fp->base->wv[1].p);
+        v_cpy(c1, fp->base->wv[1].q);
     }
 
     /* Interpolate the views. */
@@ -710,32 +712,32 @@ void game_ball(int i)
     jump_e = 1;
     jump_b = 0;
 
-    for (ui = 0; ui < file.uc; ui++)
+    for (ui = 0; ui < file.vary.uc; ui++)
     {
-        file.uv[ui].v[0] = 0.f;
-        file.uv[ui].v[1] = 0.f;
-        file.uv[ui].v[2] = 0.f;
+        file.vary.uv[ui].v[0] = 0.f;
+        file.vary.uv[ui].v[1] = 0.f;
+        file.vary.uv[ui].v[2] = 0.f;
 
-        file.uv[ui].w[0] = 0.f;
-        file.uv[ui].w[1] = 0.f;
-        file.uv[ui].w[2] = 0.f;
+        file.vary.uv[ui].w[0] = 0.f;
+        file.vary.uv[ui].w[1] = 0.f;
+        file.vary.uv[ui].w[2] = 0.f;
     }
 }
 
 void game_get_pos(float p[3], float e[3][3])
 {
-    v_cpy(p,    file.uv[ball].p);
-    v_cpy(e[0], file.uv[ball].e[0]);
-    v_cpy(e[1], file.uv[ball].e[1]);
-    v_cpy(e[2], file.uv[ball].e[2]);
+    v_cpy(p,    file.vary.uv[ball].p);
+    v_cpy(e[0], file.vary.uv[ball].e[0]);
+    v_cpy(e[1], file.vary.uv[ball].e[1]);
+    v_cpy(e[2], file.vary.uv[ball].e[2]);
 }
 
 void game_set_pos(float p[3], float e[3][3])
 {
-    v_cpy(file.uv[ball].p,    p);
-    v_cpy(file.uv[ball].e[0], e[0]);
-    v_cpy(file.uv[ball].e[1], e[1]);
-    v_cpy(file.uv[ball].e[2], e[2]);
+    v_cpy(file.vary.uv[ball].p,    p);
+    v_cpy(file.vary.uv[ball].e[0], e[0]);
+    v_cpy(file.vary.uv[ball].e[1], e[1]);
+    v_cpy(file.vary.uv[ball].e[2], e[2]);
 }
 
 /*---------------------------------------------------------------------------*/
index de26f07..b70ce25 100644 (file)
 #include "vec3.h"
 #include "glext.h"
 #include "config.h"
-#include "solid_gl.h"
 #include "common.h"
 
+#include "solid_draw.h"
+
 /*---------------------------------------------------------------------------*/
 
 static int has_solid = 0;
 static int has_inner = 0;
 static int has_outer = 0;
 
-static struct s_file solid;
-static struct s_file inner;
-static struct s_file outer;
+static struct s_full solid;
+static struct s_full inner;
+static struct s_full outer;
 
 #define F_PENDULUM   1
 #define F_DRAWBACK   2
@@ -49,15 +50,15 @@ static float outer_alpha;
 
 #define SET(B, v, b) ((v) ? ((B) | (b)) : ((B) & ~(b)))
 
-static int ball_opts(const struct s_file *fp, float *alpha)
+static int ball_opts(const struct s_base *base, float *alpha)
 {
     int flags = F_DEPTHTEST;
     int di;
 
-    for (di = 0; di < fp->dc; ++di)
+    for (di = 0; di < base->dc; ++di)
     {
-        char *k = fp->av + fp->dv[di].ai;
-        char *v = fp->av + fp->dv[di].aj;
+        char *k = base->av + base->dv[di].ai;
+        char *v = base->av + base->dv[di].aj;
 
         if (strcmp(k, "pendulum")  == 0)
             flags = SET(flags, atoi(v), F_PENDULUM);
@@ -93,14 +94,14 @@ void ball_init(void)
     inner_alpha = 1.0f;
     outer_alpha = 1.0f;
 
-    if ((has_solid = sol_load_gl(&solid, solid_file, 0)))
-        solid_flags = ball_opts(&solid, &solid_alpha);
+    if ((has_solid = sol_load_full(&solid, solid_file, 0)))
+        solid_flags = ball_opts(&solid.base, &solid_alpha);
 
-    if ((has_inner = sol_load_gl(&inner, inner_file, 0)))
-        inner_flags = ball_opts(&inner, &inner_alpha);
+    if ((has_inner = sol_load_full(&inner, inner_file, 0)))
+        inner_flags = ball_opts(&inner.base, &inner_alpha);
 
-    if ((has_outer = sol_load_gl(&outer, outer_file, 0)))
-        outer_flags = ball_opts(&outer, &outer_alpha);
+    if ((has_outer = sol_load_full(&outer, outer_file, 0)))
+        outer_flags = ball_opts(&outer.base, &outer_alpha);
 
     free(solid_file);
     free(inner_file);
@@ -109,9 +110,9 @@ void ball_init(void)
 
 void ball_free(void)
 {
-    if (has_outer) sol_free_gl(&outer);
-    if (has_inner) sol_free_gl(&inner);
-    if (has_solid) sol_free_gl(&solid);
+    if (has_outer) sol_free_full(&outer);
+    if (has_inner) sol_free_full(&inner);
+    if (has_solid) sol_free_full(&solid);
 
     has_solid = has_inner = has_outer = 0;
 }
@@ -140,13 +141,13 @@ static void ball_draw_solid(const float *ball_M,
 
             /* Draw the solid billboard geometry. */
 
-            if (solid.rc)
+            if (solid.base.rc)
             {
                 if (test == 0) glDisable(GL_DEPTH_TEST);
                 if (mask == 0) glDepthMask(GL_FALSE);
                 glDisable(GL_LIGHTING);
                 {
-                    sol_bill(&solid, ball_bill_M, t);
+                    sol_bill(&solid.draw, ball_bill_M, t);
                 }
                 glEnable(GL_LIGHTING);
                 if (mask == 0) glDepthMask(GL_TRUE);
@@ -155,7 +156,7 @@ static void ball_draw_solid(const float *ball_M,
 
             /* Draw the solid opaque and transparent geometry. */
 
-            sol_draw(&solid, mask, test);
+            sol_draw(&solid.draw, mask, test);
         }
         glPopMatrix();
 
@@ -190,20 +191,20 @@ static void ball_draw_inner(const float *pend_M,
 
         /* Draw the inner opaque and transparent geometry. */
 
-        sol_draw(&inner, mask, test);
+        sol_draw(&inner.draw, mask, test);
 
         /* Draw the inner billboard geometry. */
 
-        if (inner.rc)
+        if (inner.base.rc)
         {
             if (test == 0) glDisable(GL_DEPTH_TEST);
             if (mask == 0) glDepthMask(GL_FALSE);
             glDisable(GL_LIGHTING);
             {
                 if (pend)
-                    sol_bill(&inner, pend_bill_M, t);
+                    sol_bill(&inner.draw, pend_bill_M, t);
                 else
-                    sol_bill(&inner, bill_M,      t);
+                    sol_bill(&inner.draw, bill_M,      t);
             }
 
             glEnable(GL_LIGHTING);
@@ -245,20 +246,20 @@ static void ball_draw_outer(const float *pend_M,
 
         /* Draw the outer opaque and transparent geometry. */
 
-        sol_draw(&outer, mask, test);
+        sol_draw(&outer.draw, mask, test);
 
         /* Draw the outer billboard geometry. */
 
-        if (outer.rc)
+        if (outer.base.rc)
         {
             if (test == 0) glDisable(GL_DEPTH_TEST);
             if (mask == 0) glDepthMask(GL_FALSE);
             glDisable(GL_LIGHTING);
             {
                 if (pend)
-                    sol_bill(&outer, pend_bill_M, t);
+                    sol_bill(&outer.draw, pend_bill_M, t);
                 else
-                    sol_bill(&outer, bill_M,      t);
+                    sol_bill(&outer.draw, bill_M,      t);
             }
             glEnable(GL_LIGHTING);
             if (mask == 0) glDepthMask(GL_TRUE);
index eb19670..0dd3694 100644 (file)
@@ -21,7 +21,6 @@
 #include "geom.h"
 #include "part.h"
 #include "vec3.h"
-#include "solid.h"
 #include "image.h"
 #include "config.h"
 #include "video.h"
index 7e54e3d..f704027 100644 (file)
@@ -3,10 +3,6 @@
 
 /*---------------------------------------------------------------------------*/
 
-#include "solid.h"
-
-/*---------------------------------------------------------------------------*/
-
 #define IMG_SHAD "png/shadow.png"
 
 #define JUMP_HEIGHT   2.00f
index ce272d1..8af06db 100644 (file)
 #include "item.h"
 #include "glext.h"
 #include "vec3.h"
-#include "solid_gl.h"
 #include "image.h"
 #include "config.h"
 
+#include "solid_draw.h"
+
 /*---------------------------------------------------------------------------*/
 
-static struct s_file item_coin_file;
-static struct s_file item_grow_file;
-static struct s_file item_shrink_file;
+static struct s_full item_coin_file;
+static struct s_full item_grow_file;
+static struct s_full item_shrink_file;
 
-void item_color(const struct s_item *hp, float *c)
+void item_color(const struct v_item *hp, float *c)
 {
     switch (hp->t)
     {
@@ -80,16 +81,16 @@ void item_color(const struct s_item *hp, float *c)
 
 void item_init(void)
 {
-    sol_load_gl(&item_coin_file,   "item/coin/coin.sol",     0);
-    sol_load_gl(&item_grow_file,   "item/grow/grow.sol",     0);
-    sol_load_gl(&item_shrink_file, "item/shrink/shrink.sol", 0);
+    sol_load_full(&item_coin_file,   "item/coin/coin.sol",     0);
+    sol_load_full(&item_grow_file,   "item/grow/grow.sol",     0);
+    sol_load_full(&item_shrink_file, "item/shrink/shrink.sol", 0);
 }
 
 void item_free(void)
 {
-    sol_free_gl(&item_coin_file);
-    sol_free_gl(&item_grow_file);
-    sol_free_gl(&item_shrink_file);
+    sol_free_full(&item_coin_file);
+    sol_free_full(&item_grow_file);
+    sol_free_full(&item_shrink_file);
 }
 
 void item_push(int type)
@@ -97,22 +98,22 @@ void item_push(int type)
     glEnable(GL_COLOR_MATERIAL);
 }
 
-void item_draw(const struct s_item *hp, float r)
+void item_draw(const struct v_item *hp, float r)
 {
+    struct s_draw *draw = NULL;
     float c[3];
-    struct s_file *fp = NULL;
 
     switch (hp->t)
     {
-    case ITEM_COIN:   fp = &item_coin_file;   break;
-    case ITEM_GROW:   fp = &item_grow_file;   break;
-    case ITEM_SHRINK: fp = &item_shrink_file; break;
+    case ITEM_COIN:   draw = &item_coin_file.draw;   break;
+    case ITEM_GROW:   draw = &item_grow_file.draw;   break;
+    case ITEM_SHRINK: draw = &item_shrink_file.draw; break;
     }
 
     item_color(hp, c);
 
     glColor3fv(c);
-    sol_draw(fp, 0, 1);
+    sol_draw(draw, 0, 1);
 }
 
 void item_pull(void)
index 6ac4bc5..4d72414 100644 (file)
 #ifndef ITEM_H
 #define ITEM_H
 
-#include "solid.h"
+#include "solid_vary.h"
 
 #define ITEM_RADIUS 0.15f
 
-void item_color(const struct s_item *, float *);
+void item_color(const struct v_item *, float *);
 void item_init(void);
 void item_free(void);
 
 void item_push(int);
-void item_draw(const struct s_item *, float);
+void item_draw(const struct v_item *, float);
 void item_pull(void);
 
 #endif
index defb7b4..175e7d5 100644 (file)
@@ -19,8 +19,9 @@
 #include <string.h>
 #include <math.h>
 
+#include "solid_base.h"
+
 #include "vec3.h"
-#include "solid.h"
 #include "base_image.h"
 #include "base_config.h"
 #include "fs.h"
@@ -77,102 +78,102 @@ static int overflow(const char *s)
     return 0;
 }
 
-static int incm(struct s_file *fp)
+static int incm(struct s_base *fp)
 {
     return (fp->mc < MAXM) ? fp->mc++ : overflow("mtrl");
 }
 
-static int incv(struct s_file *fp)
+static int incv(struct s_base *fp)
 {
     return (fp->vc < MAXV) ? fp->vc++ : overflow("vert");
 }
 
-static int ince(struct s_file *fp)
+static int ince(struct s_base *fp)
 {
     return (fp->ec < MAXE) ? fp->ec++ : overflow("edge");
 }
 
-static int incs(struct s_file *fp)
+static int incs(struct s_base *fp)
 {
     return (fp->sc < MAXS) ? fp->sc++ : overflow("side");
 }
 
-static int inct(struct s_file *fp)
+static int inct(struct s_base *fp)
 {
     return (fp->tc < MAXT) ? fp->tc++ : overflow("texc");
 }
 
-static int incg(struct s_file *fp)
+static int incg(struct s_base *fp)
 {
     return (fp->gc < MAXG) ? fp->gc++ : overflow("geom");
 }
 
-static int incl(struct s_file *fp)
+static int incl(struct s_base *fp)
 {
     return (fp->lc < MAXL) ? fp->lc++ : overflow("lump");
 }
 
-static int incn(struct s_file *fp)
+static int incn(struct s_base *fp)
 {
     return (fp->nc < MAXN) ? fp->nc++ : overflow("node");
 }
 
-static int incp(struct s_file *fp)
+static int incp(struct s_base *fp)
 {
     return (fp->pc < MAXP) ? fp->pc++ : overflow("path");
 }
 
-static int incb(struct s_file *fp)
+static int incb(struct s_base *fp)
 {
     return (fp->bc < MAXB) ? fp->bc++ : overflow("body");
 }
 
-static int inch(struct s_file *fp)
+static int inch(struct s_base *fp)
 {
     return (fp->hc < MAXH) ? fp->hc++ : overflow("item");
 }
 
-static int incz(struct s_file *fp)
+static int incz(struct s_base *fp)
 {
     return (fp->zc < MAXZ) ? fp->zc++ : overflow("goal");
 }
 
-static int incj(struct s_file *fp)
+static int incj(struct s_base *fp)
 {
     return (fp->jc < MAXJ) ? fp->jc++ : overflow("jump");
 }
 
-static int incx(struct s_file *fp)
+static int incx(struct s_base *fp)
 {
     return (fp->xc < MAXX) ? fp->xc++ : overflow("swch");
 }
 
-static int incr(struct s_file *fp)
+static int incr(struct s_base *fp)
 {
     return (fp->rc < MAXR) ? fp->rc++ : overflow("bill");
 }
 
-static int incu(struct s_file *fp)
+static int incu(struct s_base *fp)
 {
     return (fp->uc < MAXU) ? fp->uc++ : overflow("ball");
 }
 
-static int incw(struct s_file *fp)
+static int incw(struct s_base *fp)
 {
     return (fp->wc < MAXW) ? fp->wc++ : overflow("view");
 }
 
-static int incd(struct s_file *fp)
+static int incd(struct s_base *fp)
 {
     return (fp->dc < MAXD) ? fp->dc++ : overflow("dict");
 }
 
-static int inci(struct s_file *fp)
+static int inci(struct s_base *fp)
 {
     return (fp->ic < MAXI) ? fp->ic++ : overflow("indx");
 }
 
-static void init_file(struct s_file *fp)
+static void init_file(struct s_base *fp)
 {
     fp->mc = 0;
     fp->vc = 0;
@@ -195,26 +196,26 @@ static void init_file(struct s_file *fp)
     fp->ac = 0;
     fp->ic = 0;
 
-    fp->mv = (struct s_mtrl *) calloc(MAXM, sizeof (struct s_mtrl));
-    fp->vv = (struct s_vert *) calloc(MAXV, sizeof (struct s_vert));
-    fp->ev = (struct s_edge *) calloc(MAXE, sizeof (struct s_edge));
-    fp->sv = (struct s_side *) calloc(MAXS, sizeof (struct s_side));
-    fp->tv = (struct s_texc *) calloc(MAXT, sizeof (struct s_texc));
-    fp->gv = (struct s_geom *) calloc(MAXG, sizeof (struct s_geom));
-    fp->lv = (struct s_lump *) calloc(MAXL, sizeof (struct s_lump));
-    fp->nv = (struct s_node *) calloc(MAXN, sizeof (struct s_node));
-    fp->pv = (struct s_path *) calloc(MAXP, sizeof (struct s_path));
-    fp->bv = (struct s_body *) calloc(MAXB, sizeof (struct s_body));
-    fp->hv = (struct s_item *) calloc(MAXH, sizeof (struct s_item));
-    fp->zv = (struct s_goal *) calloc(MAXZ, sizeof (struct s_goal));
-    fp->jv = (struct s_jump *) calloc(MAXJ, sizeof (struct s_jump));
-    fp->xv = (struct s_swch *) calloc(MAXX, sizeof (struct s_swch));
-    fp->rv = (struct s_bill *) calloc(MAXR, sizeof (struct s_bill));
-    fp->uv = (struct s_ball *) calloc(MAXU, sizeof (struct s_ball));
-    fp->wv = (struct s_view *) calloc(MAXW, sizeof (struct s_view));
-    fp->dv = (struct s_dict *) calloc(MAXD, sizeof (struct s_dict));
-    fp->av = (char          *) calloc(MAXA, sizeof (char));
-    fp->iv = (int           *) calloc(MAXI, sizeof (int));
+    fp->mv = (struct b_mtrl *) calloc(MAXM, sizeof (*fp->mv));
+    fp->vv = (struct b_vert *) calloc(MAXV, sizeof (*fp->vv));
+    fp->ev = (struct b_edge *) calloc(MAXE, sizeof (*fp->ev));
+    fp->sv = (struct b_side *) calloc(MAXS, sizeof (*fp->sv));
+    fp->tv = (struct b_texc *) calloc(MAXT, sizeof (*fp->tv));
+    fp->gv = (struct b_geom *) calloc(MAXG, sizeof (*fp->gv));
+    fp->lv = (struct b_lump *) calloc(MAXL, sizeof (*fp->lv));
+    fp->nv = (struct b_node *) calloc(MAXN, sizeof (*fp->nv));
+    fp->pv = (struct b_path *) calloc(MAXP, sizeof (*fp->pv));
+    fp->bv = (struct b_body *) calloc(MAXB, sizeof (*fp->bv));
+    fp->hv = (struct b_item *) calloc(MAXH, sizeof (*fp->hv));
+    fp->zv = (struct b_goal *) calloc(MAXZ, sizeof (*fp->zv));
+    fp->jv = (struct b_jump *) calloc(MAXJ, sizeof (*fp->jv));
+    fp->xv = (struct b_swch *) calloc(MAXX, sizeof (*fp->xv));
+    fp->rv = (struct b_bill *) calloc(MAXR, sizeof (*fp->rv));
+    fp->uv = (struct b_ball *) calloc(MAXU, sizeof (*fp->uv));
+    fp->wv = (struct b_view *) calloc(MAXW, sizeof (*fp->wv));
+    fp->dv = (struct b_dict *) calloc(MAXD, sizeof (*fp->dv));
+    fp->av = (char *)          calloc(MAXA, sizeof (*fp->av));
+    fp->iv = (int *)           calloc(MAXI, sizeof (*fp->iv));
 }
 
 /*---------------------------------------------------------------------------*/
@@ -277,7 +278,7 @@ static int   targ_wi[MAXW];
 static int   targ_ji[MAXW];
 static int   targ_n;
 
-static void targets(struct s_file *fp)
+static void targets(struct s_base *fp)
 {
     int i;
 
@@ -396,10 +397,10 @@ static void size_image(const char *name, int *w, int *h)
     if (fs_gets((s), sizeof (s), (f)))                                  \
         sscanf((s), "%f %f %f %f", (v), (v) + 1, (v) + 2, (v) + 3)
 
-static int read_mtrl(struct s_file *fp, const char *name)
+static int read_mtrl(struct s_base *fp, const char *name)
 {
     static char line[MAXSTR];
-    struct s_mtrl *mp;
+    struct b_mtrl *mp;
     fs_file fin;
     int mi;
 
@@ -456,18 +457,18 @@ static int read_mtrl(struct s_file *fp, const char *name)
  * specification.
  */
 
-static void move_side(struct s_side *sp, const float p[3])
+static void move_side(struct b_side *sp, const float p[3])
 {
     sp->d -= v_dot(sp->n, p);
 }
 
-static void move_vert(struct s_vert *vp, const float p[3])
+static void move_vert(struct b_vert *vp, const float p[3])
 {
     v_sub(vp->p, vp->p, p);
 }
 
-static void move_lump(struct s_file *fp,
-                      struct s_lump *lp, const float p[3])
+static void move_lump(struct s_base *fp,
+                      struct b_lump *lp, const float p[3])
 {
     int i;
 
@@ -477,8 +478,8 @@ static void move_lump(struct s_file *fp,
         move_vert(fp->vv + fp->iv[lp->v0 + i], p);
 }
 
-static void move_body(struct s_file *fp,
-                      struct s_body *bp)
+static void move_body(struct s_base *fp,
+                      struct b_body *bp)
 {
     int i, *b;
 
@@ -510,7 +511,7 @@ static void move_body(struct s_file *fp,
     }
 }
 
-static void move_file(struct s_file *fp)
+static void move_file(struct s_base *fp)
 {
     int i;
 
@@ -529,31 +530,31 @@ static void move_file(struct s_file *fp)
  * references to Neverball materials, rather than MTL definitions.
  */
 
-static void read_vt(struct s_file *fp, const char *line)
+static void read_vt(struct s_base *fp, const char *line)
 {
-    struct s_texc *tp = fp->tv + inct(fp);
+    struct b_texc *tp = fp->tv + inct(fp);
 
     sscanf(line, "%f %f", tp->u, tp->u + 1);
 }
 
-static void read_vn(struct s_file *fp, const char *line)
+static void read_vn(struct s_base *fp, const char *line)
 {
-    struct s_side *sp = fp->sv + incs(fp);
+    struct b_side *sp = fp->sv + incs(fp);
 
     sscanf(line, "%f %f %f", sp->n, sp->n + 1, sp->n + 2);
 }
 
-static void read_v(struct s_file *fp, const char *line)
+static void read_v(struct s_base *fp, const char *line)
 {
-    struct s_vert *vp = fp->vv + incv(fp);
+    struct b_vert *vp = fp->vv + incv(fp);
 
     sscanf(line, "%f %f %f", vp->p, vp->p + 1, vp->p + 2);
 }
 
-static void read_f(struct s_file *fp, const char *line,
+static void read_f(struct s_base *fp, const char *line,
                    int v0, int t0, int s0, int mi)
 {
-    struct s_geom *gp = fp->gv + incg(fp);
+    struct b_geom *gp = fp->gv + incg(fp);
 
     char c1;
     char c2;
@@ -576,7 +577,7 @@ static void read_f(struct s_file *fp, const char *line,
     gp->mi  = mi;
 }
 
-static void read_obj(struct s_file *fp, const char *name, int mi)
+static void read_obj(struct s_base *fp, const char *name, int mi)
 {
     char line[MAXSTR];
     char mtrl[MAXSTR];
@@ -764,13 +765,13 @@ static int map_token(fs_file fin, int pi, char key[MAXSTR], char val[MAXSTR])
 
 /* Parse a lump from the given file and add it to the solid. */
 
-static void read_lump(struct s_file *fp, fs_file fin)
+static void read_lump(struct s_base *fp, fs_file fin)
 {
     char k[MAXSTR];
     char v[MAXSTR];
     int t;
 
-    struct s_lump *lp = fp->lv + incl(fp);
+    struct b_lump *lp = fp->lv + incl(fp);
 
     lp->s0 = fp->ic;
 
@@ -797,13 +798,13 @@ static void read_lump(struct s_file *fp, fs_file fin)
 
 /*---------------------------------------------------------------------------*/
 
-static void make_path(struct s_file *fp,
+static void make_path(struct s_base *fp,
                       char k[][MAXSTR],
                       char v[][MAXSTR], int c)
 {
     int i, pi = incp(fp);
 
-    struct s_path *pp = fp->pv + pi;
+    struct b_path *pp = fp->pv + pi;
 
     pp->p[0] = 0.f;
     pp->p[1] = 0.f;
@@ -888,13 +889,13 @@ static void make_path(struct s_file *fp,
     }
 }
 
-static void make_dict(struct s_file *fp,
+static void make_dict(struct s_base *fp,
                       const char *k,
                       const char *v)
 {
     int space_left, space_needed, di = incd(fp);
 
-    struct s_dict *dp = fp->dv + di;
+    struct b_dict *dp = fp->dv + di;
 
     space_left   = MAXA - fp->ac;
     space_needed = strlen(k) + 1 + strlen(v) + 1;
@@ -915,7 +916,7 @@ static void make_dict(struct s_file *fp,
 
 static int read_dict_entries = 0;
 
-static void make_body(struct s_file *fp,
+static void make_body(struct s_base *fp,
                       char k[][MAXSTR],
                       char v[][MAXSTR], int c, int l0)
 {
@@ -930,9 +931,8 @@ static void make_body(struct s_file *fp,
     float y = 0.f;
     float z = 0.f;
 
-    struct s_body *bp = fp->bv + bi;
+    struct b_body *bp = fp->bv + bi;
 
-    bp->t  = 0.f;
     bp->pi = -1;
     bp->ni = -1;
 
@@ -975,13 +975,13 @@ static void make_body(struct s_file *fp,
     read_dict_entries = 0;
 }
 
-static void make_item(struct s_file *fp,
+static void make_item(struct s_base *fp,
                       char k[][MAXSTR],
                       char v[][MAXSTR], int c)
 {
     int i, hi = inch(fp);
 
-    struct s_item *hp = fp->hv + hi;
+    struct b_item *hp = fp->hv + hi;
 
     hp->p[0] = 0.f;
     hp->p[1] = 0.f;
@@ -1018,15 +1018,15 @@ static void make_item(struct s_file *fp,
     }
 }
 
-static void make_bill(struct s_file *fp,
+static void make_bill(struct s_base *fp,
                       char k[][MAXSTR],
                       char v[][MAXSTR], int c)
 {
     int i, ri = incr(fp);
 
-    struct s_bill *rp = fp->rv + ri;
+    struct b_bill *rp = fp->rv + ri;
 
-    memset(rp, 0, sizeof (struct s_bill));
+    memset(rp, 0, sizeof (struct b_bill));
     rp->t = 1.0f;
 
     for (i = 0; i < c; i++)
@@ -1072,13 +1072,13 @@ static void make_bill(struct s_file *fp,
         fp->mv[rp->mi].fl |= M_ADDITIVE;
 }
 
-static void make_goal(struct s_file *fp,
+static void make_goal(struct s_base *fp,
                       char k[][MAXSTR],
                       char v[][MAXSTR], int c)
 {
     int i, zi = incz(fp);
 
-    struct s_goal *zp = fp->zv + zi;
+    struct b_goal *zp = fp->zv + zi;
 
     zp->p[0] = 0.f;
     zp->p[1] = 0.f;
@@ -1103,13 +1103,13 @@ static void make_goal(struct s_file *fp,
     }
 }
 
-static void make_view(struct s_file *fp,
+static void make_view(struct s_base *fp,
                       char k[][MAXSTR],
                       char v[][MAXSTR], int c)
 {
     int i, wi = incw(fp);
 
-    struct s_view *wp = fp->wv + wi;
+    struct b_view *wp = fp->wv + wi;
 
     wp->p[0] = 0.f;
     wp->p[1] = 0.f;
@@ -1136,13 +1136,13 @@ static void make_view(struct s_file *fp,
     }
 }
 
-static void make_jump(struct s_file *fp,
+static void make_jump(struct s_base *fp,
                       char k[][MAXSTR],
                       char v[][MAXSTR], int c)
 {
     int i, ji = incj(fp);
 
-    struct s_jump *jp = fp->jv + ji;
+    struct b_jump *jp = fp->jv + ji;
 
     jp->p[0] = 0.f;
     jp->p[1] = 0.f;
@@ -1173,22 +1173,20 @@ static void make_jump(struct s_file *fp,
     }
 }
 
-static void make_swch(struct s_file *fp,
+static void make_swch(struct s_base *fp,
                       char k[][MAXSTR],
                       char v[][MAXSTR], int c)
 {
     int i, xi = incx(fp);
 
-    struct s_swch *xp = fp->xv + xi;
+    struct b_swch *xp = fp->xv + xi;
 
     xp->p[0] = 0.f;
     xp->p[1] = 0.f;
     xp->p[2] = 0.f;
     xp->r    = 0.5;
     xp->pi   = 0;
-    xp->t0   = 0;
     xp->t    = 0;
-    xp->f0   = 0;
     xp->f    = 0;
     xp->i    = 0;
 
@@ -1201,16 +1199,10 @@ static void make_swch(struct s_file *fp,
             make_ref(v[i], &xp->pi);
 
         if (strcmp(k[i], "timer") == 0)
-        {
-            sscanf(v[i], "%f", &xp->t0);
-            xp->t = xp->t0;
-        }
+            sscanf(v[i], "%f", &xp->t);
 
         if (strcmp(k[i], "state") == 0)
-        {
-            xp->f  = atoi(v[i]);
-            xp->f0 = atoi(v[i]);
-        }
+            xp->f = atoi(v[i]);
 
         if (strcmp(k[i], "invisible") == 0)
             xp->i = atoi(v[i]);
@@ -1228,7 +1220,7 @@ static void make_swch(struct s_file *fp,
     }
 }
 
-static void make_targ(struct s_file *fp,
+static void make_targ(struct s_base *fp,
                       char k[][MAXSTR],
                       char v[][MAXSTR], int c)
 {
@@ -1258,13 +1250,13 @@ static void make_targ(struct s_file *fp,
     targ_n++;
 }
 
-static void make_ball(struct s_file *fp,
+static void make_ball(struct s_base *fp,
                       char k[][MAXSTR],
                       char v[][MAXSTR], int c)
 {
     int i, ui = incu(fp);
 
-    struct s_ball *up = fp->uv + ui;
+    struct b_ball *up = fp->uv + ui;
 
     up->p[0] = 0.0f;
     up->p[1] = 0.0f;
@@ -1293,7 +1285,7 @@ static void make_ball(struct s_file *fp,
 
 /*---------------------------------------------------------------------------*/
 
-static void read_ent(struct s_file *fp, fs_file fin)
+static void read_ent(struct s_base *fp, fs_file fin)
 {
     char k[MAXKEY][MAXSTR];
     char v[MAXKEY][MAXSTR];
@@ -1333,7 +1325,7 @@ static void read_ent(struct s_file *fp, fs_file fin)
     if (!strcmp(v[i], "misc_model"))               make_body(fp, k, v, c, l0);
 }
 
-static void read_map(struct s_file *fp, fs_file fin)
+static void read_map(struct s_base *fp, fs_file fin)
 {
     char k[MAXSTR];
     char v[MAXSTR];
@@ -1348,12 +1340,12 @@ static void read_map(struct s_file *fp, fs_file fin)
 
 /* Test the location of a point with respect to a side plane. */
 
-static int fore_side(const float p[3], const struct s_side *sp)
+static int fore_side(const float p[3], const struct b_side *sp)
 {
     return (v_dot(p, sp->n) - sp->d > +SMALL) ? 1 : 0;
 }
 
-static int on_side(const float p[3], const struct s_side *sp)
+static int on_side(const float p[3], const struct b_side *sp)
 {
     float d = v_dot(p, sp->n) - sp->d;
 
@@ -1366,8 +1358,8 @@ static int on_side(const float p[3], const struct s_side *sp)
  * geometry.
  */
 
-static int ok_vert(const struct s_file *fp,
-                   const struct s_lump *lp, const float p[3])
+static int ok_vert(const struct s_base *fp,
+                   const struct b_lump *lp, const float p[3])
 {
     float r[3];
     int i;
@@ -1401,8 +1393,8 @@ static int ok_vert(const struct s_file *fp,
  * Confirm that this point falls  within the current lump, and that it
  * is unique.  Add it as a vert of the solid.
  */
-static void clip_vert(struct s_file *fp,
-                      struct s_lump *lp, int si, int sj, int sk)
+static void clip_vert(struct s_base *fp,
+                      struct b_lump *lp, int si, int sj, int sk)
 {
     float M[16], X[16], I[16];
     float d[3],  p[3];
@@ -1444,8 +1436,8 @@ static void clip_vert(struct s_file *fp,
  * finding a pair of vertices that fall on both planes.  Add it to the
  * solid.
  */
-static void clip_edge(struct s_file *fp,
-                      struct s_lump *lp, int si, int sj)
+static void clip_edge(struct s_base *fp,
+                      struct b_lump *lp, int si, int sj)
 {
     int i, j;
 
@@ -1482,15 +1474,15 @@ static void clip_edge(struct s_file *fp,
  * verts to  have a counter-clockwise winding about  the plane normal.
  * Create geoms to tessellate the resulting convex polygon.
  */
-static void clip_geom(struct s_file *fp,
-                      struct s_lump *lp, int si)
+static void clip_geom(struct s_base *fp,
+                      struct b_lump *lp, int si)
 {
     int   m[256], t[256], d, i, j, n = 0;
     float u[3];
     float v[3];
     float w[3];
 
-    struct s_side *sp = fp->sv + si;
+    struct b_side *sp = fp->sv + si;
 
     /* Find em. */
 
@@ -1563,7 +1555,7 @@ static void clip_geom(struct s_file *fp,
  * each trio of planes, a new edge  for each pair of planes, and a new
  * set of geom for each visible plane.
  */
-static void clip_lump(struct s_file *fp, struct s_lump *lp)
+static void clip_lump(struct s_base *fp, struct b_lump *lp)
 {
     int i, j, k;
 
@@ -1600,7 +1592,7 @@ static void clip_lump(struct s_file *fp, struct s_lump *lp)
             lp->fl |= L_DETAIL;
 }
 
-static void clip_file(struct s_file *fp)
+static void clip_file(struct s_base *fp)
 {
     int i;
 
@@ -1618,7 +1610,7 @@ static void clip_file(struct s_file *fp)
  * the number of elements that can be eliminated.
  */
 
-static int comp_mtrl(const struct s_mtrl *mp, const struct s_mtrl *mq)
+static int comp_mtrl(const struct b_mtrl *mp, const struct b_mtrl *mq)
 {
     if (fabs(mp->d[0] - mq->d[0]) > SMALL) return 0;
     if (fabs(mp->d[1] - mq->d[1]) > SMALL) return 0;
@@ -1647,7 +1639,7 @@ static int comp_mtrl(const struct s_mtrl *mp, const struct s_mtrl *mq)
     return 1;
 }
 
-static int comp_vert(const struct s_vert *vp, const struct s_vert *vq)
+static int comp_vert(const struct b_vert *vp, const struct b_vert *vq)
 {
     if (fabs(vp->p[0] - vq->p[0]) > SMALL) return 0;
     if (fabs(vp->p[1] - vq->p[1]) > SMALL) return 0;
@@ -1656,7 +1648,7 @@ static int comp_vert(const struct s_vert *vp, const struct s_vert *vq)
     return 1;
 }
 
-static int comp_edge(const struct s_edge *ep, const struct s_edge *eq)
+static int comp_edge(const struct b_edge *ep, const struct b_edge *eq)
 {
     if (ep->vi != eq->vi && ep->vi != eq->vj) return 0;
     if (ep->vj != eq->vi && ep->vj != eq->vj) return 0;
@@ -1664,7 +1656,7 @@ static int comp_edge(const struct s_edge *ep, const struct s_edge *eq)
     return 1;
 }
 
-static int comp_side(const struct s_side *sp, const struct s_side *sq)
+static int comp_side(const struct b_side *sp, const struct b_side *sq)
 {
     if  (fabs(sp->d - sq->d) > SMALL)  return 0;
     if (v_dot(sp->n,  sq->n) < 0.9999) return 0;
@@ -1672,7 +1664,7 @@ static int comp_side(const struct s_side *sp, const struct s_side *sq)
     return 1;
 }
 
-static int comp_texc(const struct s_texc *tp, const struct s_texc *tq)
+static int comp_texc(const struct b_texc *tp, const struct b_texc *tq)
 {
     if (fabs(tp->u[0] - tq->u[0]) > SMALL) return 0;
     if (fabs(tp->u[1] - tq->u[1]) > SMALL) return 0;
@@ -1680,7 +1672,7 @@ static int comp_texc(const struct s_texc *tp, const struct s_texc *tq)
     return 1;
 }
 
-static int comp_geom(const struct s_geom *gp, const struct s_geom *gq)
+static int comp_geom(const struct b_geom *gp, const struct b_geom *gq)
 {
     if (gp->mi != gq->mi) return 0;
 
@@ -1707,7 +1699,7 @@ static int comp_geom(const struct s_geom *gp, const struct s_geom *gq)
  * and sorting the file.
  */
 
-static void swap_mtrl(struct s_file *fp, int mi, int mj)
+static void swap_mtrl(struct s_base *fp, int mi, int mj)
 {
     int i;
 
@@ -1719,7 +1711,7 @@ static void swap_mtrl(struct s_file *fp, int mi, int mj)
 
 static int vert_swaps[MAXV];
 
-static void apply_vert_swaps(struct s_file *fp)
+static void apply_vert_swaps(struct s_base *fp)
 {
     int i, j;
 
@@ -1741,7 +1733,7 @@ static void apply_vert_swaps(struct s_file *fp)
             fp->iv[fp->lv[i].v0 + j] = vert_swaps[fp->iv[fp->lv[i].v0 + j]];
 }
 
-static void swap_vert(struct s_file *fp, int vi, int vj)
+static void swap_vert(struct s_base *fp, int vi, int vj)
 {
     int i, j;
 
@@ -1766,7 +1758,7 @@ static void swap_vert(struct s_file *fp, int vi, int vj)
 
 static int edge_swaps[MAXE];
 
-static void apply_edge_swaps(struct s_file *fp)
+static void apply_edge_swaps(struct s_base *fp)
 {
     int i, j;
 
@@ -1777,7 +1769,7 @@ static void apply_edge_swaps(struct s_file *fp)
 
 static int side_swaps[MAXS];
 
-static void apply_side_swaps(struct s_file *fp)
+static void apply_side_swaps(struct s_base *fp)
 {
     int i, j;
 
@@ -1797,7 +1789,7 @@ static void apply_side_swaps(struct s_file *fp)
 
 static int texc_swaps[MAXT];
 
-static void apply_texc_swaps(struct s_file *fp)
+static void apply_texc_swaps(struct s_base *fp)
 {
     int i;
 
@@ -1811,7 +1803,7 @@ static void apply_texc_swaps(struct s_file *fp)
 
 static int geom_swaps[MAXG];
 
-static void apply_geom_swaps(struct s_file *fp)
+static void apply_geom_swaps(struct s_base *fp)
 {
     int i, j;
 
@@ -1826,7 +1818,7 @@ static void apply_geom_swaps(struct s_file *fp)
 
 /*---------------------------------------------------------------------------*/
 
-static void uniq_mtrl(struct s_file *fp)
+static void uniq_mtrl(struct s_base *fp)
 {
     int i, j, k = 0;
 
@@ -1853,7 +1845,7 @@ static void uniq_mtrl(struct s_file *fp)
     fp->mc = k;
 }
 
-static void uniq_vert(struct s_file *fp)
+static void uniq_vert(struct s_base *fp)
 {
     int i, j, k = 0;
 
@@ -1878,7 +1870,7 @@ static void uniq_vert(struct s_file *fp)
     fp->vc = k;
 }
 
-static void uniq_edge(struct s_file *fp)
+static void uniq_edge(struct s_base *fp)
 {
     int i, j, k = 0;
 
@@ -1906,7 +1898,7 @@ static void uniq_edge(struct s_file *fp)
 static int geomlist[MAXV];
 static int nextgeom[MAXG];
 
-static void uniq_geom(struct s_file *fp)
+static void uniq_geom(struct s_base *fp)
 {
     int i, j, k = 0;
 
@@ -1938,7 +1930,7 @@ found:
     fp->gc = k;
 }
 
-static void uniq_texc(struct s_file *fp)
+static void uniq_texc(struct s_base *fp)
 {
     int i, j, k = 0;
 
@@ -1963,7 +1955,7 @@ static void uniq_texc(struct s_file *fp)
     fp->tc = k;
 }
 
-static void uniq_side(struct s_file *fp)
+static void uniq_side(struct s_base *fp)
 {
     int i, j, k = 0;
 
@@ -1988,7 +1980,7 @@ static void uniq_side(struct s_file *fp)
     fp->sc = k;
 }
 
-static void uniq_file(struct s_file *fp)
+static void uniq_file(struct s_base *fp)
 {
     /* Debug mode skips optimization, producing oversized output files. */
 
@@ -2005,7 +1997,7 @@ static void uniq_file(struct s_file *fp)
 
 /*---------------------------------------------------------------------------*/
 
-struct s_trip
+struct b_trip
 {
     int vi;
     int mi;
@@ -2015,8 +2007,8 @@ struct s_trip
 
 static int comp_trip(const void *p, const void *q)
 {
-    const struct s_trip *tp = (const struct s_trip *) p;
-    const struct s_trip *tq = (const struct s_trip *) q;
+    const struct b_trip *tp = (const struct b_trip *) p;
+    const struct b_trip *tq = (const struct b_trip *) q;
 
     if (tp->vi < tq->vi) return -1;
     if (tp->vi > tq->vi) return +1;
@@ -2026,13 +2018,13 @@ static int comp_trip(const void *p, const void *q)
     return 0;
 }
 
-static void smth_file(struct s_file *fp)
+static void smth_file(struct s_base *fp)
 {
-    struct s_trip temp, *T;
+    struct b_trip temp, *T;
 
     if (debug_output == 0)
     {
-        if ((T = (struct s_trip *) malloc(fp->gc * 3 * sizeof (struct s_trip))))
+        if ((T = (struct b_trip *) malloc(fp->gc * 3 * sizeof (struct b_trip))))
         {
             int gi, i, j, k, l, c = 0;
 
@@ -2040,7 +2032,7 @@ static void smth_file(struct s_file *fp)
 
             for (gi = 0; gi < fp->gc; ++gi)
             {
-                struct s_geom *gp = fp->gv + gi;
+                struct b_geom *gp = fp->gv + gi;
 
                 T[c].vi = gp->vi;
                 T[c].mi = gp->mi;
@@ -2063,7 +2055,7 @@ static void smth_file(struct s_file *fp)
 
             /* Sort all triplets by vertex index and material. */
 
-            qsort(T, c, sizeof (struct s_trip), comp_trip);
+            qsort(T, c, sizeof (struct b_trip), comp_trip);
 
             /* For each set of triplets sharing vertex index and material... */
 
@@ -2138,7 +2130,7 @@ static void smth_file(struct s_file *fp)
 
             for (i = 0; i < c; ++i)
             {
-                struct s_geom *gp = fp->gv + T[i].gi;
+                struct b_geom *gp = fp->gv + T[i].gi;
 
                 if (gp->vi == T[i].vi) gp->si = T[i].si;
                 if (gp->vj == T[i].vi) gp->sj = T[i].si;
@@ -2155,7 +2147,7 @@ static void smth_file(struct s_file *fp)
 
 /*---------------------------------------------------------------------------*/
 
-static void sort_file(struct s_file *fp)
+static void sort_file(struct s_base *fp)
 {
     int i, j;
 
@@ -2167,7 +2159,7 @@ static void sort_file(struct s_file *fp)
                 (fp->rv[j].d == fp->rv[i].d &&
                  fp->rv[j].mi > fp->rv[i].mi))
             {
-                struct s_bill t;
+                struct b_bill t;
 
                 t         = fp->rv[i];
                 fp->rv[i] = fp->rv[j];
@@ -2179,7 +2171,7 @@ static void sort_file(struct s_file *fp)
     for (i = 0; i < fp->vc; i++)
         if (fp->vv[0].p[1] > fp->vv[i].p[1])
         {
-            struct s_vert t;
+            struct b_vert t;
 
             t         = fp->vv[0];
             fp->vv[0] = fp->vv[i];
@@ -2193,9 +2185,9 @@ static void sort_file(struct s_file *fp)
 
 /*---------------------------------------------------------------------------*/
 
-static int test_lump_side(const struct s_file *fp,
-                          const struct s_lump *lp,
-                          const struct s_side *sp,
+static int test_lump_side(const struct s_base *fp,
+                          const struct b_lump *lp,
+                          const struct b_side *sp,
                           float bsphere[4])
 {
     int si;
@@ -2242,7 +2234,7 @@ static int test_lump_side(const struct s_file *fp,
     return 0;
 }
 
-static int node_node(struct s_file *fp, int l0, int lc, float bsphere[][4])
+static int node_node(struct s_base *fp, int l0, int lc, float bsphere[][4])
 {
     if (lc < 8)
     {
@@ -2328,7 +2320,7 @@ static int node_node(struct s_file *fp, int l0, int lc, float bsphere[][4])
             for (lj = 0; lj < li; lj++)
                 if (fp->lv[l0 + li].fl < fp->lv[l0 + lj].fl)
                 {
-                    struct s_lump l;
+                    struct b_lump l;
                     float f;
                     int i;
 
@@ -2376,8 +2368,8 @@ static int node_node(struct s_file *fp, int l0, int lc, float bsphere[][4])
 /*
  * Compute a bounding sphere for a lump (not optimal)
  */
-static void lump_bounding_sphere(struct s_file *fp,
-                                 struct s_lump *lp,
+static void lump_bounding_sphere(struct s_base *fp,
+                                 struct b_lump *lp,
                                  float bsphere[4])
 {
     float bbox[6];
@@ -2393,7 +2385,7 @@ static void lump_bounding_sphere(struct s_file *fp,
 
     for (i = 1; i < lp->vc; i++)
     {
-        struct s_vert *vp = fp->vv + fp->iv[lp->v0 + i];
+        struct b_vert *vp = fp->vv + fp->iv[lp->v0 + i];
         int j;
 
         for (j = 0; j < 3; j++)
@@ -2416,7 +2408,7 @@ static void lump_bounding_sphere(struct s_file *fp,
     bsphere[3] = fsqrtf(r);
 }
 
-static void node_file(struct s_file *fp)
+static void node_file(struct s_base *fp)
 {
     float bsphere[MAXL][4];
     int i;
@@ -2434,7 +2426,7 @@ static void node_file(struct s_file *fp)
 
 /*---------------------------------------------------------------------------*/
 
-static void dump_file(struct s_file *p, const char *name)
+static void dump_file(struct s_base *p, const char *name)
 {
     int i, j;
     int c = 0;
@@ -2488,7 +2480,7 @@ int main(int argc, char *argv[])
 {
     char src[MAXSTR] = "";
     char dst[MAXSTR] = "";
-    struct s_file f;
+    struct s_base f;
     fs_file fin;
 
     if (!fs_init(argv[0]))
@@ -2542,7 +2534,7 @@ int main(int argc, char *argv[])
             node_file(&f);
             dump_file(&f, dst);
 
-            sol_stor(&f, base_name(dst));
+            sol_stor_base(&f, base_name(dst));
 
             fs_close(fin);
 
diff --git a/share/solid.c b/share/solid.c
deleted file mode 100644 (file)
index c45bb72..0000000
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * Copyright (C) 2003 Robert Kooima
- *
- * NEVERBALL is  free software; you can redistribute  it and/or modify
- * it under the  terms of the GNU General  Public License as published
- * by the Free  Software Foundation; either version 2  of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
- * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
- * General Public License for more details.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "solid.h"
-#include "base_config.h"
-#include "binary.h"
-#include "common.h"
-#include "fs.h"
-
-enum
-{
-    SOL_VER_MINIMUM = 6,
-    SOL_VER_PATH_FLAGS,
-    SOL_VER_CURRENT = SOL_VER_PATH_FLAGS
-};
-
-#define SOL_MAGIC (0xAF | 'S' << 8 | 'O' << 16 | 'L' << 24)
-
-/*---------------------------------------------------------------------------*/
-
-static int sol_version;
-
-static int sol_file(fs_file fin)
-{
-    int magic;
-    int version;
-
-    get_index(fin, &magic);
-    get_index(fin, &version);
-
-    if (magic != SOL_MAGIC || (version < SOL_VER_MINIMUM ||
-                               version > SOL_VER_CURRENT))
-        return 0;
-
-    sol_version = version;
-
-    return 1;
-}
-
-static void sol_load_mtrl(fs_file fin, struct s_mtrl *mp)
-{
-    get_array(fin,  mp->d, 4);
-    get_array(fin,  mp->a, 4);
-    get_array(fin,  mp->s, 4);
-    get_array(fin,  mp->e, 4);
-    get_array(fin,  mp->h, 1);
-    get_index(fin, &mp->fl);
-
-    fs_read(mp->f, 1, PATHMAX, fin);
-}
-
-static void sol_load_vert(fs_file fin, struct s_vert *vp)
-{
-    get_array(fin,  vp->p, 3);
-}
-
-static void sol_load_edge(fs_file fin, struct s_edge *ep)
-{
-    get_index(fin, &ep->vi);
-    get_index(fin, &ep->vj);
-}
-
-static void sol_load_side(fs_file fin, struct s_side *sp)
-{
-    get_array(fin,  sp->n, 3);
-    get_float(fin, &sp->d);
-}
-
-static void sol_load_texc(fs_file fin, struct s_texc *tp)
-{
-    get_array(fin,  tp->u, 2);
-}
-
-static void sol_load_geom(fs_file fin, struct s_geom *gp)
-{
-    get_index(fin, &gp->mi);
-    get_index(fin, &gp->ti);
-    get_index(fin, &gp->si);
-    get_index(fin, &gp->vi);
-    get_index(fin, &gp->tj);
-    get_index(fin, &gp->sj);
-    get_index(fin, &gp->vj);
-    get_index(fin, &gp->tk);
-    get_index(fin, &gp->sk);
-    get_index(fin, &gp->vk);
-}
-
-static void sol_load_lump(fs_file fin, struct s_lump *lp)
-{
-    get_index(fin, &lp->fl);
-    get_index(fin, &lp->v0);
-    get_index(fin, &lp->vc);
-    get_index(fin, &lp->e0);
-    get_index(fin, &lp->ec);
-    get_index(fin, &lp->g0);
-    get_index(fin, &lp->gc);
-    get_index(fin, &lp->s0);
-    get_index(fin, &lp->sc);
-}
-
-static void sol_load_node(fs_file fin, struct s_node *np)
-{
-    get_index(fin, &np->si);
-    get_index(fin, &np->ni);
-    get_index(fin, &np->nj);
-    get_index(fin, &np->l0);
-    get_index(fin, &np->lc);
-}
-
-static void sol_load_path(fs_file fin, struct s_path *pp)
-{
-    get_array(fin,  pp->p, 3);
-    get_float(fin, &pp->t);
-    get_index(fin, &pp->pi);
-    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);
-
-    pp->e[0] = 1.0f;
-    pp->e[1] = 0.0f;
-    pp->e[2] = 0.0f;
-    pp->e[3] = 0.0f;
-
-    if (pp->fl & P_ORIENTED)
-        get_array(fin, pp->e, 4);
-}
-
-static void sol_load_body(fs_file fin, struct s_body *bp)
-{
-    get_index(fin, &bp->pi);
-    get_index(fin, &bp->ni);
-    get_index(fin, &bp->l0);
-    get_index(fin, &bp->lc);
-    get_index(fin, &bp->g0);
-    get_index(fin, &bp->gc);
-}
-
-static void sol_load_item(fs_file fin, struct s_item *hp)
-{
-    get_array(fin,  hp->p, 3);
-    get_index(fin, &hp->t);
-    get_index(fin, &hp->n);
-}
-
-static void sol_load_goal(fs_file fin, struct s_goal *zp)
-{
-    get_array(fin,  zp->p, 3);
-    get_float(fin, &zp->r);
-}
-
-static void sol_load_swch(fs_file fin, struct s_swch *xp)
-{
-    get_array(fin,  xp->p, 3);
-    get_float(fin, &xp->r);
-    get_index(fin, &xp->pi);
-    get_float(fin, &xp->t0);
-    get_float(fin, &xp->t);
-    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)
-{
-    get_index(fin, &rp->fl);
-    get_index(fin, &rp->mi);
-    get_float(fin, &rp->t);
-    get_float(fin, &rp->d);
-    get_array(fin,  rp->w,  3);
-    get_array(fin,  rp->h,  3);
-    get_array(fin,  rp->rx, 3);
-    get_array(fin,  rp->ry, 3);
-    get_array(fin,  rp->rz, 3);
-    get_array(fin,  rp->p,  3);
-}
-
-static void sol_load_jump(fs_file fin, struct s_jump *jp)
-{
-    get_array(fin,  jp->p, 3);
-    get_array(fin,  jp->q, 3);
-    get_float(fin, &jp->r);
-}
-
-static void sol_load_ball(fs_file fin, struct s_ball *bp)
-{
-    get_array(fin,  bp->p, 3);
-    get_float(fin, &bp->r);
-
-    bp->e[0][0] = bp->E[0][0] = 1.0f;
-    bp->e[0][1] = bp->E[0][1] = 0.0f;
-    bp->e[0][2] = bp->E[0][2] = 0.0f;
-
-    bp->e[1][0] = bp->E[1][0] = 0.0f;
-    bp->e[1][1] = bp->E[1][1] = 1.0f;
-    bp->e[1][2] = bp->E[1][2] = 0.0f;
-
-    bp->e[2][0] = bp->E[2][0] = 0.0f;
-    bp->e[2][1] = bp->E[2][1] = 0.0f;
-    bp->e[2][2] = bp->E[2][2] = 1.0f;
-}
-
-static void sol_load_view(fs_file fin, struct s_view *wp)
-{
-    get_array(fin,  wp->p, 3);
-    get_array(fin,  wp->q, 3);
-}
-
-static void sol_load_dict(fs_file fin, struct s_dict *dp)
-{
-    get_index(fin, &dp->ai);
-    get_index(fin, &dp->aj);
-}
-
-static void sol_load_indx(fs_file fin, struct s_file *fp)
-{
-    get_index(fin, &fp->ac);
-    get_index(fin, &fp->dc);
-    get_index(fin, &fp->mc);
-    get_index(fin, &fp->vc);
-    get_index(fin, &fp->ec);
-    get_index(fin, &fp->sc);
-    get_index(fin, &fp->tc);
-    get_index(fin, &fp->gc);
-    get_index(fin, &fp->lc);
-    get_index(fin, &fp->nc);
-    get_index(fin, &fp->pc);
-    get_index(fin, &fp->bc);
-    get_index(fin, &fp->hc);
-    get_index(fin, &fp->zc);
-    get_index(fin, &fp->jc);
-    get_index(fin, &fp->xc);
-    get_index(fin, &fp->rc);
-    get_index(fin, &fp->uc);
-    get_index(fin, &fp->wc);
-    get_index(fin, &fp->ic);
-}
-
-static int sol_load_file(fs_file fin, struct s_file *fp)
-{
-    int i;
-
-    if (!sol_file(fin))
-        return 0;
-
-    sol_load_indx(fin, fp);
-
-    if (fp->ac)
-        fp->av = (char          *) calloc(fp->ac, sizeof (char));
-    if (fp->mc)
-        fp->mv = (struct s_mtrl *) calloc(fp->mc, sizeof (struct s_mtrl));
-    if (fp->vc)
-        fp->vv = (struct s_vert *) calloc(fp->vc, sizeof (struct s_vert));
-    if (fp->ec)
-        fp->ev = (struct s_edge *) calloc(fp->ec, sizeof (struct s_edge));
-    if (fp->sc)
-        fp->sv = (struct s_side *) calloc(fp->sc, sizeof (struct s_side));
-    if (fp->tc)
-        fp->tv = (struct s_texc *) calloc(fp->tc, sizeof (struct s_texc));
-    if (fp->gc)
-        fp->gv = (struct s_geom *) calloc(fp->gc, sizeof (struct s_geom));
-    if (fp->lc)
-        fp->lv = (struct s_lump *) calloc(fp->lc, sizeof (struct s_lump));
-    if (fp->nc)
-        fp->nv = (struct s_node *) calloc(fp->nc, sizeof (struct s_node));
-    if (fp->pc)
-        fp->pv = (struct s_path *) calloc(fp->pc, sizeof (struct s_path));
-    if (fp->bc)
-        fp->bv = (struct s_body *) calloc(fp->bc, sizeof (struct s_body));
-    if (fp->hc)
-        fp->hv = (struct s_item *) calloc(fp->hc, sizeof (struct s_item));
-    if (fp->zc)
-        fp->zv = (struct s_goal *) calloc(fp->zc, sizeof (struct s_goal));
-    if (fp->jc)
-        fp->jv = (struct s_jump *) calloc(fp->jc, sizeof (struct s_jump));
-    if (fp->xc)
-        fp->xv = (struct s_swch *) calloc(fp->xc, sizeof (struct s_swch));
-    if (fp->rc)
-        fp->rv = (struct s_bill *) calloc(fp->rc, sizeof (struct s_bill));
-    if (fp->uc)
-        fp->uv = (struct s_ball *) calloc(fp->uc, sizeof (struct s_ball));
-    if (fp->wc)
-        fp->wv = (struct s_view *) calloc(fp->wc, sizeof (struct s_view));
-    if (fp->dc)
-        fp->dv = (struct s_dict *) calloc(fp->dc, sizeof (struct s_dict));
-    if (fp->ic)
-        fp->iv = (int           *) calloc(fp->ic, sizeof (int));
-
-    if (fp->ac)
-        fs_read(fp->av, 1, fp->ac, fin);
-
-    for (i = 0; i < fp->dc; i++) sol_load_dict(fin, fp->dv + i);
-    for (i = 0; i < fp->mc; i++) sol_load_mtrl(fin, fp->mv + i);
-    for (i = 0; i < fp->vc; i++) sol_load_vert(fin, fp->vv + i);
-    for (i = 0; i < fp->ec; i++) sol_load_edge(fin, fp->ev + i);
-    for (i = 0; i < fp->sc; i++) sol_load_side(fin, fp->sv + i);
-    for (i = 0; i < fp->tc; i++) sol_load_texc(fin, fp->tv + i);
-    for (i = 0; i < fp->gc; i++) sol_load_geom(fin, fp->gv + i);
-    for (i = 0; i < fp->lc; i++) sol_load_lump(fin, fp->lv + i);
-    for (i = 0; i < fp->nc; i++) sol_load_node(fin, fp->nv + i);
-    for (i = 0; i < fp->pc; i++) sol_load_path(fin, fp->pv + i);
-    for (i = 0; i < fp->bc; i++) sol_load_body(fin, fp->bv + i);
-    for (i = 0; i < fp->hc; i++) sol_load_item(fin, fp->hv + i);
-    for (i = 0; i < fp->zc; i++) sol_load_goal(fin, fp->zv + i);
-    for (i = 0; i < fp->jc; i++) sol_load_jump(fin, fp->jv + i);
-    for (i = 0; i < fp->xc; i++) sol_load_swch(fin, fp->xv + i);
-    for (i = 0; i < fp->rc; i++) sol_load_bill(fin, fp->rv + i);
-    for (i = 0; i < fp->uc; i++) sol_load_ball(fin, fp->uv + i);
-    for (i = 0; i < fp->wc; i++) sol_load_view(fin, fp->wv + i);
-    for (i = 0; i < fp->ic; i++) get_index(fin, fp->iv + i);
-
-    return 1;
-}
-
-static int sol_load_head(fs_file fin, struct s_file *fp)
-{
-    if (!sol_file(fin))
-        return 0;
-
-    sol_load_indx(fin, fp);
-
-    if (fp->ac)
-    {
-        fp->av = (char *) calloc(fp->ac, sizeof (char));
-        fs_read(fp->av, 1, fp->ac, fin);
-    }
-
-    if (fp->dc)
-    {
-        int i;
-
-        fp->dv = (struct s_dict *) calloc(fp->dc, sizeof (struct s_dict));
-
-        for (i = 0; i < fp->dc; i++)
-            sol_load_dict(fin, fp->dv + i);
-    }
-
-    return 1;
-}
-
-int sol_load_only_file(struct s_file *fp, const char *filename)
-{
-    fs_file fin;
-    int res = 0;
-
-    if ((fin = fs_open(filename, "r")))
-    {
-        res = sol_load_file(fin, fp);
-        fs_close(fin);
-    }
-    return res;
-}
-
-int sol_load_only_head(struct s_file *fp, const char *filename)
-{
-    fs_file fin;
-    int res = 0;
-
-    if ((fin = fs_open(filename, "r")))
-    {
-        res = sol_load_head(fin, fp);
-        fs_close(fin);
-    }
-    return res;
-}
-
-/*---------------------------------------------------------------------------*/
-
-static void sol_stor_mtrl(fs_file fout, struct s_mtrl *mp)
-{
-    put_array(fout, mp->d, 4);
-    put_array(fout, mp->a, 4);
-    put_array(fout, mp->s, 4);
-    put_array(fout, mp->e, 4);
-    put_array(fout, mp->h, 1);
-    put_index(fout, mp->fl);
-
-    fs_write(mp->f, 1, PATHMAX, fout);
-}
-
-static void sol_stor_vert(fs_file fout, struct s_vert *vp)
-{
-    put_array(fout,  vp->p, 3);
-}
-
-static void sol_stor_edge(fs_file fout, struct s_edge *ep)
-{
-    put_index(fout, ep->vi);
-    put_index(fout, ep->vj);
-}
-
-static void sol_stor_side(fs_file fout, struct s_side *sp)
-{
-    put_array(fout, sp->n, 3);
-    put_float(fout, sp->d);
-}
-
-static void sol_stor_texc(fs_file fout, struct s_texc *tp)
-{
-    put_array(fout,  tp->u, 2);
-}
-
-static void sol_stor_geom(fs_file fout, struct s_geom *gp)
-{
-    put_index(fout, gp->mi);
-    put_index(fout, gp->ti);
-    put_index(fout, gp->si);
-    put_index(fout, gp->vi);
-    put_index(fout, gp->tj);
-    put_index(fout, gp->sj);
-    put_index(fout, gp->vj);
-    put_index(fout, gp->tk);
-    put_index(fout, gp->sk);
-    put_index(fout, gp->vk);
-}
-
-static void sol_stor_lump(fs_file fout, struct s_lump *lp)
-{
-    put_index(fout, lp->fl);
-    put_index(fout, lp->v0);
-    put_index(fout, lp->vc);
-    put_index(fout, lp->e0);
-    put_index(fout, lp->ec);
-    put_index(fout, lp->g0);
-    put_index(fout, lp->gc);
-    put_index(fout, lp->s0);
-    put_index(fout, lp->sc);
-}
-
-static void sol_stor_node(fs_file fout, struct s_node *np)
-{
-    put_index(fout, np->si);
-    put_index(fout, np->ni);
-    put_index(fout, np->nj);
-    put_index(fout, np->l0);
-    put_index(fout, np->lc);
-}
-
-static void sol_stor_path(fs_file fout, struct s_path *pp)
-{
-    put_array(fout, pp->p, 3);
-    put_float(fout, pp->t);
-    put_index(fout, pp->pi);
-    put_index(fout, pp->f);
-    put_index(fout, pp->s);
-    put_index(fout, pp->fl);
-
-    if (pp->fl & P_ORIENTED)
-        put_array(fout, pp->e, 4);
-}
-
-static void sol_stor_body(fs_file fout, struct s_body *bp)
-{
-    put_index(fout, bp->pi);
-    put_index(fout, bp->ni);
-    put_index(fout, bp->l0);
-    put_index(fout, bp->lc);
-    put_index(fout, bp->g0);
-    put_index(fout, bp->gc);
-}
-
-static void sol_stor_item(fs_file fout, struct s_item *hp)
-{
-    put_array(fout, hp->p, 3);
-    put_index(fout, hp->t);
-    put_index(fout, hp->n);
-}
-
-static void sol_stor_goal(fs_file fout, struct s_goal *zp)
-{
-    put_array(fout, zp->p, 3);
-    put_float(fout, zp->r);
-}
-
-static void sol_stor_swch(fs_file fout, struct s_swch *xp)
-{
-    put_array(fout, xp->p, 3);
-    put_float(fout, xp->r);
-    put_index(fout, xp->pi);
-    put_float(fout, xp->t0);
-    put_float(fout, xp->t);
-    put_index(fout, xp->f0);
-    put_index(fout, xp->f);
-    put_index(fout, xp->i);
-}
-
-static void sol_stor_bill(fs_file fout, struct s_bill *rp)
-{
-    put_index(fout, rp->fl);
-    put_index(fout, rp->mi);
-    put_float(fout, rp->t);
-    put_float(fout, rp->d);
-    put_array(fout, rp->w,  3);
-    put_array(fout, rp->h,  3);
-    put_array(fout, rp->rx, 3);
-    put_array(fout, rp->ry, 3);
-    put_array(fout, rp->rz, 3);
-    put_array(fout, rp->p,  3);
-}
-
-static void sol_stor_jump(fs_file fout, struct s_jump *jp)
-{
-    put_array(fout, jp->p, 3);
-    put_array(fout, jp->q, 3);
-    put_float(fout, jp->r);
-}
-
-static void sol_stor_ball(fs_file fout, struct s_ball *bp)
-{
-    put_array(fout, bp->p, 3);
-    put_float(fout, bp->r);
-}
-
-static void sol_stor_view(fs_file fout, struct s_view *wp)
-{
-    put_array(fout,  wp->p, 3);
-    put_array(fout,  wp->q, 3);
-}
-
-static void sol_stor_dict(fs_file fout, struct s_dict *dp)
-{
-    put_index(fout, dp->ai);
-    put_index(fout, dp->aj);
-}
-
-static void sol_stor_file(fs_file fout, struct s_file *fp)
-{
-    int i;
-    int magic   = SOL_MAGIC;
-    int version = SOL_VER_CURRENT;
-
-    put_index(fout, magic);
-    put_index(fout, version);
-
-    put_index(fout, fp->ac);
-    put_index(fout, fp->dc);
-    put_index(fout, fp->mc);
-    put_index(fout, fp->vc);
-    put_index(fout, fp->ec);
-    put_index(fout, fp->sc);
-    put_index(fout, fp->tc);
-    put_index(fout, fp->gc);
-    put_index(fout, fp->lc);
-    put_index(fout, fp->nc);
-    put_index(fout, fp->pc);
-    put_index(fout, fp->bc);
-    put_index(fout, fp->hc);
-    put_index(fout, fp->zc);
-    put_index(fout, fp->jc);
-    put_index(fout, fp->xc);
-    put_index(fout, fp->rc);
-    put_index(fout, fp->uc);
-    put_index(fout, fp->wc);
-    put_index(fout, fp->ic);
-
-    fs_write(fp->av, 1, fp->ac, fout);
-
-    for (i = 0; i < fp->dc; i++) sol_stor_dict(fout, fp->dv + i);
-    for (i = 0; i < fp->mc; i++) sol_stor_mtrl(fout, fp->mv + i);
-    for (i = 0; i < fp->vc; i++) sol_stor_vert(fout, fp->vv + i);
-    for (i = 0; i < fp->ec; i++) sol_stor_edge(fout, fp->ev + i);
-    for (i = 0; i < fp->sc; i++) sol_stor_side(fout, fp->sv + i);
-    for (i = 0; i < fp->tc; i++) sol_stor_texc(fout, fp->tv + i);
-    for (i = 0; i < fp->gc; i++) sol_stor_geom(fout, fp->gv + i);
-    for (i = 0; i < fp->lc; i++) sol_stor_lump(fout, fp->lv + i);
-    for (i = 0; i < fp->nc; i++) sol_stor_node(fout, fp->nv + i);
-    for (i = 0; i < fp->pc; i++) sol_stor_path(fout, fp->pv + i);
-    for (i = 0; i < fp->bc; i++) sol_stor_body(fout, fp->bv + i);
-    for (i = 0; i < fp->hc; i++) sol_stor_item(fout, fp->hv + i);
-    for (i = 0; i < fp->zc; i++) sol_stor_goal(fout, fp->zv + i);
-    for (i = 0; i < fp->jc; i++) sol_stor_jump(fout, fp->jv + i);
-    for (i = 0; i < fp->xc; i++) sol_stor_swch(fout, fp->xv + i);
-    for (i = 0; i < fp->rc; i++) sol_stor_bill(fout, fp->rv + i);
-    for (i = 0; i < fp->uc; i++) sol_stor_ball(fout, fp->uv + i);
-    for (i = 0; i < fp->wc; i++) sol_stor_view(fout, fp->wv + i);
-    for (i = 0; i < fp->ic; i++) put_index(fout, fp->iv[i]);
-}
-
-/*---------------------------------------------------------------------------*/
-
-int sol_stor(struct s_file *fp, const char *filename)
-{
-    fs_file fout;
-
-    if ((fout = fs_open(filename, "w")))
-    {
-        sol_stor_file(fout, fp);
-        fs_close(fout);
-
-        return 1;
-    }
-    return 0;
-}
-
-void sol_free(struct s_file *fp)
-{
-    if (fp->av) free(fp->av);
-    if (fp->mv) free(fp->mv);
-    if (fp->vv) free(fp->vv);
-    if (fp->ev) free(fp->ev);
-    if (fp->sv) free(fp->sv);
-    if (fp->tv) free(fp->tv);
-    if (fp->gv) free(fp->gv);
-    if (fp->lv) free(fp->lv);
-    if (fp->nv) free(fp->nv);
-    if (fp->pv) free(fp->pv);
-    if (fp->bv) free(fp->bv);
-    if (fp->hv) free(fp->hv);
-    if (fp->zv) free(fp->zv);
-    if (fp->jv) free(fp->jv);
-    if (fp->xv) free(fp->xv);
-    if (fp->rv) free(fp->rv);
-    if (fp->uv) free(fp->uv);
-    if (fp->wv) free(fp->wv);
-    if (fp->dv) free(fp->dv);
-    if (fp->iv) free(fp->iv);
-
-    memset(fp, 0, sizeof (struct s_file));
-}
-
-/*---------------------------------------------------------------------------*/
diff --git a/share/solid.h b/share/solid.h
deleted file mode 100644 (file)
index 23d1ae1..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (C) 2003 Robert Kooima
- *
- * NEVERBALL is  free software; you can redistribute  it and/or modify
- * it under the  terms of the GNU General  Public License as published
- * by the Free  Software Foundation; either version 2  of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
- * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
- * General Public License for more details.
- */
-
-#ifndef SOL_H
-#define SOL_H
-
-#include "glext.h"
-#include "base_config.h"
-
-/*
- * Some might  be taken  aback at  the terseness of  the names  of the
- * structure  members and  the variables  used by  the  functions that
- * access them.  Yes, yes, I know:  readability.  I  contend that once
- * the naming  convention is embraced, the names  become more readable
- * than any  verbose alternative, and their brevity  and uniformity do
- * more to augment readability than longVariableNames ever could.
- *
- * Members  and variables  are named  XY.   X determines  the type  of
- * structure to which the variable  refers.  Y determines the usage of
- * the variable.
- *
- * The Xs are as documented by struct s_file:
- *
- *     f  File          (struct s_file)
- *     m  Material      (struct s_mtrl)
- *     v  Vertex        (struct s_vert)
- *     e  Edge          (struct s_edge)
- *     s  Side          (struct s_side)
- *     t  Texture coord (struct s_texc)
- *     g  Geometry      (struct s_geom)
- *     l  Lump          (struct s_lump)
- *     n  Node          (struct s_node)
- *     p  Path          (struct s_path)
- *     b  Body          (struct s_body)
- *     h  Item          (struct s_item)
- *     z  Goal          (struct s_goal)
- *     j  Jump          (struct s_jump)
- *     x  Switch        (struct s_swch)
- *     r  Billboard     (struct s_bill)
- *     u  User          (struct s_ball)
- *     w  Viewpoint     (struct s_view)
- *     d  Dictionary    (struct s_dict)
- *     i  Index         (int)
- *     a  Text          (char)
- *
- * The Ys are as follows:
- *
- *     c  Counter
- *     p  Pointer
- *     v  Vector (array)
- *     0  Index of the first
- *     i  Index
- *     j  Subindex
- *     k  Subsubindex
- *
- * Thus "up" is a pointer to  a user structure.  "lc" is the number of
- * lumps.  "ei" and "ej" are  edge indices into some "ev" edge vector.
- * An edge is  defined by two vertices, so  an edge structure consists
- * of "vi" and "vj".  And so on.
- *
- * Those members that do not conform to this convention are explicitly
- * documented with a comment.
- *
- * These prefixes are still available: c k o q y.
- */
-
-/*---------------------------------------------------------------------------*/
-
-/* Material type flags */
-
-#define M_OPAQUE       1
-#define M_TRANSPARENT  2
-#define M_REFLECTIVE   4
-#define M_ENVIRONMENT  8
-#define M_ADDITIVE    16
-#define M_CLAMPED     32
-#define M_DECAL       64
-#define M_TWO_SIDED  128
-#define M_SHADOWED   256
-
-/* Billboard types. */
-
-#define B_EDGE     1
-#define B_FLAT     2
-#define B_ADDITIVE 4
-#define B_NOFACE   8
-
-/* Lump flags. */
-
-#define L_DETAIL   1
-
-/* Item types. */
-
-#define ITEM_NONE       0
-#define ITEM_COIN       1
-#define ITEM_GROW       2
-#define ITEM_SHRINK     3
-
-/* Path flags. */
-
-#define P_ORIENTED 1
-
-/*---------------------------------------------------------------------------*/
-
-struct s_mtrl
-{
-    float d[4];                                /* diffuse color              */
-    float a[4];                                /* ambient color              */
-    float s[4];                                /* specular color             */
-    float e[4];                                /* emission color             */
-    float h[1];                                /* specular exponent          */
-    float angle;
-
-    int fl;                                    /* material flags             */
-
-    GLuint o;                                  /* OpenGL texture object      */
-    char   f[PATHMAX];                         /* texture file name          */
-};
-
-struct s_vert
-{
-    float p[3];                                /* vertex position            */
-};
-
-struct s_edge
-{
-    int vi;
-    int vj;
-};
-
-struct s_side
-{
-    float n[3];                                /* plane normal vector        */
-    float d;                                   /* distance from origin       */
-};
-
-struct s_texc
-{
-    float u[2];                                /* texture coordinate         */
-};
-
-struct s_geom
-{
-    int mi;
-    int ti, si, vi;
-    int tj, sj, vj;
-    int tk, sk, vk;
-};
-
-struct s_lump
-{
-    int fl;                                    /* lump flags                 */
-    int v0, vc;
-    int e0, ec;
-    int g0, gc;
-    int s0, sc;
-};
-
-struct s_node
-{
-    int si;
-    int ni;
-    int nj;
-    int l0;
-    int lc;
-};
-
-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                */
-    int s;                                     /* smooth flag                */
-
-    int fl;                                    /* flags                      */
-
-    /* TODO: merge enable and smooth into flags. */
-};
-
-struct s_body
-{
-    float t;                                   /* time on current path       */
-    int   tm;                                  /* milliseconds               */
-
-    GLuint ol;                                 /* opaque geometry list       */
-    GLuint tl;                                 /* transparent geometry list  */
-    GLuint rl;                                 /* reflective geometry list   */
-    GLuint sl;                                 /* shadowed geometry list     */
-
-    int pi;
-    int ni;
-    int l0;
-    int lc;
-    int g0;
-    int gc;
-};
-
-struct s_item
-{
-    float p[3];                                /* position                   */
-    int   t;                                   /* type                       */
-    int   n;                                   /* value                      */
-};
-
-struct s_goal
-{
-    float p[3];                                /* position                   */
-    float r;                                   /* radius                     */
-};
-
-struct s_swch
-{
-    float p[3];                                /* position                   */
-    float r;                                   /* radius                     */
-    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?              */
-    int   e;                                   /* is a ball inside it?       */
-};
-
-struct s_bill
-{
-    int  fl;
-    int  mi;
-    float t;                                   /* repeat time interval       */
-    float d;                                   /* distance                   */
-
-    float w[3];                                /* width coefficients         */
-    float h[3];                                /* height coefficients        */
-
-    float rx[3];                               /* X rotation coefficients    */
-    float ry[3];                               /* Y rotation coefficients    */
-    float rz[3];                               /* Z rotation coefficients    */
-
-    float p[3];
-};
-
-struct s_jump
-{
-    float p[3];                                /* position                   */
-    float q[3];                                /* target position            */
-    float r;                                   /* radius                     */
-};
-
-struct s_ball
-{
-    float e[3][3];                             /* basis of orientation       */
-    float p[3];                                /* position vector            */
-    float v[3];                                /* velocity vector            */
-    float w[3];                                /* angular velocity vector    */
-    float E[3][3];                             /* basis of pendulum          */
-    float W[3];                                /* angular pendulum velocity  */
-    float r;                                   /* radius                     */
-};
-
-struct s_view
-{
-    float p[3];
-    float q[3];
-};
-
-struct s_dict
-{
-    int ai;
-    int aj;
-};
-
-struct s_file
-{
-    int ac;
-    int mc;
-    int vc;
-    int ec;
-    int sc;
-    int tc;
-    int gc;
-    int lc;
-    int nc;
-    int pc;
-    int bc;
-    int hc;
-    int zc;
-    int jc;
-    int xc;
-    int rc;
-    int uc;
-    int wc;
-    int dc;
-    int ic;
-
-    char          *av;
-    struct s_mtrl *mv;
-    struct s_vert *vv;
-    struct s_edge *ev;
-    struct s_side *sv;
-    struct s_texc *tv;
-    struct s_geom *gv;
-    struct s_lump *lv;
-    struct s_node *nv;
-    struct s_path *pv;
-    struct s_body *bv;
-    struct s_item *hv;
-    struct s_goal *zv;
-    struct s_jump *jv;
-    struct s_swch *xv;
-    struct s_bill *rv;
-    struct s_ball *uv;
-    struct s_view *wv;
-    struct s_dict *dv;
-    int           *iv;
-};
-
-/*---------------------------------------------------------------------------*/
-
-int   sol_load_only_file(struct s_file *, const char *);
-int   sol_load_only_head(struct s_file *, const char *);
-int   sol_stor(struct s_file *, const char *);
-void  sol_free(struct s_file *);
-
-/*---------------------------------------------------------------------------*/
-
-#endif
index ea2836c..eb828ee 100644 (file)
@@ -17,7 +17,8 @@
 
 #include "solid_all.h"
 #include "solid_cmd.h"
-#include "solid.h"
+#include "solid_vary.h"
+
 #include "common.h"
 #include "vec3.h"
 #include "geom.h"
@@ -36,14 +37,14 @@ static float derp(float t)
 }
 #endif
 
-void sol_body_p(float p[3], const struct s_file *fp, int pi, float t)
+void sol_body_p(float p[3], const struct s_vary *vary, int pi, float t)
 {
     float v[3];
 
     if (pi >= 0)
     {
-        const struct s_path *pp = fp->pv + pi;
-        const struct s_path *pq = fp->pv + pp->pi;
+        const struct b_path *pp = vary->base->pv + pi;
+        const struct b_path *pq = vary->base->pv + pp->pi;
 
         float s = MIN(t / pp->t, 1.0f);
 
@@ -59,15 +60,15 @@ void sol_body_p(float p[3], const struct s_file *fp, int pi, float t)
 }
 
 void sol_body_v(float v[3],
-                const struct s_file *fp,
+                const struct s_vary *vary,
                 int pi, float t, float dt)
 {
-    if (pi >= 0 && fp->pv[pi].f)
+    if (pi >= 0 && vary->pv[pi].f)
     {
         float p[3], q[3];
 
-        sol_body_p(p, fp, pi, t);
-        sol_body_p(q, fp, pi, t + dt);
+        sol_body_p(p, vary, pi, t);
+        sol_body_p(q, vary, pi, t + dt);
 
         v_sub(v, q, p);
 
@@ -84,19 +85,19 @@ void sol_body_v(float v[3],
 }
 
 void sol_body_e(float e[4],
-                const struct s_file *fp,
-                const struct s_body *bp,
+                const struct s_vary *vary,
+                const struct v_body *bp,
                 float dt)
 {
-    struct s_path *pp = fp->pv + bp->pi;
+    struct b_path *pp = vary->base->pv + bp->pi;
 
     if (bp->pi >= 0)
     {
-        struct s_path *pq = fp->pv + pp->pi;
+        struct b_path *pq = vary->base->pv + pp->pi;
 
         if (pp->fl & P_ORIENTED || pq->fl & P_ORIENTED)
         {
-            if (!pp->f)
+            if (!vary->pv[bp->pi].f)
                 dt = 0;
 
             q_slerp(e, pp->e, pq->e, (bp->t + dt) / pp->t);
@@ -111,14 +112,14 @@ void sol_body_e(float e[4],
 }
 
 void sol_body_w(float w[3],
-                const struct s_file *fp,
-                const struct s_body *bp)
+                const struct s_vary *vary,
+                const struct v_body *bp)
 {
-    struct s_path *pp = fp->pv + bp->pi;
+    struct b_path *pp = vary->base->pv + bp->pi;
 
-    if (bp->pi >= 0 && pp->f)
+    if (bp->pi >= 0 && vary->pv[bp->pi].f)
     {
-        struct s_path *pq = fp->pv + pp->pi;
+        struct b_path *pq = vary->base->pv + pp->pi;
 
         if (pp->fl & P_ORIENTED || pq->fl & P_ORIENTED)
         {
@@ -200,7 +201,7 @@ void sol_rotate(float e[3][3], const float w[3], float dt)
  * Compute the new angular velocity and orientation of a ball pendulum.
  * A gives the accelleration of the ball.  G gives the gravity vector.
  */
-void sol_pendulum(struct s_ball *up,
+void sol_pendulum(struct v_ball *up,
                   const float a[3],
                   const float g[3], float dt)
 {
@@ -248,22 +249,22 @@ void sol_pendulum(struct s_ball *up,
 
 /*---------------------------------------------------------------------------*/
 
-static void sol_path_flag(struct s_file *fp, int pi, int f)
+static void sol_path_flag(struct s_vary *vary, int pi, int f)
 {
     union cmd cmd;
 
-    if (fp->pv[pi].f == f)
+    if (vary->pv[pi].f == f)
         return;
 
-    fp->pv[pi].f = f;
+    vary->pv[pi].f = f;
 
     cmd.type = CMD_PATH_FLAG;
     cmd.pathflag.pi = pi;
-    cmd.pathflag.f = fp->pv[pi].f;
+    cmd.pathflag.f = vary->pv[pi].f;
     sol_cmd_enq(&cmd);
 }
 
-static void sol_path_loop(struct s_file *fp, int p0, int f)
+static void sol_path_loop(struct s_vary *vary, int p0, int f)
 {
     int pi = p0;
     int pj = p0;
@@ -271,11 +272,11 @@ static void sol_path_loop(struct s_file *fp, int p0, int f)
 
     do  /* Tortoise and hare cycle traverser. */
     {
-        sol_path_flag(fp, pi, f);
+        sol_path_flag(vary, pi, f);
 
-        pi = fp->pv[pi].pi;
-        pj = fp->pv[pj].pi;
-        pj = fp->pv[pj].pi;
+        pi = vary->base->pv[pi].pi;
+        pj = vary->base->pv[pj].pi;
+        pj = vary->base->pv[pj].pi;
     }
     while (pi != pj);
 
@@ -292,10 +293,10 @@ static void sol_path_loop(struct s_file *fp, int p0, int f)
 
     do
     {
-        sol_path_flag(fp, pi, f);
+        sol_path_flag(vary, pi, f);
 
-        pi = fp->pv[pi].pi;
-        pj = fp->pv[pj].pi;
+        pi = vary->base->pv[pi].pi;
+        pj = vary->base->pv[pj].pi;
     }
     while (pi != pj && pi != pk);
 }
@@ -305,26 +306,26 @@ 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, int ms)
+void sol_swch_step(struct s_vary *vary, float dt, int ms)
 {
     int xi;
 
     union cmd cmd;
 
-    for (xi = 0; xi < fp->xc; xi++)
+    for (xi = 0; xi < vary->xc; xi++)
     {
-        struct s_swch *xp = fp->xv + xi;
+        struct v_swch *xp = vary->xv + xi;
 
-        if (xp->tm < xp->t0m)
+        if (xp->tm < xp->base->tm)
         {
             xp->t += dt;
             xp->tm += ms;
 
-            if (xp->tm >= xp->t0m)
+            if (xp->tm >= xp->base->tm)
             {
-                sol_path_loop(fp, xp->pi, xp->f0);
+                sol_path_loop(vary, xp->base->pi, xp->base->f);
 
-                xp->f = xp->f0;
+                xp->f = xp->base->f;
 
                 cmd.type = CMD_SWCH_TOGGLE;
                 cmd.swchtoggle.xi = xi;
@@ -337,27 +338,27 @@ void sol_swch_step(struct s_file *fp, float dt, int ms)
 /*
  * Compute the positions of all bodies after DT seconds have passed.
  */
-void sol_body_step(struct s_file *fp, float dt, int ms)
+void sol_body_step(struct s_vary *vary, float dt, int ms)
 {
     int i;
 
     union cmd cmd;
 
-    for (i = 0; i < fp->bc; i++)
+    for (i = 0; i < vary->bc; i++)
     {
-        struct s_body *bp = fp->bv + i;
-        struct s_path *pp = fp->pv + bp->pi;
+        struct v_body *bp = vary->bv + i;
+        struct v_path *pp = vary->pv + bp->pi;
 
         if (bp->pi >= 0 && pp->f)
         {
             bp->t += dt;
             bp->tm += ms;
 
-            if (bp->tm >= pp->tm)
+            if (bp->tm >= pp->base->tm)
             {
                 bp->t  = 0;
                 bp->tm = 0;
-                bp->pi = pp->pi;
+                bp->pi = pp->base->pi;
 
                 cmd.type        = CMD_BODY_TIME;
                 cmd.bodytime.bi = i;
@@ -376,13 +377,13 @@ void sol_body_step(struct s_file *fp, float dt, int ms)
 /*
  * Compute the positions of all balls after DT seconds have passed.
  */
-void sol_ball_step(struct s_file *fp, float dt)
+void sol_ball_step(struct s_vary *vary, float dt)
 {
     int i;
 
-    for (i = 0; i < fp->uc; i++)
+    for (i = 0; i < vary->uc; i++)
     {
-        struct s_ball *up = fp->uv + i;
+        struct v_ball *up = vary->uv + i;
 
         v_mad(up->p, up->p, up->v, dt);
 
@@ -392,15 +393,15 @@ void sol_ball_step(struct s_file *fp, float dt)
 
 /*---------------------------------------------------------------------------*/
 
-int sol_item_test(struct s_file *fp, float *p, float item_r)
+int sol_item_test(struct s_vary *vary, float *p, float item_r)
 {
-    const float *ball_p = fp->uv->p;
-    const float  ball_r = fp->uv->r;
+    const float *ball_p = vary->uv->p;
+    const float  ball_r = vary->uv->r;
     int hi;
 
-    for (hi = 0; hi < fp->hc; hi++)
+    for (hi = 0; hi < vary->hc; hi++)
     {
-        struct s_item *hp = fp->hv + hi;
+        struct v_item *hp = vary->hv + hi;
         float r[3];
 
         v_sub(r, ball_p, hp->p);
@@ -417,15 +418,15 @@ int sol_item_test(struct s_file *fp, float *p, float item_r)
     return -1;
 }
 
-struct s_goal *sol_goal_test(struct s_file *fp, float *p, int ui)
+struct b_goal *sol_goal_test(struct s_vary *vary, float *p, int ui)
 {
-    const float *ball_p = fp->uv[ui].p;
-    const float  ball_r = fp->uv[ui].r;
+    const float *ball_p = vary->uv[ui].p;
+    const float  ball_r = vary->uv[ui].r;
     int zi;
 
-    for (zi = 0; zi < fp->zc; zi++)
+    for (zi = 0; zi < vary->base->zc; zi++)
     {
-        struct s_goal *zp = fp->zv + zi;
+        struct b_goal *zp = vary->base->zv + zi;
         float r[3];
 
         r[0] = ball_p[0] - zp->p[0];
@@ -449,15 +450,15 @@ struct s_goal *sol_goal_test(struct s_file *fp, float *p, int ui)
 /*
  * Test for a ball entering a teleporter.
  */
-int sol_jump_test(struct s_file *fp, float *p, int ui)
+int sol_jump_test(struct s_vary *vary, float *p, int ui)
 {
-    const float *ball_p = fp->uv[ui].p;
-    const float  ball_r = fp->uv[ui].r;
+    const float *ball_p = vary->uv[ui].p;
+    const float  ball_r = vary->uv[ui].r;
     int ji, in = 0;
 
-    for (ji = 0; ji < fp->jc; ji++)
+    for (ji = 0; ji < vary->base->jc; ji++)
     {
-        struct s_jump *jp = fp->jv + ji;
+        struct b_jump *jp = vary->base->jv + ji;
         float d, r[3];
 
         r[0] = ball_p[0] - jp->p[0];
@@ -496,32 +497,32 @@ int sol_jump_test(struct s_file *fp, float *p, int ui)
 /*
  * Test for a ball entering a switch.
  */
-int sol_swch_test(struct s_file *fp, int ui)
+int sol_swch_test(struct s_vary *vary, int ui)
 {
-    const float *ball_p = fp->uv[ui].p;
-    const float  ball_r = fp->uv[ui].r;
+    const float *ball_p = vary->uv[ui].p;
+    const float  ball_r = vary->uv[ui].r;
 
     union cmd cmd;
 
     int xi, rc = SWCH_OUTSIDE;
 
-    for (xi = 0; xi < fp->xc; xi++)
+    for (xi = 0; xi < vary->xc; xi++)
     {
-        struct s_swch *xp = fp->xv + xi;
+        struct v_swch *xp = vary->xv + xi;
 
         /* FIXME enter/exit events don't work for timed switches */
 
-        if (xp->t0m == 0 || xp->f == xp->f0)
+        if (xp->base->t == 0 || xp->f == xp->base->f)
         {
             float d, r[3];
 
-            r[0] = ball_p[0] - xp->p[0];
-            r[1] = ball_p[2] - xp->p[2];
+            r[0] = ball_p[0] - xp->base->p[0];
+            r[1] = ball_p[2] - xp->base->p[2];
             r[2] = 0;
 
             /* Distance of the far side from the edge of the halo. */
 
-            d = v_len(r) + ball_r - xp->r;
+            d = v_len(r) + ball_r - xp->base->r;
 
             /*
              * The  "inside" distance,  which must  be  cleared before
@@ -530,14 +531,14 @@ int sol_swch_test(struct s_file *fp, int ui)
              */
 
             if (d <= ball_r * 2 &&
-                ball_p[1] > xp->p[1] &&
-                ball_p[1] < xp->p[1] + SWCH_HEIGHT / 2)
+                ball_p[1] > xp->base->p[1] &&
+                ball_p[1] < xp->base->p[1] + SWCH_HEIGHT / 2)
             {
                 if (!xp->e && d <= 0.0f)
                 {
                     /* The ball enters. */
 
-                    if (xp->t0m == 0)
+                    if (xp->base->tm == 0)
                     {
                         xp->e = 1;
 
@@ -554,11 +555,11 @@ int sol_swch_test(struct s_file *fp, int ui)
                     cmd.swchtoggle.xi = xi;
                     sol_cmd_enq(&cmd);
 
-                    sol_path_loop(fp, xp->pi, xp->f);
+                    sol_path_loop(vary, xp->base->pi, xp->f);
 
                     /* It toggled to non-default state, start the timer. */
 
-                    if (xp->f != xp->f0)
+                    if (xp->f != xp->base->f)
                     {
                         xp->t = 0.0f;
                         xp->tm = 0;
@@ -566,7 +567,7 @@ int sol_swch_test(struct s_file *fp, int ui)
 
                     /* If visible, set the result. */
 
-                    if (!xp->i)
+                    if (!xp->base->i)
                         rc = SWCH_TRIGGER;
                 }
             }
index 56ecbfc..d6d2c6a 100644 (file)
@@ -1,24 +1,23 @@
 #ifndef SOLID_ALL_H
 #define SOLID_ALL_H
 
-#include "solid.h"
+#include "solid_vary.h"
 
-void sol_body_p(float p[3], const struct s_file *fp, int pi, float t);
-void sol_body_v(float v[3], const struct s_file *fp, int pi, float t, float dt);
-void sol_body_e(float e[3],
-                const struct s_file *fp,
-                const struct s_body *bp, float dt);
-void sol_body_w(float w[3], const struct s_file *fp, const struct s_body *bp);
+void sol_body_p(float p[3], const struct s_vary *, int pi, float t);
+void sol_body_v(float v[3], const struct s_vary *, int pi, float t, float dt);
+void sol_body_e(float e[3], const struct s_vary *, const struct v_body *bp,
+                float dt);
+void sol_body_w(float w[3], const struct s_vary *, const struct v_body *bp);
 
 void sol_rotate(float e[3][3], const float w[3], float dt);
 
-void sol_pendulum(struct s_ball *up,
+void sol_pendulum(struct v_ball *up,
                   const float a[3],
                   const float g[3], 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);
+void sol_swch_step(struct s_vary *, float dt, int ms);
+void sol_body_step(struct s_vary *, float dt, int ms);
+void sol_ball_step(struct s_vary *, float dt);
 
 enum
 {
@@ -34,9 +33,9 @@ enum
     SWCH_INSIDE
 };
 
-int            sol_item_test(struct s_file *fp, float *p, float item_r);
-struct s_goal *sol_goal_test(struct s_file *fp, float *p, int ui);
-int            sol_jump_test(struct s_file *fp, float *p, int ui);
-int            sol_swch_test(struct s_file *fp, int ui);
+int            sol_item_test(struct s_vary *, float *p, float item_r);
+struct b_goal *sol_goal_test(struct s_vary *, float *p, int ui);
+int            sol_jump_test(struct s_vary *, float *p, int ui);
+int            sol_swch_test(struct s_vary *, int ui);
 
 #endif
diff --git a/share/solid_base.c b/share/solid_base.c
new file mode 100644 (file)
index 0000000..dbbff30
--- /dev/null
@@ -0,0 +1,635 @@
+/*
+ * Copyright (C) 2003 Robert Kooima
+ *
+ * NEVERBALL is  free software; you can redistribute  it and/or modify
+ * it under the  terms of the GNU General  Public License as published
+ * by the Free  Software Foundation; either version 2  of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
+ * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
+ * General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "solid_base.h"
+#include "base_config.h"
+#include "binary.h"
+#include "common.h"
+#include "fs.h"
+#include "vec3.h"
+
+enum
+{
+    SOL_VER_MINIMUM = 6,
+    SOL_VER_PATH_FLAGS,
+    SOL_VER_CURRENT = SOL_VER_PATH_FLAGS
+};
+
+#define SOL_MAGIC (0xAF | 'S' << 8 | 'O' << 16 | 'L' << 24)
+
+/*---------------------------------------------------------------------------*/
+
+static int sol_version;
+
+static int sol_file(fs_file fin)
+{
+    int magic;
+    int version;
+
+    get_index(fin, &magic);
+    get_index(fin, &version);
+
+    if (magic != SOL_MAGIC || (version < SOL_VER_MINIMUM ||
+                               version > SOL_VER_CURRENT))
+        return 0;
+
+    sol_version = version;
+
+    return 1;
+}
+
+static void sol_load_mtrl(fs_file fin, struct b_mtrl *mp)
+{
+    get_array(fin,  mp->d, 4);
+    get_array(fin,  mp->a, 4);
+    get_array(fin,  mp->s, 4);
+    get_array(fin,  mp->e, 4);
+    get_array(fin,  mp->h, 1);
+    get_index(fin, &mp->fl);
+
+    fs_read(mp->f, 1, PATHMAX, fin);
+}
+
+static void sol_load_vert(fs_file fin, struct b_vert *vp)
+{
+    get_array(fin,  vp->p, 3);
+}
+
+static void sol_load_edge(fs_file fin, struct b_edge *ep)
+{
+    get_index(fin, &ep->vi);
+    get_index(fin, &ep->vj);
+}
+
+static void sol_load_side(fs_file fin, struct b_side *sp)
+{
+    get_array(fin,  sp->n, 3);
+    get_float(fin, &sp->d);
+}
+
+static void sol_load_texc(fs_file fin, struct b_texc *tp)
+{
+    get_array(fin,  tp->u, 2);
+}
+
+static void sol_load_geom(fs_file fin, struct b_geom *gp)
+{
+    get_index(fin, &gp->mi);
+    get_index(fin, &gp->ti);
+    get_index(fin, &gp->si);
+    get_index(fin, &gp->vi);
+    get_index(fin, &gp->tj);
+    get_index(fin, &gp->sj);
+    get_index(fin, &gp->vj);
+    get_index(fin, &gp->tk);
+    get_index(fin, &gp->sk);
+    get_index(fin, &gp->vk);
+}
+
+static void sol_load_lump(fs_file fin, struct b_lump *lp)
+{
+    get_index(fin, &lp->fl);
+    get_index(fin, &lp->v0);
+    get_index(fin, &lp->vc);
+    get_index(fin, &lp->e0);
+    get_index(fin, &lp->ec);
+    get_index(fin, &lp->g0);
+    get_index(fin, &lp->gc);
+    get_index(fin, &lp->s0);
+    get_index(fin, &lp->sc);
+}
+
+static void sol_load_node(fs_file fin, struct b_node *np)
+{
+    get_index(fin, &np->si);
+    get_index(fin, &np->ni);
+    get_index(fin, &np->nj);
+    get_index(fin, &np->l0);
+    get_index(fin, &np->lc);
+}
+
+static void sol_load_path(fs_file fin, struct b_path *pp)
+{
+    get_array(fin,  pp->p, 3);
+    get_float(fin, &pp->t);
+    get_index(fin, &pp->pi);
+    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);
+
+    pp->e[0] = 1.0f;
+    pp->e[1] = 0.0f;
+    pp->e[2] = 0.0f;
+    pp->e[3] = 0.0f;
+
+    if (pp->fl & P_ORIENTED)
+        get_array(fin, pp->e, 4);
+}
+
+static void sol_load_body(fs_file fin, struct b_body *bp)
+{
+    get_index(fin, &bp->pi);
+    get_index(fin, &bp->ni);
+    get_index(fin, &bp->l0);
+    get_index(fin, &bp->lc);
+    get_index(fin, &bp->g0);
+    get_index(fin, &bp->gc);
+}
+
+static void sol_load_item(fs_file fin, struct b_item *hp)
+{
+    get_array(fin,  hp->p, 3);
+    get_index(fin, &hp->t);
+    get_index(fin, &hp->n);
+}
+
+static void sol_load_goal(fs_file fin, struct b_goal *zp)
+{
+    get_array(fin,  zp->p, 3);
+    get_float(fin, &zp->r);
+}
+
+static void sol_load_swch(fs_file fin, struct b_swch *xp)
+{
+    float f;
+    int i;
+
+    get_array(fin,  xp->p, 3);
+    get_float(fin, &xp->r);
+    get_index(fin, &xp->pi);
+    get_float(fin, &xp->t);
+    get_float(fin, &f);
+    get_index(fin, &xp->f);
+    get_index(fin, &i);
+    get_index(fin, &xp->i);
+
+    xp->tm = TIME_TO_MS(xp->t);
+    xp->t = MS_TO_TIME(xp->tm);
+}
+
+static void sol_load_bill(fs_file fin, struct b_bill *rp)
+{
+    get_index(fin, &rp->fl);
+    get_index(fin, &rp->mi);
+    get_float(fin, &rp->t);
+    get_float(fin, &rp->d);
+    get_array(fin,  rp->w,  3);
+    get_array(fin,  rp->h,  3);
+    get_array(fin,  rp->rx, 3);
+    get_array(fin,  rp->ry, 3);
+    get_array(fin,  rp->rz, 3);
+    get_array(fin,  rp->p,  3);
+}
+
+static void sol_load_jump(fs_file fin, struct b_jump *jp)
+{
+    get_array(fin,  jp->p, 3);
+    get_array(fin,  jp->q, 3);
+    get_float(fin, &jp->r);
+}
+
+static void sol_load_ball(fs_file fin, struct b_ball *bp)
+{
+    get_array(fin,  bp->p, 3);
+    get_float(fin, &bp->r);
+}
+
+static void sol_load_view(fs_file fin, struct b_view *wp)
+{
+    get_array(fin,  wp->p, 3);
+    get_array(fin,  wp->q, 3);
+}
+
+static void sol_load_dict(fs_file fin, struct b_dict *dp)
+{
+    get_index(fin, &dp->ai);
+    get_index(fin, &dp->aj);
+}
+
+static void sol_load_indx(fs_file fin, struct s_base *fp)
+{
+    get_index(fin, &fp->ac);
+    get_index(fin, &fp->dc);
+    get_index(fin, &fp->mc);
+    get_index(fin, &fp->vc);
+    get_index(fin, &fp->ec);
+    get_index(fin, &fp->sc);
+    get_index(fin, &fp->tc);
+    get_index(fin, &fp->gc);
+    get_index(fin, &fp->lc);
+    get_index(fin, &fp->nc);
+    get_index(fin, &fp->pc);
+    get_index(fin, &fp->bc);
+    get_index(fin, &fp->hc);
+    get_index(fin, &fp->zc);
+    get_index(fin, &fp->jc);
+    get_index(fin, &fp->xc);
+    get_index(fin, &fp->rc);
+    get_index(fin, &fp->uc);
+    get_index(fin, &fp->wc);
+    get_index(fin, &fp->ic);
+}
+
+static int sol_load_file(fs_file fin, struct s_base *fp)
+{
+    int i;
+
+    if (!sol_file(fin))
+        return 0;
+
+    sol_load_indx(fin, fp);
+
+    if (fp->ac)
+        fp->av = (char *)          calloc(fp->ac, sizeof (*fp->av));
+    if (fp->mc)
+        fp->mv = (struct b_mtrl *) calloc(fp->mc, sizeof (*fp->mv));
+    if (fp->vc)
+        fp->vv = (struct b_vert *) calloc(fp->vc, sizeof (*fp->vv));
+    if (fp->ec)
+        fp->ev = (struct b_edge *) calloc(fp->ec, sizeof (*fp->ev));
+    if (fp->sc)
+        fp->sv = (struct b_side *) calloc(fp->sc, sizeof (*fp->sv));
+    if (fp->tc)
+        fp->tv = (struct b_texc *) calloc(fp->tc, sizeof (*fp->tv));
+    if (fp->gc)
+        fp->gv = (struct b_geom *) calloc(fp->gc, sizeof (*fp->gv));
+    if (fp->lc)
+        fp->lv = (struct b_lump *) calloc(fp->lc, sizeof (*fp->lv));
+    if (fp->nc)
+        fp->nv = (struct b_node *) calloc(fp->nc, sizeof (*fp->nv));
+    if (fp->pc)
+        fp->pv = (struct b_path *) calloc(fp->pc, sizeof (*fp->pv));
+    if (fp->bc)
+        fp->bv = (struct b_body *) calloc(fp->bc, sizeof (*fp->bv));
+    if (fp->hc)
+        fp->hv = (struct b_item *) calloc(fp->hc, sizeof (*fp->hv));
+    if (fp->zc)
+        fp->zv = (struct b_goal *) calloc(fp->zc, sizeof (*fp->zv));
+    if (fp->jc)
+        fp->jv = (struct b_jump *) calloc(fp->jc, sizeof (*fp->jv));
+    if (fp->xc)
+        fp->xv = (struct b_swch *) calloc(fp->xc, sizeof (*fp->xv));
+    if (fp->rc)
+        fp->rv = (struct b_bill *) calloc(fp->rc, sizeof (*fp->rv));
+    if (fp->uc)
+        fp->uv = (struct b_ball *) calloc(fp->uc, sizeof (*fp->uv));
+    if (fp->wc)
+        fp->wv = (struct b_view *) calloc(fp->wc, sizeof (*fp->wv));
+    if (fp->dc)
+        fp->dv = (struct b_dict *) calloc(fp->dc, sizeof (*fp->dv));
+    if (fp->ic)
+        fp->iv = (int *)           calloc(fp->ic, sizeof (*fp->iv));
+
+    if (fp->ac)
+        fs_read(fp->av, 1, fp->ac, fin);
+
+    for (i = 0; i < fp->dc; i++) sol_load_dict(fin, fp->dv + i);
+    for (i = 0; i < fp->mc; i++) sol_load_mtrl(fin, fp->mv + i);
+    for (i = 0; i < fp->vc; i++) sol_load_vert(fin, fp->vv + i);
+    for (i = 0; i < fp->ec; i++) sol_load_edge(fin, fp->ev + i);
+    for (i = 0; i < fp->sc; i++) sol_load_side(fin, fp->sv + i);
+    for (i = 0; i < fp->tc; i++) sol_load_texc(fin, fp->tv + i);
+    for (i = 0; i < fp->gc; i++) sol_load_geom(fin, fp->gv + i);
+    for (i = 0; i < fp->lc; i++) sol_load_lump(fin, fp->lv + i);
+    for (i = 0; i < fp->nc; i++) sol_load_node(fin, fp->nv + i);
+    for (i = 0; i < fp->pc; i++) sol_load_path(fin, fp->pv + i);
+    for (i = 0; i < fp->bc; i++) sol_load_body(fin, fp->bv + i);
+    for (i = 0; i < fp->hc; i++) sol_load_item(fin, fp->hv + i);
+    for (i = 0; i < fp->zc; i++) sol_load_goal(fin, fp->zv + i);
+    for (i = 0; i < fp->jc; i++) sol_load_jump(fin, fp->jv + i);
+    for (i = 0; i < fp->xc; i++) sol_load_swch(fin, fp->xv + i);
+    for (i = 0; i < fp->rc; i++) sol_load_bill(fin, fp->rv + i);
+    for (i = 0; i < fp->uc; i++) sol_load_ball(fin, fp->uv + i);
+    for (i = 0; i < fp->wc; i++) sol_load_view(fin, fp->wv + i);
+    for (i = 0; i < fp->ic; i++) get_index(fin, fp->iv + i);
+
+    return 1;
+}
+
+static int sol_load_head(fs_file fin, struct s_base *fp)
+{
+    if (!sol_file(fin))
+        return 0;
+
+    sol_load_indx(fin, fp);
+
+    if (fp->ac)
+    {
+        fp->av = (char *) calloc(fp->ac, sizeof (*fp->av));
+        fs_read(fp->av, 1, fp->ac, fin);
+    }
+
+    if (fp->dc)
+    {
+        int i;
+
+        fp->dv = (struct b_dict *) calloc(fp->dc, sizeof (*fp->dv));
+
+        for (i = 0; i < fp->dc; i++)
+            sol_load_dict(fin, fp->dv + i);
+    }
+
+    return 1;
+}
+
+int sol_load_base(struct s_base *fp, const char *filename)
+{
+    fs_file fin;
+    int res = 0;
+
+    memset(fp, 0, sizeof (*fp));
+
+    if ((fin = fs_open(filename, "r")))
+    {
+        res = sol_load_file(fin, fp);
+        fs_close(fin);
+    }
+    return res;
+}
+
+int sol_load_meta(struct s_base *fp, const char *filename)
+{
+    fs_file fin;
+    int res = 0;
+
+    if ((fin = fs_open(filename, "r")))
+    {
+        res = sol_load_head(fin, fp);
+        fs_close(fin);
+    }
+    return res;
+}
+
+void sol_free_base(struct s_base *fp)
+{
+    if (fp->av) free(fp->av);
+    if (fp->mv) free(fp->mv);
+    if (fp->vv) free(fp->vv);
+    if (fp->ev) free(fp->ev);
+    if (fp->sv) free(fp->sv);
+    if (fp->tv) free(fp->tv);
+    if (fp->gv) free(fp->gv);
+    if (fp->lv) free(fp->lv);
+    if (fp->nv) free(fp->nv);
+    if (fp->pv) free(fp->pv);
+    if (fp->bv) free(fp->bv);
+    if (fp->hv) free(fp->hv);
+    if (fp->zv) free(fp->zv);
+    if (fp->jv) free(fp->jv);
+    if (fp->xv) free(fp->xv);
+    if (fp->rv) free(fp->rv);
+    if (fp->uv) free(fp->uv);
+    if (fp->wv) free(fp->wv);
+    if (fp->dv) free(fp->dv);
+    if (fp->iv) free(fp->iv);
+
+    memset(fp, 0, sizeof (*fp));
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void sol_stor_mtrl(fs_file fout, struct b_mtrl *mp)
+{
+    put_array(fout, mp->d, 4);
+    put_array(fout, mp->a, 4);
+    put_array(fout, mp->s, 4);
+    put_array(fout, mp->e, 4);
+    put_array(fout, mp->h, 1);
+    put_index(fout, mp->fl);
+
+    fs_write(mp->f, 1, PATHMAX, fout);
+}
+
+static void sol_stor_vert(fs_file fout, struct b_vert *vp)
+{
+    put_array(fout,  vp->p, 3);
+}
+
+static void sol_stor_edge(fs_file fout, struct b_edge *ep)
+{
+    put_index(fout, ep->vi);
+    put_index(fout, ep->vj);
+}
+
+static void sol_stor_side(fs_file fout, struct b_side *sp)
+{
+    put_array(fout, sp->n, 3);
+    put_float(fout, sp->d);
+}
+
+static void sol_stor_texc(fs_file fout, struct b_texc *tp)
+{
+    put_array(fout,  tp->u, 2);
+}
+
+static void sol_stor_geom(fs_file fout, struct b_geom *gp)
+{
+    put_index(fout, gp->mi);
+    put_index(fout, gp->ti);
+    put_index(fout, gp->si);
+    put_index(fout, gp->vi);
+    put_index(fout, gp->tj);
+    put_index(fout, gp->sj);
+    put_index(fout, gp->vj);
+    put_index(fout, gp->tk);
+    put_index(fout, gp->sk);
+    put_index(fout, gp->vk);
+}
+
+static void sol_stor_lump(fs_file fout, struct b_lump *lp)
+{
+    put_index(fout, lp->fl);
+    put_index(fout, lp->v0);
+    put_index(fout, lp->vc);
+    put_index(fout, lp->e0);
+    put_index(fout, lp->ec);
+    put_index(fout, lp->g0);
+    put_index(fout, lp->gc);
+    put_index(fout, lp->s0);
+    put_index(fout, lp->sc);
+}
+
+static void sol_stor_node(fs_file fout, struct b_node *np)
+{
+    put_index(fout, np->si);
+    put_index(fout, np->ni);
+    put_index(fout, np->nj);
+    put_index(fout, np->l0);
+    put_index(fout, np->lc);
+}
+
+static void sol_stor_path(fs_file fout, struct b_path *pp)
+{
+    put_array(fout, pp->p, 3);
+    put_float(fout, pp->t);
+    put_index(fout, pp->pi);
+    put_index(fout, pp->f);
+    put_index(fout, pp->s);
+    put_index(fout, pp->fl);
+
+    if (pp->fl & P_ORIENTED)
+        put_array(fout, pp->e, 4);
+}
+
+static void sol_stor_body(fs_file fout, struct b_body *bp)
+{
+    put_index(fout, bp->pi);
+    put_index(fout, bp->ni);
+    put_index(fout, bp->l0);
+    put_index(fout, bp->lc);
+    put_index(fout, bp->g0);
+    put_index(fout, bp->gc);
+}
+
+static void sol_stor_item(fs_file fout, struct b_item *hp)
+{
+    put_array(fout, hp->p, 3);
+    put_index(fout, hp->t);
+    put_index(fout, hp->n);
+}
+
+static void sol_stor_goal(fs_file fout, struct b_goal *zp)
+{
+    put_array(fout, zp->p, 3);
+    put_float(fout, zp->r);
+}
+
+static void sol_stor_swch(fs_file fout, struct b_swch *xp)
+{
+    put_array(fout, xp->p, 3);
+    put_float(fout, xp->r);
+    put_index(fout, xp->pi);
+    put_float(fout, xp->t);
+    put_float(fout, xp->t);
+    put_index(fout, xp->f);
+    put_index(fout, xp->f);
+    put_index(fout, xp->i);
+}
+
+static void sol_stor_bill(fs_file fout, struct b_bill *rp)
+{
+    put_index(fout, rp->fl);
+    put_index(fout, rp->mi);
+    put_float(fout, rp->t);
+    put_float(fout, rp->d);
+    put_array(fout, rp->w,  3);
+    put_array(fout, rp->h,  3);
+    put_array(fout, rp->rx, 3);
+    put_array(fout, rp->ry, 3);
+    put_array(fout, rp->rz, 3);
+    put_array(fout, rp->p,  3);
+}
+
+static void sol_stor_jump(fs_file fout, struct b_jump *jp)
+{
+    put_array(fout, jp->p, 3);
+    put_array(fout, jp->q, 3);
+    put_float(fout, jp->r);
+}
+
+static void sol_stor_ball(fs_file fout, struct b_ball *bp)
+{
+    put_array(fout, bp->p, 3);
+    put_float(fout, bp->r);
+}
+
+static void sol_stor_view(fs_file fout, struct b_view *wp)
+{
+    put_array(fout,  wp->p, 3);
+    put_array(fout,  wp->q, 3);
+}
+
+static void sol_stor_dict(fs_file fout, struct b_dict *dp)
+{
+    put_index(fout, dp->ai);
+    put_index(fout, dp->aj);
+}
+
+static void sol_stor_file(fs_file fout, struct s_base *fp)
+{
+    int i;
+    int magic   = SOL_MAGIC;
+    int version = SOL_VER_CURRENT;
+
+    put_index(fout, magic);
+    put_index(fout, version);
+
+    put_index(fout, fp->ac);
+    put_index(fout, fp->dc);
+    put_index(fout, fp->mc);
+    put_index(fout, fp->vc);
+    put_index(fout, fp->ec);
+    put_index(fout, fp->sc);
+    put_index(fout, fp->tc);
+    put_index(fout, fp->gc);
+    put_index(fout, fp->lc);
+    put_index(fout, fp->nc);
+    put_index(fout, fp->pc);
+    put_index(fout, fp->bc);
+    put_index(fout, fp->hc);
+    put_index(fout, fp->zc);
+    put_index(fout, fp->jc);
+    put_index(fout, fp->xc);
+    put_index(fout, fp->rc);
+    put_index(fout, fp->uc);
+    put_index(fout, fp->wc);
+    put_index(fout, fp->ic);
+
+    fs_write(fp->av, 1, fp->ac, fout);
+
+    for (i = 0; i < fp->dc; i++) sol_stor_dict(fout, fp->dv + i);
+    for (i = 0; i < fp->mc; i++) sol_stor_mtrl(fout, fp->mv + i);
+    for (i = 0; i < fp->vc; i++) sol_stor_vert(fout, fp->vv + i);
+    for (i = 0; i < fp->ec; i++) sol_stor_edge(fout, fp->ev + i);
+    for (i = 0; i < fp->sc; i++) sol_stor_side(fout, fp->sv + i);
+    for (i = 0; i < fp->tc; i++) sol_stor_texc(fout, fp->tv + i);
+    for (i = 0; i < fp->gc; i++) sol_stor_geom(fout, fp->gv + i);
+    for (i = 0; i < fp->lc; i++) sol_stor_lump(fout, fp->lv + i);
+    for (i = 0; i < fp->nc; i++) sol_stor_node(fout, fp->nv + i);
+    for (i = 0; i < fp->pc; i++) sol_stor_path(fout, fp->pv + i);
+    for (i = 0; i < fp->bc; i++) sol_stor_body(fout, fp->bv + i);
+    for (i = 0; i < fp->hc; i++) sol_stor_item(fout, fp->hv + i);
+    for (i = 0; i < fp->zc; i++) sol_stor_goal(fout, fp->zv + i);
+    for (i = 0; i < fp->jc; i++) sol_stor_jump(fout, fp->jv + i);
+    for (i = 0; i < fp->xc; i++) sol_stor_swch(fout, fp->xv + i);
+    for (i = 0; i < fp->rc; i++) sol_stor_bill(fout, fp->rv + i);
+    for (i = 0; i < fp->uc; i++) sol_stor_ball(fout, fp->uv + i);
+    for (i = 0; i < fp->wc; i++) sol_stor_view(fout, fp->wv + i);
+    for (i = 0; i < fp->ic; i++) put_index(fout, fp->iv[i]);
+}
+
+int sol_stor_base(struct s_base *fp, const char *filename)
+{
+    fs_file fout;
+
+    if ((fout = fs_open(filename, "w")))
+    {
+        sol_stor_file(fout, fp);
+        fs_close(fout);
+
+        return 1;
+    }
+    return 0;
+}
+
+/*---------------------------------------------------------------------------*/
diff --git a/share/solid_base.h b/share/solid_base.h
new file mode 100644 (file)
index 0000000..c041300
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2003 Robert Kooima
+ *
+ * NEVERBALL is  free software; you can redistribute  it and/or modify
+ * it under the  terms of the GNU General  Public License as published
+ * by the Free  Software Foundation; either version 2  of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
+ * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef SOLID_BASE_H
+#define SOLID_BASE_H
+
+#include "base_config.h"
+
+/*
+ * Some might  be taken  aback at  the terseness of  the names  of the
+ * structure  members and  the variables  used by  the  functions that
+ * access them.  Yes, yes, I know:  readability.  I  contend that once
+ * the naming  convention is embraced, the names  become more readable
+ * than any  verbose alternative, and their brevity  and uniformity do
+ * more to augment readability than longVariableNames ever could.
+ *
+ * Members  and variables  are named  XY.   X determines  the type  of
+ * structure to which the variable  refers.  Y determines the usage of
+ * the variable.
+ *
+ * The Xs are as documented by struct s_file:
+ *
+ *     f  File          (struct s_file)
+ *     m  Material      (struct s_mtrl)
+ *     v  Vertex        (struct s_vert)
+ *     e  Edge          (struct s_edge)
+ *     s  Side          (struct s_side)
+ *     t  Texture coord (struct s_texc)
+ *     g  Geometry      (struct s_geom)
+ *     l  Lump          (struct s_lump)
+ *     n  Node          (struct s_node)
+ *     p  Path          (struct s_path)
+ *     b  Body          (struct s_body)
+ *     h  Item          (struct s_item)
+ *     z  Goal          (struct s_goal)
+ *     j  Jump          (struct s_jump)
+ *     x  Switch        (struct s_swch)
+ *     r  Billboard     (struct s_bill)
+ *     u  User          (struct s_ball)
+ *     w  Viewpoint     (struct s_view)
+ *     d  Dictionary    (struct s_dict)
+ *     i  Index         (int)
+ *     a  Text          (char)
+ *
+ * The Ys are as follows:
+ *
+ *     c  Counter
+ *     p  Pointer
+ *     v  Vector (array)
+ *     0  Index of the first
+ *     i  Index
+ *     j  Subindex
+ *     k  Subsubindex
+ *
+ * Thus "up" is a pointer to  a user structure.  "lc" is the number of
+ * lumps.  "ei" and "ej" are  edge indices into some "ev" edge vector.
+ * An edge is  defined by two vertices, so  an edge structure consists
+ * of "vi" and "vj".  And so on.
+ *
+ * Those members that do not conform to this convention are explicitly
+ * documented with a comment.
+ *
+ * These prefixes are still available: c k o q y.
+ */
+
+/*
+ * Additionally, solid data is split into three main parts: static
+ * data (base), simulation data (vary), and rendering data (draw).
+ */
+
+/*---------------------------------------------------------------------------*/
+
+/* Material type flags */
+
+#define M_OPAQUE       1
+#define M_TRANSPARENT  2
+#define M_REFLECTIVE   4
+#define M_ENVIRONMENT  8
+#define M_ADDITIVE    16
+#define M_CLAMPED     32
+#define M_DECAL       64
+#define M_TWO_SIDED  128
+#define M_SHADOWED   256
+
+/* Billboard types. */
+
+#define B_EDGE     1
+#define B_FLAT     2
+#define B_ADDITIVE 4
+#define B_NOFACE   8
+
+/* Lump flags. */
+
+#define L_DETAIL   1
+
+/* Item types. */
+
+#define ITEM_NONE       0
+#define ITEM_COIN       1
+#define ITEM_GROW       2
+#define ITEM_SHRINK     3
+
+/* Path flags. */
+
+#define P_ORIENTED 1
+
+/*---------------------------------------------------------------------------*/
+
+struct b_mtrl
+{
+    float d[4];                                /* diffuse color              */
+    float a[4];                                /* ambient color              */
+    float s[4];                                /* specular color             */
+    float e[4];                                /* emission color             */
+    float h[1];                                /* specular exponent          */
+    float angle;
+
+    int fl;                                    /* material flags             */
+
+    char   f[PATHMAX];                         /* texture file name          */
+};
+
+struct b_vert
+{
+    float p[3];                                /* vertex position            */
+};
+
+struct b_edge
+{
+    int vi;
+    int vj;
+};
+
+struct b_side
+{
+    float n[3];                                /* plane normal vector        */
+    float d;                                   /* distance from origin       */
+};
+
+struct b_texc
+{
+    float u[2];                                /* texture coordinate         */
+};
+
+struct b_geom
+{
+    int mi;
+    int ti, si, vi;
+    int tj, sj, vj;
+    int tk, sk, vk;
+};
+
+struct b_lump
+{
+    int fl;                                    /* lump flags                 */
+    int v0, vc;
+    int e0, ec;
+    int g0, gc;
+    int s0, sc;
+};
+
+struct b_node
+{
+    int si;
+    int ni;
+    int nj;
+    int l0;
+    int lc;
+};
+
+struct b_path
+{
+    float p[3];                                /* starting position          */
+    float e[4];                                /* orientation (quaternion)   */
+    float t;                                   /* travel time                */
+    int   tm;                                  /* milliseconds               */
+
+    int pi;
+    int f;                                     /* enable flag                */
+    int s;                                     /* smooth flag                */
+
+    int fl;                                    /* flags                      */
+
+    /* TODO: merge enable and smooth into flags. */
+};
+
+struct b_body
+{
+    int pi;
+    int ni;
+    int l0;
+    int lc;
+    int g0;
+    int gc;
+};
+
+struct b_item
+{
+    float p[3];                                /* position                   */
+    int   t;                                   /* type                       */
+    int   n;                                   /* value                      */
+};
+
+struct b_goal
+{
+    float p[3];                                /* position                   */
+    float r;                                   /* radius                     */
+};
+
+struct b_swch
+{
+    float p[3];                                /* position                   */
+    float r;                                   /* radius                     */
+    int  pi;                                   /* the linked path            */
+
+    float t;                                   /* default timer              */
+    int   tm;                                  /* milliseconds               */
+    int   f;                                   /* default state              */
+    int   i;                                   /* is invisible?              */
+};
+
+struct b_bill
+{
+    int  fl;
+    int  mi;
+    float t;                                   /* repeat time interval       */
+    float d;                                   /* distance                   */
+
+    float w[3];                                /* width coefficients         */
+    float h[3];                                /* height coefficients        */
+
+    float rx[3];                               /* X rotation coefficients    */
+    float ry[3];                               /* Y rotation coefficients    */
+    float rz[3];                               /* Z rotation coefficients    */
+
+    float p[3];
+};
+
+struct b_jump
+{
+    float p[3];                                /* position                   */
+    float q[3];                                /* target position            */
+    float r;                                   /* radius                     */
+};
+
+struct b_ball
+{
+    float p[3];                                /* position vector            */
+    float r;                                   /* radius                     */
+};
+
+struct b_view
+{
+    float p[3];
+    float q[3];
+};
+
+struct b_dict
+{
+    int ai;
+    int aj;
+};
+
+struct s_base
+{
+    int ac;
+    int mc;
+    int vc;
+    int ec;
+    int sc;
+    int tc;
+    int gc;
+    int lc;
+    int nc;
+    int pc;
+    int bc;
+    int hc;
+    int zc;
+    int jc;
+    int xc;
+    int rc;
+    int uc;
+    int wc;
+    int dc;
+    int ic;
+
+    char          *av;
+    struct b_mtrl *mv;
+    struct b_vert *vv;
+    struct b_edge *ev;
+    struct b_side *sv;
+    struct b_texc *tv;
+    struct b_geom *gv;
+    struct b_lump *lv;
+    struct b_node *nv;
+    struct b_path *pv;
+    struct b_body *bv;
+    struct b_item *hv;
+    struct b_goal *zv;
+    struct b_jump *jv;
+    struct b_swch *xv;
+    struct b_bill *rv;
+    struct b_ball *uv;
+    struct b_view *wv;
+    struct b_dict *dv;
+    int           *iv;
+};
+
+/*---------------------------------------------------------------------------*/
+
+int  sol_load_base(struct s_base *, const char *);
+int  sol_load_meta(struct s_base *, const char *);
+void sol_free_base(struct s_base *);
+int  sol_stor_base(struct s_base *, const char *);
+
+/*---------------------------------------------------------------------------*/
+
+#endif
diff --git a/share/solid_draw.c b/share/solid_draw.c
new file mode 100644 (file)
index 0000000..3ae47bb
--- /dev/null
@@ -0,0 +1,841 @@
+/*
+ * Copyright (C) 2003 Robert Kooima
+ *
+ * NEVERBALL is  free software; you can redistribute  it and/or modify
+ * it under the  terms of the GNU General  Public License as published
+ * by the Free  Software Foundation; either version 2  of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
+ * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
+ * General Public License for more details.
+ */
+
+#include <SDL.h>
+#include <SDL_rwops.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "glext.h"
+#include "vec3.h"
+#include "image.h"
+#include "base_image.h"
+#include "base_config.h"
+#include "lang.h"
+
+#include "solid_draw.h"
+#include "solid_all.h"
+
+/*---------------------------------------------------------------------------*/
+
+static int sol_enum_mtrl(const struct s_base *base,
+                         const struct b_body *bp, int mi)
+{
+    int li, gi, c = 0;
+
+    /* Count all lump geoms with this material. */
+
+    for (li = 0; li < bp->lc; li++)
+    {
+        int g0 = base->lv[bp->l0 + li].g0;
+        int gc = base->lv[bp->l0 + li].gc;
+
+        for (gi = 0; gi < gc; gi++)
+            if (base->gv[base->iv[g0 + gi]].mi == mi)
+                c++;
+    }
+
+    /* Count all body geoms with this material. */
+
+    for (gi = 0; gi < bp->gc; gi++)
+        if (base->gv[base->iv[bp->g0 + gi]].mi == mi)
+            c++;
+
+    return c;
+}
+
+static int sol_enum_body(const struct s_base *base,
+                         const struct b_body *bp, int fl)
+{
+    int mi, c = 0;
+
+    /* Count all geoms with this flag. */
+
+    for (mi = 0; mi < base->mc; mi++)
+        if (base->mv[mi].fl & fl)
+            c = c + sol_enum_mtrl(base, bp, mi);
+
+    return c;
+}
+
+/*---------------------------------------------------------------------------*/
+
+int sol_reflective(const struct s_draw *draw)
+{
+    int bi;
+
+    for (bi = 0; bi < draw->bc; bi++)
+        if (draw->bv[bi].rl)
+            return 1;
+
+    return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+#define tobyte(f) ((GLubyte) (f * 255.0f))
+
+#define color_cmp(a, b) (tobyte((a)[0]) == tobyte((b)[0]) && \
+                         tobyte((a)[1]) == tobyte((b)[1]) && \
+                         tobyte((a)[2]) == tobyte((b)[2]) && \
+                         tobyte((a)[3]) == tobyte((b)[3]))
+
+static struct b_mtrl default_base_mtrl =
+{
+    { 0.8f, 0.8f, 0.8f, 1.0f },
+    { 0.2f, 0.2f, 0.2f, 1.0f },
+    { 0.0f, 0.0f, 0.0f, 1.0f },
+    { 0.0f, 0.0f, 0.0f, 1.0f },
+    { 0.0f }, 0.0f, M_OPAQUE, ""
+};
+
+static struct d_mtrl default_draw_mtrl =
+{
+    &default_base_mtrl, 0
+};
+
+static const struct d_mtrl *sol_draw_mtrl(const struct s_draw *draw,
+                                          const struct d_mtrl *mp_draw,
+                                          const struct d_mtrl *mq_draw)
+{
+    const struct b_mtrl *mp_base = mp_draw->base;
+    const struct b_mtrl *mq_base = mq_draw->base;
+
+    /* Change material properties only as needed. */
+
+    if (!color_cmp(mp_base->a, mq_base->a))
+        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,   mp_base->a);
+    if (!color_cmp(mp_base->d, mq_base->d))
+        glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,   mp_base->d);
+    if (!color_cmp(mp_base->s, mq_base->s))
+        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,  mp_base->s);
+    if (!color_cmp(mp_base->e, mq_base->e))
+        glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION,  mp_base->e);
+    if (tobyte(mp_base->h[0]) != tobyte(mq_base->h[0]))
+        glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mp_base->h);
+
+    /* Bind the texture. */
+
+    if (mp_draw->o != mq_draw->o)
+        glBindTexture(GL_TEXTURE_2D, mp_draw->o);
+
+    /* Enable environment mapping. */
+
+    if ((mp_base->fl & M_ENVIRONMENT) && !(mq_base->fl & M_ENVIRONMENT))
+    {
+        glEnable(GL_TEXTURE_GEN_S);
+        glEnable(GL_TEXTURE_GEN_T);
+
+        glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+        glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+    }
+
+    /* Disable environment mapping. */
+
+    if ((mq_base->fl & M_ENVIRONMENT) && !(mp_base->fl & M_ENVIRONMENT))
+    {
+        glDisable(GL_TEXTURE_GEN_S);
+        glDisable(GL_TEXTURE_GEN_T);
+    }
+
+    /* Enable additive blending. */
+
+    if ((mp_base->fl & M_ADDITIVE) && !(mq_base->fl & M_ADDITIVE))
+        glBlendFunc(GL_ONE, GL_ONE);
+
+    /* Enable standard blending. */
+
+    if ((mq_base->fl & M_ADDITIVE) && !(mp_base->fl & M_ADDITIVE))
+        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+    /* Enable visibility-from-behind. */
+
+    if ((mp_base->fl & M_TWO_SIDED) && !(mq_base->fl & M_TWO_SIDED))
+    {
+        glDisable(GL_CULL_FACE);
+        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
+    }
+
+    /* Disable visibility-from-behind. */
+
+    if ((mq_base->fl & M_TWO_SIDED) && !(mp_base->fl & M_TWO_SIDED))
+    {
+        glEnable(GL_CULL_FACE);
+        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
+    }
+
+    /* Enable decal offset. */
+
+    if ((mp_base->fl & M_DECAL) && !(mq_base->fl & M_DECAL))
+    {
+        glEnable(GL_POLYGON_OFFSET_FILL);
+        glPolygonOffset(-1.0f, -2.0f);
+    }
+
+    /* Disable decal offset. */
+
+    if ((mq_base->fl & M_DECAL) && !(mp_base->fl & M_DECAL))
+        glDisable(GL_POLYGON_OFFSET_FILL);
+
+    return mp_draw;
+}
+
+static const struct d_mtrl *sol_back_bill(const struct s_draw *draw,
+                                           const struct b_bill *rp,
+                                           const struct d_mtrl *mp,
+                                           float t)
+{
+    float T = (rp->t > 0.0f) ? (fmodf(t, rp->t) - rp->t / 2) : 0.0f;
+
+    float w = rp->w[0] + rp->w[1] * T + rp->w[2] * T * T;
+    float h = rp->h[0] + rp->h[1] * T + rp->h[2] * T * T;
+
+    if (w > 0 && h > 0)
+    {
+        float rx = rp->rx[0] + rp->rx[1] * T + rp->rx[2] * T * T;
+        float ry = rp->ry[0] + rp->ry[1] * T + rp->ry[2] * T * T;
+        float rz = rp->rz[0] + rp->rz[1] * T + rp->rz[2] * T * T;
+
+        glPushMatrix();
+        {
+            float y0 = (rp->fl & B_EDGE) ? 0 : -h / 2;
+            float y1 = (rp->fl & B_EDGE) ? h : +h / 2;
+
+            glRotatef(ry, 0.0f, 1.0f, 0.0f);
+            glRotatef(rx, 1.0f, 0.0f, 0.0f);
+            glTranslatef(0.0f, 0.0f, -rp->d);
+
+            if (rp->fl & B_FLAT)
+            {
+                glRotatef(-rx - 90.0f, 1.0f, 0.0f, 0.0f);
+                glRotatef(-ry,         0.0f, 0.0f, 1.0f);
+            }
+            if (rp->fl & B_EDGE)
+                glRotatef(-rx,         1.0f, 0.0f, 0.0f);
+
+            glRotatef(rz, 0.0f, 0.0f, 1.0f);
+
+            mp = sol_draw_mtrl(draw, draw->mv + rp->mi, mp);
+
+            glBegin(GL_QUADS);
+            {
+                glTexCoord2f(0.0f, 0.0f); glVertex2f(-w / 2, y0);
+                glTexCoord2f(1.0f, 0.0f); glVertex2f(+w / 2, y0);
+                glTexCoord2f(1.0f, 1.0f); glVertex2f(+w / 2, y1);
+                glTexCoord2f(0.0f, 1.0f); glVertex2f(-w / 2, y1);
+            }
+            glEnd();
+        }
+        glPopMatrix();
+    }
+
+    return mp;
+}
+
+/*---------------------------------------------------------------------------*/
+
+void sol_back(const struct s_draw *draw, float n, float f, float t)
+{
+    const struct d_mtrl *mp = &default_draw_mtrl;
+
+    int ri;
+
+    /* Render all billboards in the given range. */
+
+    glDisable(GL_LIGHTING);
+    glDepthMask(GL_FALSE);
+    {
+        for (ri = 0; ri < draw->base->rc; ri++)
+            if (n <= draw->base->rv[ri].d && draw->base->rv[ri].d < f)
+                mp = sol_back_bill(draw, draw->base->rv + ri, mp, t);
+
+        mp = sol_draw_mtrl(draw, &default_draw_mtrl, mp);
+    }
+    glDepthMask(GL_TRUE);
+    glEnable(GL_LIGHTING);
+}
+
+/*---------------------------------------------------------------------------*/
+/*
+ * The  following code  renders a  body in  a  ludicrously inefficient
+ * manner.  It iterates the materials and scans the data structure for
+ * geometry using each.  This  has the effect of absolutely minimizing
+ * material  changes,  texture  bindings,  and  Begin/End  pairs,  but
+ * maximizing trips through the data.
+ *
+ * However, this  is only done once  for each level.   The results are
+ * stored in display lists.  Thus, it is well worth it.
+ */
+
+static void sol_draw_geom(const struct s_base *base,
+                          const struct b_geom *gp, int mi)
+{
+    if (gp->mi == mi)
+    {
+        const float *ui = base->tv[gp->ti].u;
+        const float *uj = base->tv[gp->tj].u;
+        const float *uk = base->tv[gp->tk].u;
+
+        const float *ni = base->sv[gp->si].n;
+        const float *nj = base->sv[gp->sj].n;
+        const float *nk = base->sv[gp->sk].n;
+
+        const float *vi = base->vv[gp->vi].p;
+        const float *vj = base->vv[gp->vj].p;
+        const float *vk = base->vv[gp->vk].p;
+
+        glTexCoord2fv(ui);
+        glNormal3fv(ni);
+        glVertex3fv(vi);
+
+        glTexCoord2fv(uj);
+        glNormal3fv(nj);
+        glVertex3fv(vj);
+
+        glTexCoord2fv(uk);
+        glNormal3fv(nk);
+        glVertex3fv(vk);
+    }
+}
+
+static void sol_draw_lump(const struct s_base *base,
+                          const struct b_lump *lp, int mi)
+{
+    int i;
+
+    for (i = 0; i < lp->gc; i++)
+        sol_draw_geom(base, base->gv + base->iv[lp->g0 + i], mi);
+}
+
+static const struct d_mtrl *sol_draw_body(const struct s_draw *draw,
+                                          const struct b_body *bp,
+                                          const struct d_mtrl *mp,
+                                          int fl, int decal)
+{
+    const struct s_base *base = draw->base;
+
+    int mi, li, gi;
+
+    /* Iterate all materials of the correct opacity. */
+
+    for (mi = 0; mi < draw->mc; mi++)
+    {
+        struct d_mtrl *mq = draw->mv + mi;
+
+        if ((mq->base->fl & fl) && (mq->base->fl & M_DECAL) == decal)
+        {
+            if (sol_enum_mtrl(draw->base, bp, mi))
+            {
+                /* Set the material state. */
+
+                mp = sol_draw_mtrl(draw, mq, mp);
+
+                /* Render all geometry of that material. */
+
+                glBegin(GL_TRIANGLES);
+                {
+                    for (li = 0; li < bp->lc; li++)
+                        sol_draw_lump(draw->base,
+                                      base->lv + bp->l0 + li,
+                                      mi);
+                    for (gi = 0; gi < bp->gc; gi++)
+                        sol_draw_geom(draw->base,
+                                      base->gv + base->iv[bp->g0 + gi],
+                                      mi);
+                }
+                glEnd();
+            }
+        }
+    }
+
+    return mp;
+}
+
+static void sol_draw_list(const struct s_vary *vary,
+                          const struct v_body *bp, GLuint list)
+{
+    float p[3], e[4], u[3], a;
+
+    sol_body_p(p, vary, bp->pi, bp->t);
+    sol_body_e(e, vary, bp, 0);
+
+    q_as_axisangle(e, u, &a);
+    a = V_DEG(a);
+
+    glPushMatrix();
+    {
+        /* Translate and rotate a moving body. */
+
+        glTranslatef(p[0], p[1], p[2]);
+        glRotatef(a, u[0], u[1], u[2]);
+
+        /* Draw the body. */
+
+        glCallList(list);
+    }
+    glPopMatrix();
+}
+
+void sol_draw(const struct s_draw *draw, int depthmask, int depthtest)
+{
+    int bi;
+
+    /* Render all opaque geometry into the color and depth buffers. */
+
+    for (bi = 0; bi < draw->bc; bi++)
+        if (draw->bv[bi].ol)
+            sol_draw_list(draw->vary, draw->vary->bv + bi, draw->bv[bi].ol);
+
+    /* Render all translucent geometry into only the color buffer. */
+
+    if (depthtest == 0) glDisable(GL_DEPTH_TEST);
+    if (depthmask == 0) glDepthMask(GL_FALSE);
+    {
+        for (bi = 0; bi < draw->bc; bi++)
+            if (draw->bv[bi].tl)
+                sol_draw_list(draw->vary, draw->vary->bv + bi, draw->bv[bi].tl);
+    }
+    if (depthmask == 0) glDepthMask(GL_TRUE);
+    if (depthtest == 0) glEnable(GL_DEPTH_TEST);
+}
+
+void sol_bill(const struct s_draw *draw, const float *M, float t)
+{
+    const struct d_mtrl *mp = &default_draw_mtrl;
+
+    int ri;
+
+    for (ri = 0; ri < draw->base->rc; ++ri)
+    {
+        const struct b_bill *rp = draw->base->rv + ri;
+
+        float T = rp->t * t;
+        float S = fsinf(T);
+
+        float w  = rp->w [0] + rp->w [1] * T + rp->w [2] * S;
+        float h  = rp->h [0] + rp->h [1] * T + rp->h [2] * S;
+        float rx = rp->rx[0] + rp->rx[1] * T + rp->rx[2] * S;
+        float ry = rp->ry[0] + rp->ry[1] * T + rp->ry[2] * S;
+        float rz = rp->rz[0] + rp->rz[1] * T + rp->rz[2] * S;
+
+        mp = sol_draw_mtrl(draw, draw->mv + rp->mi, mp);
+
+        glPushMatrix();
+        {
+            glTranslatef(rp->p[0], rp->p[1], rp->p[2]);
+
+            if (M && ((rp->fl & B_NOFACE) == 0)) glMultMatrixf(M);
+
+            if (fabsf(rx) > 0.0f) glRotatef(rx, 1.0f, 0.0f, 0.0f);
+            if (fabsf(ry) > 0.0f) glRotatef(ry, 0.0f, 1.0f, 0.0f);
+            if (fabsf(rz) > 0.0f) glRotatef(rz, 0.0f, 0.0f, 1.0f);
+
+            glBegin(GL_QUADS);
+            {
+                glTexCoord2f(0.0f, 0.0f); glVertex2f(-w / 2, -h / 2);
+                glTexCoord2f(1.0f, 0.0f); glVertex2f(+w / 2, -h / 2);
+                glTexCoord2f(1.0f, 1.0f); glVertex2f(+w / 2, +h / 2);
+                glTexCoord2f(0.0f, 1.0f); glVertex2f(-w / 2, +h / 2);
+            }
+            glEnd();
+        }
+        glPopMatrix();
+    }
+
+    mp = sol_draw_mtrl(draw, &default_draw_mtrl, mp);
+}
+
+void sol_refl(const struct s_draw *draw)
+{
+    int bi;
+
+    /* Render all reflective geometry into the color and depth buffers. */
+
+    for (bi = 0; bi < draw->bc; bi++)
+        if (draw->bv[bi].rl)
+            sol_draw_list(draw->vary, draw->vary->bv + bi, draw->bv[bi].rl);
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void sol_shad_geom(const struct s_base *base,
+                          const struct b_geom *gp, int mi)
+{
+    if (gp->mi == mi)
+    {
+        const float *vi = base->vv[gp->vi].p;
+        const float *vj = base->vv[gp->vj].p;
+        const float *vk = base->vv[gp->vk].p;
+
+        glTexCoord2f(vi[0], vi[2]);
+        glVertex3fv(vi);
+
+        glTexCoord2f(vj[0], vj[2]);
+        glVertex3fv(vj);
+
+        glTexCoord2f(vk[0], vk[2]);
+        glVertex3fv(vk);
+    }
+}
+
+static void sol_shad_lump(const struct s_base *base,
+                          const struct b_lump *lp, int mi)
+{
+    int i;
+
+    for (i = 0; i < lp->gc; i++)
+        sol_shad_geom(base, base->gv + base->iv[lp->g0 + i], mi);
+}
+
+static void sol_shad_body(const struct s_base *base,
+                          const struct b_body *bp,
+                          int fl, int decal)
+{
+    int mi, li, gi;
+
+    if (decal)
+    {
+        glEnable(GL_POLYGON_OFFSET_FILL);
+        glPolygonOffset(-1.0f, -2.0f);
+    }
+
+    glBegin(GL_TRIANGLES);
+    {
+        for (mi = 0; mi < base->mc; mi++)
+        {
+            struct b_mtrl *mp = base->mv + mi;
+
+            if ((mp->fl & fl) && (mp->fl & M_DECAL) == decal)
+            {
+                for (li = 0; li < bp->lc; li++)
+                    sol_shad_lump(base, base->lv + bp->l0 + li, mi);
+                for (gi = 0; gi < bp->gc; gi++)
+                    sol_shad_geom(base, base->gv + base->iv[bp->g0 + gi], mi);
+            }
+        }
+    }
+    glEnd();
+
+    if (decal)
+        glDisable(GL_POLYGON_OFFSET_FILL);
+}
+
+static void sol_shad_list(const struct s_vary *vary,
+                          const struct v_body *bp, GLuint list)
+{
+    float p[3], e[4], u[3], a;
+
+    sol_body_p(p, vary, bp->pi, bp->t);
+    sol_body_e(e, vary, bp, 0);
+
+    q_as_axisangle(e, u, &a);
+    a = V_DEG(a);
+
+    glPushMatrix();
+    {
+        /* Translate and rotate a moving body. */
+
+        glTranslatef(p[0], p[1], p[2]);
+        glRotatef(a, u[0], u[1], u[2]);
+
+        /* Translate the shadow on a moving body. */
+
+        glMatrixMode(GL_TEXTURE);
+        {
+            glPushMatrix();
+            glTranslatef(p[0], p[2], 0.0f);
+            glRotatef(-a, u[0], u[2], u[1]);
+        }
+        glMatrixMode(GL_MODELVIEW);
+
+        /* Draw the body. */
+
+        glCallList(list);
+
+        /* Pop the shadow translation. */
+
+        glMatrixMode(GL_TEXTURE);
+        {
+            glPopMatrix();
+        }
+        glMatrixMode(GL_MODELVIEW);
+    }
+    glPopMatrix();
+}
+
+void sol_shad(const struct s_draw *draw)
+{
+    int bi;
+
+    /* Render all shadowed geometry. */
+
+    glDepthMask(GL_FALSE);
+    {
+        for (bi = 0; bi < draw->bc; bi++)
+            if (draw->bv[bi].sl)
+                sol_shad_list(draw->vary, draw->vary->bv + bi, draw->bv[bi].sl);
+    }
+    glDepthMask(GL_TRUE);
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void sol_load_objects(struct s_draw *draw, int s)
+{
+    int i;
+
+    /* Here we sort geometry into display lists by material type. */
+
+    for (i = 0; i < draw->bc; i++)
+    {
+        struct d_body *bp = draw->bv + i;
+
+        int on = sol_enum_body(draw->base, bp->base, M_OPAQUE);
+        int tn = sol_enum_body(draw->base, bp->base, M_TRANSPARENT);
+        int rn = sol_enum_body(draw->base, bp->base, M_REFLECTIVE);
+        int dn = sol_enum_body(draw->base, bp->base, M_DECAL);
+        int sn = sol_enum_body(draw->base, bp->base, M_SHADOWED);
+
+        /* Draw all opaque geometry, decals last. */
+
+        if (on)
+        {
+            bp->ol = glGenLists(1);
+
+            glNewList(bp->ol, GL_COMPILE);
+            {
+                const struct d_mtrl *mp = &default_draw_mtrl;
+
+                mp = sol_draw_body(draw, bp->base, mp, M_OPAQUE, 0);
+                mp = sol_draw_body(draw, bp->base, mp, M_OPAQUE, M_DECAL);
+                mp = sol_draw_mtrl(draw, &default_draw_mtrl, mp);
+            }
+            glEndList();
+        }
+        else bp->ol = 0;
+
+        /* Draw all translucent geometry, decals first. */
+
+        if (tn)
+        {
+            bp->tl = glGenLists(1);
+
+            glNewList(bp->tl, GL_COMPILE);
+            {
+                const struct d_mtrl *mp = &default_draw_mtrl;
+
+                mp = sol_draw_body(draw, bp->base, mp, M_TRANSPARENT, M_DECAL);
+                mp = sol_draw_body(draw, bp->base, mp, M_TRANSPARENT, 0);
+                mp = sol_draw_mtrl(draw, &default_draw_mtrl, mp);
+            }
+            glEndList();
+        }
+        else bp->tl = 0;
+
+        /* Draw all reflective geometry. */
+
+        if (rn)
+        {
+            bp->rl = glGenLists(1);
+
+            glNewList(bp->rl, GL_COMPILE);
+            {
+                const struct d_mtrl *mp = &default_draw_mtrl;
+
+                mp = sol_draw_body(draw, bp->base, mp, M_REFLECTIVE, 0);
+                mp = sol_draw_mtrl(draw, &default_draw_mtrl, mp);
+            }
+            glEndList();
+        }
+        else bp->rl = 0;
+
+        /* Draw all shadowed geometry. */
+
+        if (s && (on || rn || sn))
+        {
+            bp->sl = glGenLists(1);
+
+            glNewList(bp->sl, GL_COMPILE);
+            {
+                if (on) sol_shad_body(draw->base, bp->base, M_OPAQUE, 0);
+                if (rn) sol_shad_body(draw->base, bp->base, M_REFLECTIVE, 0);
+                if (dn) sol_shad_body(draw->base, bp->base, M_OPAQUE, M_DECAL);
+                if (sn)
+                {
+                    /* Transparent shadowed geometry hack. */
+
+                    if (dn)
+                        sol_shad_body(draw->base, bp->base, M_SHADOWED, M_DECAL);
+
+                    sol_shad_body(draw->base, bp->base, M_SHADOWED, 0);
+                }
+            }
+            glEndList();
+        }
+        else bp->sl = 0;
+    }
+}
+
+static GLuint sol_find_texture(const char *name)
+{
+    char png[MAXSTR];
+    char jpg[MAXSTR];
+
+    GLuint o;
+
+    /* Prefer a lossless copy of the texture over a lossy compression. */
+
+    strncpy(png, name, PATHMAX); strcat(png, ".png");
+    strncpy(jpg, name, PATHMAX); strcat(jpg, ".jpg");
+
+    /* Check for a PNG. */
+
+    if ((o = make_image_from_file(png)))
+        return o;
+
+    /* Check for a JPG. */
+
+    if ((o = make_image_from_file(jpg)))
+        return o;
+
+    return 0;
+}
+
+static void sol_load_textures(struct s_draw *draw)
+{
+    int i;
+
+    /* Load the image referenced by each material. */
+
+    for (i = 0; i < draw->mc; i++)
+    {
+        struct d_mtrl *mp = draw->mv + i;
+
+        if ((mp->o = sol_find_texture(_(mp->base->f))))
+        {
+            /* Set the texture to clamp or repeat based on material type. */
+
+            if (mp->base->fl & M_CLAMPED)
+            {
+                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+            }
+            else
+            {
+                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+            }
+        }
+    }
+}
+
+/*---------------------------------------------------------------------------*/
+
+int sol_load_draw(struct s_draw *draw, const struct s_vary *vary, int s)
+{
+    int i;
+
+    memset(draw, 0, sizeof (*draw));
+
+    draw->vary = vary;
+    draw->base = draw->vary->base;
+
+    if (draw->base->mc)
+    {
+        draw->mv = calloc(draw->base->mc, sizeof (*draw->mv));
+        draw->mc = draw->base->mc;
+
+        for (i = 0; i < draw->base->mc; i++)
+        {
+            struct d_mtrl *mp = draw->mv + i;
+            struct b_mtrl *mq = draw->base->mv + i;
+
+            mp->base = mq;
+        }
+    }
+
+    if (draw->base->bc)
+    {
+        draw->bv = calloc(draw->base->bc, sizeof (*draw->bv));
+        draw->bc = draw->base->bc;
+
+        for (i = 0; i < draw->base->bc; i++)
+        {
+            struct d_body *bp = draw->bv + i;
+            struct b_body *bq = draw->base->bv + i;
+
+            bp->base = bq;
+        }
+    }
+
+    sol_load_textures(draw);
+    sol_load_objects (draw, s);
+
+    return 1;
+}
+
+void sol_free_draw(struct s_draw *draw)
+{
+    int i;
+
+    for (i = 0; i < draw->mc; i++)
+    {
+        if (glIsTexture(draw->mv[i].o))
+            glDeleteTextures(1, &draw->mv[i].o);
+    }
+
+    for (i = 0; i < draw->bc; i++)
+    {
+        if (glIsList(draw->bv[i].ol))
+            glDeleteLists(draw->bv[i].ol, 1);
+        if (glIsList(draw->bv[i].tl))
+            glDeleteLists(draw->bv[i].tl, 1);
+        if (glIsList(draw->bv[i].rl))
+            glDeleteLists(draw->bv[i].rl, 1);
+        if (glIsList(draw->bv[i].sl))
+            glDeleteLists(draw->bv[i].sl, 1);
+    }
+
+    free(draw->mv);
+    free(draw->bv);
+
+    memset(draw, 0, sizeof (*draw));
+}
+
+/*---------------------------------------------------------------------------*/
+
+int sol_load_full(struct s_full *full, const char *filename, int s)
+{
+    if (sol_load_base(&full->base, filename))
+    {
+        sol_load_vary(&full->vary, &full->base);
+        sol_load_draw(&full->draw, &full->vary, s);
+
+        return 1;
+    }
+
+    return 0;
+}
+
+void sol_free_full(struct s_full *full)
+{
+    sol_free_draw(&full->draw);
+    sol_free_vary(&full->vary);
+    sol_free_base(&full->base);
+}
+
+/*---------------------------------------------------------------------------*/
diff --git a/share/solid_draw.h b/share/solid_draw.h
new file mode 100644 (file)
index 0000000..4e4525b
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2003 Robert Kooima
+ *
+ * NEVERBALL is  free software; you can redistribute  it and/or modify
+ * it under the  terms of the GNU General  Public License as published
+ * by the Free  Software Foundation; either version 2  of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
+ * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef SOLID_DRAW_H
+#define SOLID_DRAW_H
+
+#include "solid_base.h"
+#include "solid_vary.h"
+
+/*
+ * Rendered solid data.
+ */
+
+/*---------------------------------------------------------------------------*/
+
+struct d_mtrl
+{
+    const struct b_mtrl *base;
+
+    GLuint o;                                  /* OpenGL texture object      */
+};
+
+struct d_body
+{
+    const struct b_body *base;
+
+    GLuint ol;                                 /* opaque geometry list       */
+    GLuint tl;                                 /* transparent geometry list  */
+    GLuint rl;                                 /* reflective geometry list   */
+    GLuint sl;                                 /* shadowed geometry list     */
+};
+
+struct s_draw
+{
+    const struct s_base *base;
+    const struct s_vary *vary;
+
+    int mc;
+    int bc;
+
+    struct d_mtrl *mv;
+    struct d_body *bv;
+};
+
+/*---------------------------------------------------------------------------*/
+
+int  sol_load_draw(struct s_draw *, const struct s_vary *, int);
+void sol_free_draw(struct s_draw *);
+
+int  sol_reflective(const struct s_draw *);
+
+void sol_back(const struct s_draw *, float, float, float);
+void sol_refl(const struct s_draw *);
+void sol_draw(const struct s_draw *, int, int);
+void sol_bill(const struct s_draw *, const float *, float);
+void sol_shad(const struct s_draw *);
+
+/*---------------------------------------------------------------------------*/
+
+struct s_full
+{
+    struct s_base base;
+    struct s_vary vary;
+    struct s_draw draw;
+};
+
+int  sol_load_full(struct s_full *, const char *, int);
+void sol_free_full(struct s_full *);
+
+/*---------------------------------------------------------------------------*/
+
+#endif
diff --git a/share/solid_gl.c b/share/solid_gl.c
deleted file mode 100644 (file)
index 6253257..0000000
+++ /dev/null
@@ -1,758 +0,0 @@
-/*
- * Copyright (C) 2003 Robert Kooima
- *
- * NEVERBALL is  free software; you can redistribute  it and/or modify
- * it under the  terms of the GNU General  Public License as published
- * by the Free  Software Foundation; either version 2  of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
- * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
- * General Public License for more details.
- */
-
-#include <SDL.h>
-#include <SDL_rwops.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "glext.h"
-#include "vec3.h"
-#include "image.h"
-#include "base_image.h"
-#include "solid_gl.h"
-#include "solid_all.h"
-#include "base_config.h"
-#include "lang.h"
-
-/*---------------------------------------------------------------------------*/
-
-static int sol_enum_mtrl(const struct s_file *fp,
-                         const struct s_body *bp, int mi)
-{
-    int li, gi, c = 0;
-
-    /* Count all lump geoms with this material. */
-
-    for (li = 0; li < bp->lc; li++)
-    {
-        int g0 = fp->lv[bp->l0 + li].g0;
-        int gc = fp->lv[bp->l0 + li].gc;
-
-        for (gi = 0; gi < gc; gi++)
-            if (fp->gv[fp->iv[g0 + gi]].mi == mi)
-                c++;
-    }
-
-    /* Count all body geoms with this material. */
-
-    for (gi = 0; gi < bp->gc; gi++)
-        if (fp->gv[fp->iv[bp->g0 + gi]].mi == mi)
-            c++;
-
-    return c;
-}
-
-static int sol_enum_body(const struct s_file *fp,
-                         const struct s_body *bp, int fl)
-{
-    int mi, c = 0;
-
-    /* Count all geoms with this flag. */
-
-    for (mi = 0; mi < fp->mc; mi++)
-        if (fp->mv[mi].fl & fl)
-            c = c + sol_enum_mtrl(fp, bp, mi);
-
-    return c;
-}
-
-/*---------------------------------------------------------------------------*/
-
-int sol_reflective(const struct s_file *fp)
-{
-    int bi;
-
-    for (bi = 0; bi < fp->bc; bi++)
-        if (fp->bv[bi].rl)
-            return 1;
-
-    return 0;
-}
-
-/*---------------------------------------------------------------------------*/
-
-#define tobyte(f) ((GLubyte) (f * 255.0f))
-
-#define color_cmp(a, b) (tobyte((a)[0]) == tobyte((b)[0]) && \
-                         tobyte((a)[1]) == tobyte((b)[1]) && \
-                         tobyte((a)[2]) == tobyte((b)[2]) && \
-                         tobyte((a)[3]) == tobyte((b)[3]))
-
-static struct s_mtrl default_mtrl =
-{
-    { 0.8f, 0.8f, 0.8f, 1.0f },
-    { 0.2f, 0.2f, 0.2f, 1.0f },
-    { 0.0f, 0.0f, 0.0f, 1.0f },
-    { 0.0f, 0.0f, 0.0f, 1.0f },
-    { 0.0f, }, 0.0f, M_OPAQUE, 0, ""
-};
-
-static const struct s_mtrl *sol_draw_mtrl(const struct s_file *fp,
-                                          const struct s_mtrl *mp,
-                                          const struct s_mtrl *mq)
-{
-    /* Change material properties only as needed. */
-
-    if (!color_cmp(mp->a, mq->a))
-        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,   mp->a);
-    if (!color_cmp(mp->d, mq->d))
-        glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,   mp->d);
-    if (!color_cmp(mp->s, mq->s))
-        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,  mp->s);
-    if (!color_cmp(mp->e, mq->e))
-        glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION,  mp->e);
-    if (tobyte(mp->h[0]) != tobyte(mq->h[0]))
-        glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mp->h);
-
-    /* Bind the texture. */
-
-    if (mp->o != mq->o)
-        glBindTexture(GL_TEXTURE_2D, mp->o);
-
-    /* Enable environment mapping. */
-
-    if ((mp->fl & M_ENVIRONMENT) && !(mq->fl & M_ENVIRONMENT))
-    {
-        glEnable(GL_TEXTURE_GEN_S);
-        glEnable(GL_TEXTURE_GEN_T);
-
-        glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
-        glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
-    }
-
-    /* Disable environment mapping. */
-
-    if ((mq->fl & M_ENVIRONMENT) && !(mp->fl & M_ENVIRONMENT))
-    {
-        glDisable(GL_TEXTURE_GEN_S);
-        glDisable(GL_TEXTURE_GEN_T);
-    }
-
-    /* Enable additive blending. */
-
-    if ((mp->fl & M_ADDITIVE) && !(mq->fl & M_ADDITIVE))
-        glBlendFunc(GL_ONE, GL_ONE);
-
-    /* Enable standard blending. */
-
-    if ((mq->fl & M_ADDITIVE) && !(mp->fl & M_ADDITIVE))
-        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-    /* Enable visibility-from-behind. */
-
-    if ((mp->fl & M_TWO_SIDED) && !(mq->fl & M_TWO_SIDED))
-    {
-        glDisable(GL_CULL_FACE);
-        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
-    }
-
-    /* Disable visibility-from-behind. */
-
-    if ((mq->fl & M_TWO_SIDED) && !(mp->fl & M_TWO_SIDED))
-    {
-        glEnable(GL_CULL_FACE);
-        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
-    }
-
-    /* Enable decal offset. */
-
-    if ((mp->fl & M_DECAL) && !(mq->fl & M_DECAL))
-    {
-        glEnable(GL_POLYGON_OFFSET_FILL);
-        glPolygonOffset(-1.0f, -2.0f);
-    }
-
-    /* Disable decal offset. */
-
-    if ((mq->fl & M_DECAL) && !(mp->fl & M_DECAL))
-        glDisable(GL_POLYGON_OFFSET_FILL);
-
-    return mp;
-}
-
-static const struct s_mtrl *sol_back_bill(const struct s_file *fp,
-                                          const struct s_bill *rp,
-                                          const struct s_mtrl *mp, float t)
-{
-    float T = (rp->t > 0.0f) ? (fmodf(t, rp->t) - rp->t / 2) : 0.0f;
-
-    float w = rp->w[0] + rp->w[1] * T + rp->w[2] * T * T;
-    float h = rp->h[0] + rp->h[1] * T + rp->h[2] * T * T;
-
-    if (w > 0 && h > 0)
-    {
-        float rx = rp->rx[0] + rp->rx[1] * T + rp->rx[2] * T * T;
-        float ry = rp->ry[0] + rp->ry[1] * T + rp->ry[2] * T * T;
-        float rz = rp->rz[0] + rp->rz[1] * T + rp->rz[2] * T * T;
-
-        glPushMatrix();
-        {
-            float y0 = (rp->fl & B_EDGE) ? 0 : -h / 2;
-            float y1 = (rp->fl & B_EDGE) ? h : +h / 2;
-
-            glRotatef(ry, 0.0f, 1.0f, 0.0f);
-            glRotatef(rx, 1.0f, 0.0f, 0.0f);
-            glTranslatef(0.0f, 0.0f, -rp->d);
-
-            if (rp->fl & B_FLAT)
-            {
-                glRotatef(-rx - 90.0f, 1.0f, 0.0f, 0.0f);
-                glRotatef(-ry,         0.0f, 0.0f, 1.0f);
-            }
-            if (rp->fl & B_EDGE)
-                glRotatef(-rx,         1.0f, 0.0f, 0.0f);
-
-            glRotatef(rz, 0.0f, 0.0f, 1.0f);
-
-            mp = sol_draw_mtrl(fp, fp->mv + rp->mi, mp);
-
-            glBegin(GL_QUADS);
-            {
-                glTexCoord2f(0.0f, 0.0f); glVertex2f(-w / 2, y0);
-                glTexCoord2f(1.0f, 0.0f); glVertex2f(+w / 2, y0);
-                glTexCoord2f(1.0f, 1.0f); glVertex2f(+w / 2, y1);
-                glTexCoord2f(0.0f, 1.0f); glVertex2f(-w / 2, y1);
-            }
-            glEnd();
-        }
-        glPopMatrix();
-    }
-
-    return mp;
-}
-
-/*---------------------------------------------------------------------------*/
-
-void sol_back(const struct s_file *fp, float n, float f, float t)
-{
-    const struct s_mtrl *mp = &default_mtrl;
-
-    int ri;
-
-    /* Render all billboards in the given range. */
-
-    glDisable(GL_LIGHTING);
-    glDepthMask(GL_FALSE);
-    {
-        for (ri = 0; ri < fp->rc; ri++)
-            if (n <= fp->rv[ri].d && fp->rv[ri].d < f)
-                mp = sol_back_bill(fp, fp->rv + ri, mp, t);
-
-        mp = sol_draw_mtrl(fp, &default_mtrl, mp);
-    }
-    glDepthMask(GL_TRUE);
-    glEnable(GL_LIGHTING);
-}
-
-/*---------------------------------------------------------------------------*/
-/*
- * The  following code  renders a  body in  a  ludicrously inefficient
- * manner.  It iterates the materials and scans the data structure for
- * geometry using each.  This  has the effect of absolutely minimizing
- * material  changes,  texture  bindings,  and  Begin/End  pairs,  but
- * maximizing trips through the data.
- *
- * However, this  is only done once  for each level.   The results are
- * stored in display lists.  Thus, it is well worth it.
- */
-
-static void sol_draw_geom(const struct s_file *fp,
-                          const struct s_geom *gp, int mi)
-{
-    if (gp->mi == mi)
-    {
-        const float *ui = fp->tv[gp->ti].u;
-        const float *uj = fp->tv[gp->tj].u;
-        const float *uk = fp->tv[gp->tk].u;
-
-        const float *ni = fp->sv[gp->si].n;
-        const float *nj = fp->sv[gp->sj].n;
-        const float *nk = fp->sv[gp->sk].n;
-
-        const float *vi = fp->vv[gp->vi].p;
-        const float *vj = fp->vv[gp->vj].p;
-        const float *vk = fp->vv[gp->vk].p;
-
-        glTexCoord2fv(ui);
-        glNormal3fv(ni);
-        glVertex3fv(vi);
-
-        glTexCoord2fv(uj);
-        glNormal3fv(nj);
-        glVertex3fv(vj);
-
-        glTexCoord2fv(uk);
-        glNormal3fv(nk);
-        glVertex3fv(vk);
-    }
-}
-
-static void sol_draw_lump(const struct s_file *fp,
-                          const struct s_lump *lp, int mi)
-{
-    int i;
-
-    for (i = 0; i < lp->gc; i++)
-        sol_draw_geom(fp, fp->gv + fp->iv[lp->g0 + i], mi);
-}
-
-static const struct s_mtrl *sol_draw_body(const struct s_file *fp,
-                                          const struct s_body *bp,
-                                          const struct s_mtrl *mp,
-                                          int fl, int decal)
-{
-    int mi, li, gi;
-
-    /* Iterate all materials of the correct opacity. */
-
-    for (mi = 0; mi < fp->mc; mi++)
-        if ((fp->mv[mi].fl & fl) && (fp->mv[mi].fl & M_DECAL) == decal)
-        {
-            if (sol_enum_mtrl(fp, bp, mi))
-            {
-                /* Set the material state. */
-
-                mp = sol_draw_mtrl(fp, fp->mv + mi, mp);
-
-                /* Render all geometry of that material. */
-
-                glBegin(GL_TRIANGLES);
-                {
-                    for (li = 0; li < bp->lc; li++)
-                        sol_draw_lump(fp, fp->lv + bp->l0 + li, mi);
-                    for (gi = 0; gi < bp->gc; gi++)
-                        sol_draw_geom(fp, fp->gv + fp->iv[bp->g0 + gi], mi);
-                }
-                glEnd();
-            }
-        }
-
-    return mp;
-}
-
-static void sol_draw_list(const struct s_file *fp,
-                          const struct s_body *bp, GLuint list)
-{
-    float p[3], e[4], u[3], a;
-
-    sol_body_p(p, fp, bp->pi, bp->t);
-    sol_body_e(e, fp, bp, 0);
-
-    q_as_axisangle(e, u, &a);
-    a = V_DEG(a);
-
-    glPushMatrix();
-    {
-        /* Translate and rotate a moving body. */
-
-        glTranslatef(p[0], p[1], p[2]);
-        glRotatef(a, u[0], u[1], u[2]);
-
-        /* Draw the body. */
-
-        glCallList(list);
-    }
-    glPopMatrix();
-}
-
-void sol_draw(const struct s_file *fp, int depthmask, int depthtest)
-{
-    int bi;
-
-    /* Render all opaque geometry into the color and depth buffers. */
-
-    for (bi = 0; bi < fp->bc; bi++)
-        if (fp->bv[bi].ol)
-            sol_draw_list(fp, fp->bv + bi, fp->bv[bi].ol);
-
-    /* Render all translucent geometry into only the color buffer. */
-
-    if (depthtest == 0) glDisable(GL_DEPTH_TEST);
-    if (depthmask == 0) glDepthMask(GL_FALSE);
-    {
-        for (bi = 0; bi < fp->bc; bi++)
-            if (fp->bv[bi].tl)
-                sol_draw_list(fp, fp->bv + bi, fp->bv[bi].tl);
-    }
-    if (depthmask == 0) glDepthMask(GL_TRUE);
-    if (depthtest == 0) glEnable(GL_DEPTH_TEST);
-}
-
-void sol_bill(const struct s_file *fp, const float *M, float t)
-{
-    const struct s_mtrl *mp = &default_mtrl;
-
-    int ri;
-
-    for (ri = 0; ri < fp->rc; ++ri)
-    {
-        const struct s_bill *rp = fp->rv + ri;
-
-        float T = rp->t * t;
-        float S = fsinf(T);
-
-        float w  = rp->w [0] + rp->w [1] * T + rp->w [2] * S;
-        float h  = rp->h [0] + rp->h [1] * T + rp->h [2] * S;
-        float rx = rp->rx[0] + rp->rx[1] * T + rp->rx[2] * S;
-        float ry = rp->ry[0] + rp->ry[1] * T + rp->ry[2] * S;
-        float rz = rp->rz[0] + rp->rz[1] * T + rp->rz[2] * S;
-
-        mp = sol_draw_mtrl(fp, fp->mv + rp->mi, mp);
-
-        glPushMatrix();
-        {
-            glTranslatef(rp->p[0], rp->p[1], rp->p[2]);
-
-            if (M && ((rp->fl & B_NOFACE) == 0)) glMultMatrixf(M);
-
-            if (fabsf(rx) > 0.0f) glRotatef(rx, 1.0f, 0.0f, 0.0f);
-            if (fabsf(ry) > 0.0f) glRotatef(ry, 0.0f, 1.0f, 0.0f);
-            if (fabsf(rz) > 0.0f) glRotatef(rz, 0.0f, 0.0f, 1.0f);
-
-            glBegin(GL_QUADS);
-            {
-                glTexCoord2f(0.0f, 0.0f); glVertex2f(-w / 2, -h / 2);
-                glTexCoord2f(1.0f, 0.0f); glVertex2f(+w / 2, -h / 2);
-                glTexCoord2f(1.0f, 1.0f); glVertex2f(+w / 2, +h / 2);
-                glTexCoord2f(0.0f, 1.0f); glVertex2f(-w / 2, +h / 2);
-            }
-            glEnd();
-        }
-        glPopMatrix();
-    }
-
-    mp = sol_draw_mtrl(fp, &default_mtrl, mp);
-}
-
-void sol_refl(const struct s_file *fp)
-{
-    int bi;
-
-    /* Render all reflective geometry into the color and depth buffers. */
-
-    for (bi = 0; bi < fp->bc; bi++)
-        if (fp->bv[bi].rl)
-            sol_draw_list(fp, fp->bv + bi, fp->bv[bi].rl);
-}
-
-/*---------------------------------------------------------------------------*/
-
-static void sol_shad_geom(const struct s_file *fp,
-                          const struct s_geom *gp, int mi)
-{
-    if (gp->mi == mi)
-    {
-        const float *vi = fp->vv[gp->vi].p;
-        const float *vj = fp->vv[gp->vj].p;
-        const float *vk = fp->vv[gp->vk].p;
-
-        glTexCoord2f(vi[0], vi[2]);
-        glVertex3fv(vi);
-
-        glTexCoord2f(vj[0], vj[2]);
-        glVertex3fv(vj);
-
-        glTexCoord2f(vk[0], vk[2]);
-        glVertex3fv(vk);
-    }
-}
-
-static void sol_shad_lump(const struct s_file *fp,
-                          const struct s_lump *lp, int mi)
-{
-    int i;
-
-    for (i = 0; i < lp->gc; i++)
-        sol_shad_geom(fp, fp->gv + fp->iv[lp->g0 + i], mi);
-}
-
-static void sol_shad_body(const struct s_file *fp,
-                          const struct s_body *bp,
-                          int fl, int decal)
-{
-    int mi, li, gi;
-
-    if (decal)
-    {
-        glEnable(GL_POLYGON_OFFSET_FILL);
-        glPolygonOffset(-1.0f, -2.0f);
-    }
-
-    glBegin(GL_TRIANGLES);
-    {
-        for (mi = 0; mi < fp->mc; mi++)
-            if ((fp->mv[mi].fl & fl) && (fp->mv[mi].fl & M_DECAL) == decal)
-            {
-                for (li = 0; li < bp->lc; li++)
-                    sol_shad_lump(fp, fp->lv + bp->l0 + li, mi);
-                for (gi = 0; gi < bp->gc; gi++)
-                    sol_shad_geom(fp, fp->gv + fp->iv[bp->g0 + gi], mi);
-            }
-    }
-    glEnd();
-
-    if (decal)
-        glDisable(GL_POLYGON_OFFSET_FILL);
-}
-
-static void sol_shad_list(const struct s_file *fp,
-                          const struct s_body *bp, GLuint list)
-{
-    float p[3], e[4], u[3], a;
-
-    sol_body_p(p, fp, bp->pi, bp->t);
-    sol_body_e(e, fp, bp, 0);
-
-    q_as_axisangle(e, u, &a);
-    a = V_DEG(a);
-
-    glPushMatrix();
-    {
-        /* Translate and rotate a moving body. */
-
-        glTranslatef(p[0], p[1], p[2]);
-        glRotatef(a, u[0], u[1], u[2]);
-
-        /* Translate the shadow on a moving body. */
-
-        glMatrixMode(GL_TEXTURE);
-        {
-            glPushMatrix();
-            glTranslatef(p[0], p[2], 0.0f);
-            glRotatef(-a, u[0], u[2], u[1]);
-        }
-        glMatrixMode(GL_MODELVIEW);
-
-        /* Draw the body. */
-
-        glCallList(list);
-
-        /* Pop the shadow translation. */
-
-        glMatrixMode(GL_TEXTURE);
-        {
-            glPopMatrix();
-        }
-        glMatrixMode(GL_MODELVIEW);
-    }
-    glPopMatrix();
-}
-
-void sol_shad(const struct s_file *fp)
-{
-    int bi;
-
-    /* Render all shadowed geometry. */
-
-    glDepthMask(GL_FALSE);
-    {
-        for (bi = 0; bi < fp->bc; bi++)
-            if (fp->bv[bi].sl)
-                sol_shad_list(fp, fp->bv + bi, fp->bv[bi].sl);
-    }
-    glDepthMask(GL_TRUE);
-}
-
-/*---------------------------------------------------------------------------*/
-
-static void sol_load_objects(struct s_file *fp, int s)
-{
-    int i;
-
-    /* Here we sort geometry into display lists by material type. */
-
-    for (i = 0; i < fp->bc; i++)
-    {
-        struct s_body *bp = fp->bv + i;
-
-        int on = sol_enum_body(fp, bp, M_OPAQUE);
-        int tn = sol_enum_body(fp, bp, M_TRANSPARENT);
-        int rn = sol_enum_body(fp, bp, M_REFLECTIVE);
-        int dn = sol_enum_body(fp, bp, M_DECAL);
-        int sn = sol_enum_body(fp, bp, M_SHADOWED);
-
-        /* Draw all opaque geometry, decals last. */
-
-        if (on)
-        {
-            fp->bv[i].ol = glGenLists(1);
-
-            glNewList(fp->bv[i].ol, GL_COMPILE);
-            {
-                const struct s_mtrl *mp = &default_mtrl;
-
-                mp = sol_draw_body(fp, fp->bv + i, mp, M_OPAQUE, 0);
-                mp = sol_draw_body(fp, fp->bv + i, mp, M_OPAQUE, M_DECAL);
-                mp = sol_draw_mtrl(fp, &default_mtrl, mp);
-            }
-            glEndList();
-        }
-        else fp->bv[i].ol = 0;
-
-        /* Draw all translucent geometry, decals first. */
-
-        if (tn)
-        {
-            fp->bv[i].tl = glGenLists(1);
-
-            glNewList(fp->bv[i].tl, GL_COMPILE);
-            {
-                const struct s_mtrl *mp = &default_mtrl;
-
-                mp = sol_draw_body(fp, fp->bv + i, mp, M_TRANSPARENT, M_DECAL);
-                mp = sol_draw_body(fp, fp->bv + i, mp, M_TRANSPARENT, 0);
-                mp = sol_draw_mtrl(fp, &default_mtrl, mp);
-            }
-            glEndList();
-        }
-        else fp->bv[i].tl = 0;
-
-        /* Draw all reflective geometry. */
-
-        if (rn)
-        {
-            fp->bv[i].rl = glGenLists(1);
-
-            glNewList(fp->bv[i].rl, GL_COMPILE);
-            {
-                const struct s_mtrl *mp = &default_mtrl;
-
-                mp = sol_draw_body(fp, fp->bv + i, mp, M_REFLECTIVE, 0);
-                mp = sol_draw_mtrl(fp, &default_mtrl, mp);
-            }
-            glEndList();
-        }
-        else fp->bv[i].rl = 0;
-
-        /* Draw all shadowed geometry. */
-
-        if (s && (on || rn || sn))
-        {
-            fp->bv[i].sl = glGenLists(1);
-
-            glNewList(fp->bv[i].sl, GL_COMPILE);
-            {
-                if (on) sol_shad_body(fp, fp->bv + i, M_OPAQUE, 0);
-                if (rn) sol_shad_body(fp, fp->bv + i, M_REFLECTIVE, 0);
-                if (dn) sol_shad_body(fp, fp->bv + i, M_OPAQUE, M_DECAL);
-                if (sn)
-                {
-                    /* Transparent shadowed geometry hack. */
-
-                    if (dn)
-                        sol_shad_body(fp, fp->bv + i, M_SHADOWED, M_DECAL);
-
-                    sol_shad_body(fp, fp->bv + i, M_SHADOWED, 0);
-                }
-            }
-            glEndList();
-        }
-        else fp->bv[i].sl = 0;
-    }
-}
-
-static GLuint sol_find_texture(const char *name)
-{
-    char png[MAXSTR];
-    char jpg[MAXSTR];
-
-    GLuint o;
-
-    /* Prefer a lossless copy of the texture over a lossy compression. */
-
-    strncpy(png, name, PATHMAX); strcat(png, ".png");
-    strncpy(jpg, name, PATHMAX); strcat(jpg, ".jpg");
-
-    /* Check for a PNG. */
-
-    if ((o = make_image_from_file(png)))
-        return o;
-
-    /* Check for a JPG. */
-
-    if ((o = make_image_from_file(jpg)))
-        return o;
-
-    return 0;
-}
-
-static void sol_load_textures(struct s_file *fp)
-{
-    int i;
-
-    /* Load the image referenced by each material. */
-
-    for (i = 0; i < fp->mc; i++)
-        if ((fp->mv[i].o = sol_find_texture(_(fp->mv[i].f))))
-        {
-            /* Set the texture to clamp or repeat based on material type. */
-
-            if (fp->mv[i].fl & M_CLAMPED)
-            {
-                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
-                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
-            }
-            else
-            {
-                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-            }
-        }
-}
-
-/*---------------------------------------------------------------------------*/
-
-int sol_load_gl(struct s_file *fp, const char *filename, int s)
-{
-    if (sol_load_only_file(fp, filename))
-    {
-        sol_load_textures(fp);
-        sol_load_objects (fp, s);
-        return 1;
-    }
-    return 0;
-}
-
-/*---------------------------------------------------------------------------*/
-
-void sol_free_gl(struct s_file *fp)
-{
-    int i;
-
-    for (i = 0; i < fp->mc; i++)
-    {
-        if (glIsTexture(fp->mv[i].o))
-            glDeleteTextures(1, &fp->mv[i].o);
-    }
-
-    for (i = 0; i < fp->bc; i++)
-    {
-        if (glIsList(fp->bv[i].ol))
-            glDeleteLists(fp->bv[i].ol, 1);
-        if (glIsList(fp->bv[i].tl))
-            glDeleteLists(fp->bv[i].tl, 1);
-        if (glIsList(fp->bv[i].rl))
-            glDeleteLists(fp->bv[i].rl, 1);
-        if (glIsList(fp->bv[i].sl))
-            glDeleteLists(fp->bv[i].sl, 1);
-    }
-
-    sol_free(fp);
-}
-
-/*---------------------------------------------------------------------------*/
diff --git a/share/solid_gl.h b/share/solid_gl.h
deleted file mode 100644 (file)
index f67fb29..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2003 Robert Kooima
- *
- * NEVERBALL is  free software; you can redistribute  it and/or modify
- * it under the  terms of the GNU General  Public License as published
- * by the Free  Software Foundation; either version 2  of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
- * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
- * General Public License for more details.
- */
-
-#ifndef SOL_GL_H
-#define SOL_GL_H
-
-#include "solid.h"
-
-/*---------------------------------------------------------------------------*/
-
-int   sol_load_gl(struct s_file *, const char *, int);
-void  sol_free_gl(struct s_file *);
-
-int   sol_reflective(const struct s_file *);
-
-void  sol_back(const struct s_file *, float, float, float);
-void  sol_refl(const struct s_file *);
-void  sol_draw(const struct s_file *, int, int);
-void  sol_bill(const struct s_file *, const float *, float);
-void  sol_shad(const struct s_file *);
-
-/*---------------------------------------------------------------------------*/
-
-#endif
index f57b2b3..cc60720 100644 (file)
  * General Public License for more details.
  */
 
-#ifndef SOL_SIM_H
-#define SOL_SIM_H
+#ifndef SOLID_SIM_H
+#define SOLID_SIM_H
 
-#include "solid.h"
+#include "solid_vary.h"
 
 /*---------------------------------------------------------------------------*/
 
-void sol_init_sim(struct s_file *);
+void sol_init_sim(struct s_vary *);
 void sol_quit_sim(void);
 
-float sol_step(struct s_file *, const float *, float, int, int *);
+float sol_step(struct s_vary *, const float *, float, int, int *);
 
 /*---------------------------------------------------------------------------*/
 
index 8990867..c446c04 100644 (file)
@@ -17,7 +17,7 @@
 #include "vec3.h"
 #include "common.h"
 
-#include "solid.h"
+#include "solid_vary.h"
 #include "solid_sim.h"
 #include "solid_all.h"
 #include "solid_cmd.h"
@@ -246,7 +246,7 @@ static float v_side(float Q[3],
  * Q  gives the  position  of the  point  of impact  and  W gives  the
  * velocity of the object being impacted.
  */
-static float sol_bounce(struct s_ball *up,
+static float sol_bounce(struct v_ball *up,
                         const float q[3],
                         const float w[3], float dt)
 {
@@ -283,8 +283,8 @@ static float sol_bounce(struct s_ball *up,
 
 static float sol_test_vert(float dt,
                            float T[3],
-                           const struct s_ball *up,
-                           const struct s_vert *vp,
+                           const struct v_ball *up,
+                           const struct b_vert *vp,
                            const float o[3],
                            const float w[3])
 {
@@ -293,28 +293,27 @@ static float sol_test_vert(float dt,
 
 static float sol_test_edge(float dt,
                            float T[3],
-                           const struct s_ball *up,
-                           const struct s_file *fp,
-                           const struct s_edge *ep,
+                           const struct v_ball *up,
+                           const struct s_base *base,
+                           const struct b_edge *ep,
                            const float o[3],
                            const float w[3])
 {
     float q[3];
     float u[3];
 
-    v_cpy(q, fp->vv[ep->vi].p);
-    v_sub(u, fp->vv[ep->vj].p,
-          fp->vv[ep->vi].p);
+    v_cpy(q, base->vv[ep->vi].p);
+    v_sub(u, base->vv[ep->vj].p, base->vv[ep->vi].p);
 
     return v_edge(T, o, q, u, w, up->p, up->v, up->r);
 }
 
 static float sol_test_side(float dt,
                            float T[3],
-                           const struct s_ball *up,
-                           const struct s_file *fp,
-                           const struct s_lump *lp,
-                           const struct s_side *sp,
+                           const struct v_ball *up,
+                           const struct s_base *base,
+                           const struct b_lump *lp,
+                           const struct b_side *sp,
                            const float o[3],
                            const float w[3])
 {
@@ -324,7 +323,7 @@ static float sol_test_side(float dt,
     if (t < dt)
         for (i = 0; i < lp->sc; i++)
         {
-            const struct s_side *sq = fp->sv + fp->iv[lp->s0 + i];
+            const struct b_side *sq = base->sv + base->iv[lp->s0 + i];
 
             if (sp != sq &&
                 v_dot(T, sq->n) -
@@ -338,8 +337,8 @@ static float sol_test_side(float dt,
 /*---------------------------------------------------------------------------*/
 
 static int sol_test_fore(float dt,
-                         const struct s_ball *up,
-                         const struct s_side *sp,
+                         const struct v_ball *up,
+                         const struct b_side *sp,
                          const float o[3],
                          const float w[3])
 {
@@ -367,8 +366,8 @@ static int sol_test_fore(float dt,
 }
 
 static int sol_test_back(float dt,
-                         const struct s_ball *up,
-                         const struct s_side *sp,
+                         const struct v_ball *up,
+                         const struct b_side *sp,
                          const float o[3],
                          const float w[3])
 {
@@ -399,9 +398,9 @@ static int sol_test_back(float dt,
 
 static float sol_test_lump(float dt,
                            float T[3],
-                           const struct s_ball *up,
-                           const struct s_file *fp,
-                           const struct s_lump *lp,
+                           const struct v_ball *up,
+                           const struct s_base *base,
+                           const struct b_lump *lp,
                            const float o[3],
                            const float w[3])
 {
@@ -418,7 +417,7 @@ static float sol_test_lump(float dt,
     if (up->r > 0.0f)
         for (i = 0; i < lp->vc; i++)
         {
-            const struct s_vert *vp = fp->vv + fp->iv[lp->v0 + i];
+            const struct b_vert *vp = base->vv + base->iv[lp->v0 + i];
 
             if ((u = sol_test_vert(t, U, up, vp, o, w)) < t)
             {
@@ -432,9 +431,9 @@ static float sol_test_lump(float dt,
     if (up->r > 0.0f)
         for (i = 0; i < lp->ec; i++)
         {
-            const struct s_edge *ep = fp->ev + fp->iv[lp->e0 + i];
+            const struct b_edge *ep = base->ev + base->iv[lp->e0 + i];
 
-            if ((u = sol_test_edge(t, U, up, fp, ep, o, w)) < t)
+            if ((u = sol_test_edge(t, U, up, base, ep, o, w)) < t)
             {
                 v_cpy(T, U);
                 t = u;
@@ -445,9 +444,9 @@ static float sol_test_lump(float dt,
 
     for (i = 0; i < lp->sc; i++)
     {
-        const struct s_side *sp = fp->sv + fp->iv[lp->s0 + i];
+        const struct b_side *sp = base->sv + base->iv[lp->s0 + i];
 
-        if ((u = sol_test_side(t, U, up, fp, lp, sp, o, w)) < t)
+        if ((u = sol_test_side(t, U, up, base, lp, sp, o, w)) < t)
         {
             v_cpy(T, U);
             t = u;
@@ -458,9 +457,9 @@ static float sol_test_lump(float dt,
 
 static float sol_test_node(float dt,
                            float T[3],
-                           const struct s_ball *up,
-                           const struct s_file *fp,
-                           const struct s_node *np,
+                           const struct v_ball *up,
+                           const struct s_base *base,
+                           const struct b_node *np,
                            const float o[3],
                            const float w[3])
 {
@@ -471,9 +470,9 @@ static float sol_test_node(float dt,
 
     for (i = 0; i < np->lc; i++)
     {
-        const struct s_lump *lp = fp->lv + np->l0 + i;
+        const struct b_lump *lp = base->lv + np->l0 + i;
 
-        if ((u = sol_test_lump(t, U, up, fp, lp, o, w)) < t)
+        if ((u = sol_test_lump(t, U, up, base, lp, o, w)) < t)
         {
             v_cpy(T, U);
             t = u;
@@ -482,11 +481,11 @@ static float sol_test_node(float dt,
 
     /* Test in front of this node */
 
-    if (np->ni >= 0 && sol_test_fore(t, up, fp->sv + np->si, o, w))
+    if (np->ni >= 0 && sol_test_fore(t, up, base->sv + np->si, o, w))
     {
-        const struct s_node *nq = fp->nv + np->ni;
+        const struct b_node *nq = base->nv + np->ni;
 
-        if ((u = sol_test_node(t, U, up, fp, nq, o, w)) < t)
+        if ((u = sol_test_node(t, U, up, base, nq, o, w)) < t)
         {
             v_cpy(T, U);
             t = u;
@@ -495,11 +494,11 @@ static float sol_test_node(float dt,
 
     /* Test behind this node */
 
-    if (np->nj >= 0 && sol_test_back(t, up, fp->sv + np->si, o, w))
+    if (np->nj >= 0 && sol_test_back(t, up, base->sv + np->si, o, w))
     {
-        const struct s_node *nq = fp->nv + np->nj;
+        const struct b_node *nq = base->nv + np->nj;
 
-        if ((u = sol_test_node(t, U, up, fp, nq, o, w)) < t)
+        if ((u = sol_test_node(t, U, up, base, nq, o, w)) < t)
         {
             v_cpy(T, U);
             t = u;
@@ -511,18 +510,18 @@ static float sol_test_node(float dt,
 
 static float sol_test_body(float dt,
                            float T[3], float V[3],
-                           const struct s_ball *up,
-                           const struct s_file *fp,
-                           const struct s_body *bp)
+                           const struct v_ball *up,
+                           const struct s_vary *vary,
+                           const struct v_body *bp)
 {
     float U[3], O[3], E[4], W[3], A[3], u;
 
-    const struct s_node *np = fp->nv + bp->ni;
+    const struct b_node *np = vary->base->nv + bp->base->ni;
 
-    sol_body_p(O, fp, bp->pi, bp->t);
-    sol_body_v(W, fp, bp->pi, bp->t, dt);
-    sol_body_e(E, fp, bp, 0);
-    sol_body_w(A, fp, bp);
+    sol_body_p(O, vary, bp->pi, bp->t);
+    sol_body_v(W, vary, bp->pi, bp->t, dt);
+    sol_body_e(E, vary, bp, 0);
+    sol_body_w(A, vary, bp);
 
     /*
      * For rotating bodies, rather than rotate every normal and vertex
@@ -539,7 +538,7 @@ static float sol_test_body(float dt,
     {
         /* The body has a non-identity orientation or it is rotating. */
 
-        struct s_ball ball;
+        struct v_ball ball;
         float e[4], p0[3], p1[3];
         const float z[3] = { 0 };
 
@@ -552,7 +551,7 @@ static float sol_test_body(float dt,
 
         v_mad(p1, p1, up->v, dt);
         v_mad(p1, p1, W, -dt);
-        sol_body_e(e, fp, bp, dt);
+        sol_body_e(e, vary, bp, dt);
         q_conj(e, e);
         q_rot(p1, e, p1);
 
@@ -567,7 +566,7 @@ static float sol_test_body(float dt,
         v_sub(ball.v, p1, p0);
         v_scl(ball.v, ball.v, 1.0f / dt);
 
-        if ((u = sol_test_node(dt, U, &ball, fp, np, z, z)) < dt)
+        if ((u = sol_test_node(dt, U, &ball, vary->base, np, z, z)) < dt)
         {
             float d[4];
 
@@ -596,7 +595,7 @@ static float sol_test_body(float dt,
     }
     else
     {
-        if ((u = sol_test_node(dt, U, up, fp, np, O, W)) < dt)
+        if ((u = sol_test_node(dt, U, up, vary->base, np, O, W)) < dt)
         {
             v_cpy(T, U);
             v_cpy(V, W);
@@ -608,17 +607,17 @@ static float sol_test_body(float dt,
 
 static float sol_test_file(float dt,
                            float T[3], float V[3],
-                           const struct s_ball *up,
-                           const struct s_file *fp)
+                           const struct v_ball *up,
+                           const struct s_vary *vary)
 {
     float U[3], W[3], u, t = dt;
     int i;
 
-    for (i = 0; i < fp->bc; i++)
+    for (i = 0; i < vary->bc; i++)
     {
-        const struct s_body *bp = fp->bv + i;
+        const struct v_body *bp = vary->bv + i;
 
-        if ((u = sol_test_body(t, U, W, up, fp, bp)) < t)
+        if ((u = sol_test_body(t, U, W, up, vary, bp)) < t)
         {
             v_cpy(T, U);
             v_cpy(V, W);
@@ -682,16 +681,16 @@ static int ms_peek(float dt)
  * iterations, punt it.
  */
 
-float sol_step(struct s_file *fp, const float *g, float dt, int ui, int *m)
+float sol_step(struct s_vary *vary, const float *g, float dt, int ui, int *m)
 {
     float P[3], V[3], v[3], r[3], a[3], d, e, nt, b = 0.0f, tt = dt;
     int c;
 
     union cmd cmd;
 
-    if (ui < fp->uc)
+    if (ui < vary->uc)
     {
-        struct s_ball *up = fp->uv + ui;
+        struct v_ball *up = vary->uv + ui;
 
         /* If the ball is in contact with a surface, apply friction. */
 
@@ -699,7 +698,7 @@ float sol_step(struct s_file *fp, const float *g, float dt, int ui, int *m)
         v_cpy(v, up->v);
         v_cpy(up->v, g);
 
-        if (m && sol_test_file(tt, P, V, up, fp) < 0.0005f)
+        if (m && sol_test_file(tt, P, V, up, vary) < 0.0005f)
         {
             v_cpy(up->v, v);
             v_sub(r, P, up->p);
@@ -745,26 +744,26 @@ float sol_step(struct s_file *fp, const float *g, float dt, int ui, int *m)
 
             st = tt;
 
-            for (bi = 0; bi < fp->bc; bi++)
+            for (bi = 0; bi < vary->bc; bi++)
             {
-                struct s_body *bp = fp->bv + bi;
+                struct v_body *bp = vary->bv + bi;
 
                 if (bp->pi >= 0)
                 {
-                    struct s_path *pp = fp->pv + bp->pi;
+                    struct v_path *pp = vary->pv + bp->pi;
 
                     if (!pp->f)
                         continue;
 
-                    if (bp->tm + ms_peek(st) > pp->tm)
-                        st = MS_TO_TIME(pp->tm - bp->tm);
+                    if (bp->tm + ms_peek(st) > pp->base->tm)
+                        st = MS_TO_TIME(pp->base->tm - bp->tm);
                 }
             }
 
             /* Miss collisions if we reach the iteration limit. */
 
             if (c > 1)
-                nt = sol_test_file(st, P, V, up, fp);
+                nt = sol_test_file(st, P, V, up, vary);
             else
                 nt = tt;
 
@@ -774,9 +773,9 @@ float sol_step(struct s_file *fp, const float *g, float dt, int ui, int *m)
 
             ms = ms_step(nt);
 
-            sol_body_step(fp, nt, ms);
-            sol_swch_step(fp, nt, ms);
-            sol_ball_step(fp, nt);
+            sol_body_step(vary, nt, ms);
+            sol_swch_step(vary, nt, ms);
+            sol_ball_step(vary, nt);
 
             if (nt < st)
                 if (b < (d = sol_bounce(up, P, V, nt)))
@@ -795,7 +794,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)
+void sol_init_sim(struct s_vary *vary)
 {
     ms_init();
 }
diff --git a/share/solid_vary.c b/share/solid_vary.c
new file mode 100644 (file)
index 0000000..033ee44
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2003 Robert Kooima
+ *
+ * NEVERBALL is  free software; you can redistribute  it and/or modify
+ * it under the  terms of the GNU General  Public License as published
+ * by the Free  Software Foundation; either version 2  of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
+ * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
+ * General Public License for more details.
+ */
+
+#include <stdlib.h>
+
+#include "solid_vary.h"
+#include "common.h"
+#include "vec3.h"
+
+/*---------------------------------------------------------------------------*/
+
+int sol_load_vary(struct s_vary *fp, const struct s_base *base)
+{
+    int i;
+
+    memset(fp, 0, sizeof (*fp));
+
+    fp->base = base;
+
+    if (fp->base->pc)
+    {
+        fp->pv = calloc(fp->base->pc, sizeof (*fp->pv));
+        fp->pc = fp->base->pc;
+
+        for (i = 0; i < fp->base->pc; i++)
+        {
+            struct v_path *pp = fp->pv + i;
+            struct b_path *pq = fp->base->pv + i;
+
+            pp->base = pq;
+            pp->f    = pq->f;
+        }
+    }
+
+    if (fp->base->bc)
+    {
+        fp->bv = calloc(fp->base->bc, sizeof (*fp->bv));
+        fp->bc = fp->base->bc;
+
+        for (i = 0; i < fp->base->bc; i++)
+        {
+            struct v_body *bp = fp->bv + i;
+            struct b_body *bq = fp->base->bv + i;
+
+            bp->base = bq;
+            bp->pi   = bq->pi;
+        }
+    }
+
+    if (fp->base->hc)
+    {
+        fp->hv = calloc(fp->base->hc, sizeof (*fp->hv));
+        fp->hc = fp->base->hc;
+
+        for (i = 0; i < fp->base->hc; i++)
+        {
+            struct v_item *hp = fp->hv + i;
+            struct b_item *hq = fp->base->hv + i;
+
+            v_cpy(hp->p, hq->p);
+
+            hp->t = hq->t;
+            hp->n = hq->n;
+        }
+    }
+
+    if (fp->base->xc)
+    {
+        fp->xv = calloc(fp->base->xc, sizeof (*fp->xv));
+        fp->xc = fp->base->xc;
+
+        for (i = 0; i < fp->base->xc; i++)
+        {
+            struct v_swch *xp = fp->xv + i;
+            struct b_swch *xq = fp->base->xv + i;
+
+            xp->base = xq;
+            xp->t    = xq->t;
+            xp->tm   = xq->tm;
+            xp->f    = xq->f;
+        }
+    }
+
+    if (fp->base->uc)
+    {
+        fp->uv = calloc(fp->base->uc, sizeof (*fp->uv));
+        fp->uc = fp->base->uc;
+
+        for (i = 0; i < fp->base->uc; i++)
+        {
+            struct v_ball *up = fp->uv + i;
+            struct b_ball *uq = fp->base->uv + i;
+
+            v_cpy(up->p, uq->p);
+
+            up->r = uq->r;
+
+            up->E[0][0] = up->e[0][0] = 1.0f;
+            up->E[0][1] = up->e[0][1] = 0.0f;
+            up->E[0][2] = up->e[0][2] = 0.0f;
+
+            up->E[1][0] = up->e[1][0] = 0.0f;
+            up->E[1][1] = up->e[1][1] = 1.0f;
+            up->E[1][2] = up->e[1][2] = 0.0f;
+
+            up->E[2][0] = up->e[2][0] = 0.0f;
+            up->E[2][1] = up->e[2][1] = 0.0f;
+            up->E[2][2] = up->e[2][2] = 1.0f;
+        }
+    }
+
+    return 1;
+}
+
+void sol_free_vary(struct s_vary *fp)
+{
+    if (fp->pv) free(fp->pv);
+    if (fp->bv) free(fp->bv);
+    if (fp->hv) free(fp->hv);
+    if (fp->xv) free(fp->xv);
+    if (fp->uv) free(fp->uv);
+
+    memset(fp, 0, sizeof (*fp));
+}
+
+/*---------------------------------------------------------------------------*/
diff --git a/share/solid_vary.h b/share/solid_vary.h
new file mode 100644 (file)
index 0000000..403099e
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2003 Robert Kooima
+ *
+ * NEVERBALL is  free software; you can redistribute  it and/or modify
+ * it under the  terms of the GNU General  Public License as published
+ * by the Free  Software Foundation; either version 2  of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
+ * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef SOLID_VARY_H
+#define SOLID_VARY_H
+
+#include "base_config.h"
+#include "solid_base.h"
+
+/*
+ * Varying solid data.
+ */
+
+/*---------------------------------------------------------------------------*/
+
+struct v_path
+{
+    const struct b_path *base;
+
+    int f;                                     /* enable flag                */
+};
+
+struct v_body
+{
+    const struct b_body *base;
+
+    float t;                                   /* time on current path       */
+    int   tm;                                  /* milliseconds               */
+
+    int pi;
+};
+
+struct v_item
+{
+    float p[3];                                /* position                   */
+    int   t;                                   /* type                       */
+    int   n;                                   /* value                      */
+};
+
+struct v_swch
+{
+    const struct b_swch *base;
+
+    float t;                                   /* current timer              */
+    int   tm;                                  /* milliseconds               */
+    int   f;                                   /* current state              */
+    int   e;                                   /* is a ball inside it?       */
+};
+
+struct v_ball
+{
+    float e[3][3];                             /* basis of orientation       */
+    float p[3];                                /* position vector            */
+    float v[3];                                /* velocity vector            */
+    float w[3];                                /* angular velocity vector    */
+    float E[3][3];                             /* basis of pendulum          */
+    float W[3];                                /* angular pendulum velocity  */
+    float r;                                   /* radius                     */
+};
+
+struct s_vary
+{
+    const struct s_base *base;
+
+    int pc;
+    int bc;
+    int hc;
+    int xc;
+    int uc;
+
+    struct v_path *pv;
+    struct v_body *bv;
+    struct v_item *hv;
+    struct v_swch *xv;
+    struct v_ball *uv;
+};
+
+/*---------------------------------------------------------------------------*/
+
+int  sol_load_vary(struct s_vary *, const struct s_base *);
+void sol_free_vary(struct s_vary *);
+
+/*---------------------------------------------------------------------------*/
+
+#endif