updated URL of forum and table in readme file
[neverball] / share / solid.c
index 7a5e3a9..467da87 100644 (file)
@@ -1,4 +1,4 @@
-/*   
+/*
  * Copyright (C) 2003 Robert Kooima
  *
  * NEVERBALL is  free software; you can redistribute  it and/or modify
@@ -29,8 +29,8 @@
 #include "base_config.h"
 #include "binary.h"
 
-#define MAGIC 0x4F425251  /* Neverball sol file magic number (should not change) */
-#define SOL_VERSION  4    /* Neverball sol file format version (can change)      */
+#define MAGIC       0x4c4f53af
+#define SOL_VERSION 6
 
 #define LARGE 1.0e+5f
 
@@ -69,8 +69,8 @@ static void sol_body_v(float v[3],
 }
 
 void sol_body_p(float p[3],
-                       const struct s_file *fp,
-                       const struct s_body *bp)
+                const struct s_file *fp,
+                const struct s_body *bp)
 {
     float v[3];
 
@@ -180,10 +180,11 @@ static void sol_load_body(FILE *fin, struct s_body *bp)
     get_index(fin, &bp->gc);
 }
 
-static void sol_load_coin(FILE *fin, struct s_coin *cp)
+static void sol_load_item(FILE *fin, struct s_item *hp)
 {
-    get_array(fin,  cp->p, 3);
-    get_index(fin, &cp->n);
+    get_array(fin,  hp->p, 3);
+    get_index(fin, &hp->t);
+    get_index(fin, &hp->n);
 }
 
 static void sol_load_goal(FILE *fin, struct s_goal *zp)
@@ -249,9 +250,11 @@ static int sol_load_file(FILE *fin, struct s_file *fp)
 
     get_index(fin, &magic);
     get_index(fin, &version);
+
     if (magic != MAGIC || version != SOL_VERSION)
         return 0;
 
+    get_index(fin, &fp->ac);
     get_index(fin, &fp->mc);
     get_index(fin, &fp->vc);
     get_index(fin, &fp->ec);
@@ -262,7 +265,7 @@ static int sol_load_file(FILE *fin, struct s_file *fp)
     get_index(fin, &fp->nc);
     get_index(fin, &fp->pc);
     get_index(fin, &fp->bc);
-    get_index(fin, &fp->cc);
+    get_index(fin, &fp->hc);
     get_index(fin, &fp->zc);
     get_index(fin, &fp->jc);
     get_index(fin, &fp->xc);
@@ -270,8 +273,9 @@ static int sol_load_file(FILE *fin, struct s_file *fp)
     get_index(fin, &fp->uc);
     get_index(fin, &fp->wc);
     get_index(fin, &fp->ic);
-    get_index(fin, &fp->ac);
 
+    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)
@@ -292,8 +296,8 @@ static int sol_load_file(FILE *fin, struct s_file *fp)
         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->cc)
-        fp->cv = (struct s_coin *) calloc(fp->cc, sizeof (struct s_coin));
+    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)
@@ -308,8 +312,9 @@ static int sol_load_file(FILE *fin, struct s_file *fp)
         fp->wv = (struct s_view *) calloc(fp->wc, sizeof (struct s_view));
     if (fp->ic)
         fp->iv = (int           *) calloc(fp->ic, sizeof (int));
+
     if (fp->ac)
-        fp->av = (char          *) calloc(fp->ac, sizeof (char));
+        fread(fp->av, 1, fp->ac, fin);
 
     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);
@@ -321,7 +326,7 @@ static int sol_load_file(FILE *fin, struct s_file *fp)
     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->cc; i++) sol_load_coin(fin, fp->cv + 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);
@@ -330,8 +335,50 @@ static int sol_load_file(FILE *fin, struct s_file *fp)
     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);
 
-    if (fp->ac) fread(fp->av, 1, fp->ac, fin);
-    
+    return 1;
+}
+
+static int sol_load_head(FILE *fin, struct s_file *fp)
+{
+    int magic;
+    int version;
+
+    get_index(fin, &magic);
+    get_index(fin, &version);
+
+    if (magic != MAGIC || version != SOL_VERSION)
+        return 0;
+
+    get_index(fin, &fp->ac);
+
+#if 0
+    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);
+#endif
+    fseek(fin, 18 * 4, SEEK_CUR);
+
+    if (fp->ac)
+    {
+        fp->av = (char *) calloc(fp->ac, sizeof (char));
+        fread(fp->av, 1, fp->ac, fin);
+    }
+
     return 1;
 }
 
@@ -348,6 +395,19 @@ int sol_load_only_file(struct s_file *fp, const char *filename)
     return res;
 }
 
+int sol_load_only_head(struct s_file *fp, const char *filename)
+{
+    FILE *fin;
+    int res = 0;
+
+    if ((fin = fopen(filename, FMODE_RB)))
+    {
+        res = sol_load_head(fin, fp);
+        fclose(fin);
+    }
+    return res;
+}
+
 /*---------------------------------------------------------------------------*/
 
 static void sol_stor_mtrl(FILE *fout, struct s_mtrl *mp)
@@ -438,10 +498,11 @@ static void sol_stor_body(FILE *fout, struct s_body *bp)
     put_index(fout, &bp->gc);
 }
 
-static void sol_stor_coin(FILE *fout, struct s_coin *cp)
+static void sol_stor_item(FILE *fout, struct s_item *hp)
 {
-    put_array(fout,  cp->p, 3);
-    put_index(fout, &cp->n);
+    put_array(fout,  hp->p, 3);
+    put_index(fout, &hp->t);
+    put_index(fout, &hp->n);
 }
 
 static void sol_stor_goal(FILE *fout, struct s_goal *zp)
@@ -507,7 +568,8 @@ static void sol_stor_file(FILE *fin, struct s_file *fp)
 
     put_index(fin, &magic);
     put_index(fin, &version);
-    
+
+    put_index(fin, &fp->ac);
     put_index(fin, &fp->mc);
     put_index(fin, &fp->vc);
     put_index(fin, &fp->ec);
@@ -518,7 +580,7 @@ static void sol_stor_file(FILE *fin, struct s_file *fp)
     put_index(fin, &fp->nc);
     put_index(fin, &fp->pc);
     put_index(fin, &fp->bc);
-    put_index(fin, &fp->cc);
+    put_index(fin, &fp->hc);
     put_index(fin, &fp->zc);
     put_index(fin, &fp->jc);
     put_index(fin, &fp->xc);
@@ -526,8 +588,8 @@ static void sol_stor_file(FILE *fin, struct s_file *fp)
     put_index(fin, &fp->uc);
     put_index(fin, &fp->wc);
     put_index(fin, &fp->ic);
-    put_index(fin, &fp->ac);
 
+    fwrite(fp->av, 1, fp->ac, fin);
     for (i = 0; i < fp->mc; i++) sol_stor_mtrl(fin, fp->mv + i);
     for (i = 0; i < fp->vc; i++) sol_stor_vert(fin, fp->vv + i);
     for (i = 0; i < fp->ec; i++) sol_stor_edge(fin, fp->ev + i);
@@ -538,7 +600,7 @@ static void sol_stor_file(FILE *fin, struct s_file *fp)
     for (i = 0; i < fp->nc; i++) sol_stor_node(fin, fp->nv + i);
     for (i = 0; i < fp->pc; i++) sol_stor_path(fin, fp->pv + i);
     for (i = 0; i < fp->bc; i++) sol_stor_body(fin, fp->bv + i);
-    for (i = 0; i < fp->cc; i++) sol_stor_coin(fin, fp->cv + i);
+    for (i = 0; i < fp->hc; i++) sol_stor_item(fin, fp->hv + i);
     for (i = 0; i < fp->zc; i++) sol_stor_goal(fin, fp->zv + i);
     for (i = 0; i < fp->jc; i++) sol_stor_jump(fin, fp->jv + i);
     for (i = 0; i < fp->xc; i++) sol_stor_swch(fin, fp->xv + i);
@@ -546,8 +608,6 @@ static void sol_stor_file(FILE *fin, struct s_file *fp)
     for (i = 0; i < fp->uc; i++) sol_stor_ball(fin, fp->uv + i);
     for (i = 0; i < fp->wc; i++) sol_stor_view(fin, fp->wv + i);
     for (i = 0; i < fp->ic; i++) put_index(fin, fp->iv + i);
-
-    fwrite(fp->av, 1, fp->ac, fin);
 }
 
 /*---------------------------------------------------------------------------*/
@@ -578,7 +638,7 @@ void sol_free(struct s_file *fp)
     if (fp->nv) free(fp->nv);
     if (fp->pv) free(fp->pv);
     if (fp->bv) free(fp->bv);
-    if (fp->cv) free(fp->cv);
+    if (fp->hc) free(fp->hv);
     if (fp->zv) free(fp->zv);
     if (fp->jv) free(fp->jv);
     if (fp->xv) free(fp->xv);
@@ -781,7 +841,7 @@ static float sol_bounce(struct s_ball *up,
     v_mad(u, w, n, -wn);
     v_mad(v, v, n, -vn);
     v_mad(v, v, u, +km * dt);
-    v_mad(v, v, n, xn + yn); 
+    v_mad(v, v, n, xn + yn);
 
     v_mad(p, q, n, up->r);
 
@@ -1021,7 +1081,7 @@ static float sol_test_lump(float dt,
                            const float o[3],
                            const float w[3])
 {
-    float U[3] = {0.0f, 0.0f, 0.0f}; /* set some init value only for avoid gcc warnings */
+    float U[3] = {0.0f, 0.0f, 0.0f}; /* init value only to avoid gcc warnings */
     float u, t = dt;
     int i;
 
@@ -1042,7 +1102,7 @@ static float sol_test_lump(float dt,
                 t = u;
             }
         }
+
     /* Test all edges */
 
     if (up->r > 0.0f)
@@ -1253,33 +1313,31 @@ float sol_step(struct s_file *fp, const float *g, float dt, int ui, int *m)
 
 /*---------------------------------------------------------------------------*/
 
-int sol_coin_test(struct s_file *fp, float *p, float coin_r)
+struct s_item *sol_item_test(struct s_file *fp, float *p, float item_r)
 {
     const float *ball_p = fp->uv->p;
     const float  ball_r = fp->uv->r;
-    int ci, n;
 
-    for (ci = 0; ci < fp->cc; ci++)
+    int hi;
+
+    for (hi = 0; hi < fp->hc; hi++)
     {
         float r[3];
 
-        r[0] = ball_p[0] - fp->cv[ci].p[0];
-        r[1] = ball_p[1] - fp->cv[ci].p[1];
-        r[2] = ball_p[2] - fp->cv[ci].p[2];
+        r[0] = ball_p[0] - fp->hv[hi].p[0];
+        r[1] = ball_p[1] - fp->hv[hi].p[1];
+        r[2] = ball_p[2] - fp->hv[hi].p[2];
 
-        if (fp->cv[ci].n > 0 && v_len(r) < ball_r + coin_r)
+        if (fp->hv[hi].t != ITEM_NONE && v_len(r) < ball_r + item_r)
         {
-            p[0] = fp->cv[ci].p[0];
-            p[1] = fp->cv[ci].p[1];
-            p[2] = fp->cv[ci].p[2];
-
-            n = fp->cv[ci].n;
-            fp->cv[ci].n = 0;
+            p[0] = fp->hv[hi].p[0];
+            p[1] = fp->hv[hi].p[1];
+            p[2] = fp->hv[hi].p[2];
 
-            return n;
+            return &fp->hv[hi];
         }
     }
-    return 0;
+    return NULL;
 }
 
 struct s_goal *sol_goal_test(struct s_file *fp, float *p, int ui)
@@ -1311,10 +1369,10 @@ 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)
-/* Test if the ball ui in inside a jump */
-/* Return 1 if yes and fill p with the destination position */
-/* Return 0 if no */
-/* Return 2 if the ball is on the border of a jump */
+/* Test if the ball ui is inside a jump. */
+/* Return 1 if yes and fill p with the destination position. */
+/* Return 0 if no. */
+/* Return 2 if the ball is on the border of a jump. */
 {
     const float *ball_p = fp->uv[ui].p;
     const float  ball_r = fp->uv[ui].r;
@@ -1330,30 +1388,30 @@ int sol_jump_test(struct s_file *fp, float *p, int ui)
         r[1] = ball_p[2] - fp->jv[ji].p[2];
         r[2] = 0;
 
-       l = v_len(r) - fp->jv[ji].r;
+        l = v_len(r) - fp->jv[ji].r;
         if (l < 0 &&
             ball_p[1] > fp->jv[ji].p[1] &&
             ball_p[1] < fp->jv[ji].p[1] + JUMP_HEIGHT / 2)
         {
-           if (l < - ball_r )
-           {
-               p[0] = fp->jv[ji].q[0] + (ball_p[0] - fp->jv[ji].p[0]);
-               p[1] = fp->jv[ji].q[1] + (ball_p[1] - fp->jv[ji].p[1]);
-               p[2] = fp->jv[ji].q[2] + (ball_p[2] - fp->jv[ji].p[2]);
-
-               return 1;
-           }
-           else
-               res = 2;
+            if (l < - ball_r )
+            {
+                p[0] = fp->jv[ji].q[0] + (ball_p[0] - fp->jv[ji].p[0]);
+                p[1] = fp->jv[ji].q[1] + (ball_p[1] - fp->jv[ji].p[1]);
+                p[2] = fp->jv[ji].q[2] + (ball_p[2] - fp->jv[ji].p[2]);
+
+                return 1;
+            }
+            else
+                res = 2;
         }
     }
     return res;
 }
 
 int sol_swch_test(struct s_file *fp, int ui)
-/* In the sol fp, test and process the event the ball ui enters a switch
- * return 1 if a visibla switch is activated 
- * return 0 else (no switch is activated or only invisible switchs) */
+/* In the SOL fp, test and process the event the ball ui enters a switch.
+ * Return 1 if a visible switch is activated, return 0 otherwise (no switch is
+ * activated or only invisible switchs) */
 {
     const float *ball_p = fp->uv[ui].p;
     const float  ball_r = fp->uv[ui].r;
@@ -1373,7 +1431,7 @@ int sol_swch_test(struct s_file *fp, int ui)
             r[1] = ball_p[2] - xp->p[2];
             r[2] = 0;
 
-           l = v_len(r) - xp->r;
+            l = v_len(r) - xp->r;
             if (l < ball_r &&
                 ball_p[1] > xp->p[1] &&
                 ball_p[1] < xp->p[1] + SWCH_HEIGHT / 2)
@@ -1383,10 +1441,10 @@ int sol_swch_test(struct s_file *fp, int ui)
                     int pi = xp->pi;
                     int pj = xp->pi;
 
-                   /* The ball enter */
-                   if (xp->t0 == 0)
-                       xp->e = 1;
-                   
+                    /* The ball enter */
+                    if (xp->t0 == 0)
+                        xp->e = 1;
+
                     /* Toggle the state, update the path. */
 
                     xp->f = xp->f ? 0 : 1;
@@ -1407,14 +1465,14 @@ int sol_swch_test(struct s_file *fp, int ui)
                     if (xp->f != xp->f0)
                         xp->t  = xp->t0;
 
-                   /* If visible, set the result */
-                   if (!xp->i)
-                       res = 1;
+                    /* If visible, set the result */
+                    if (!xp->i)
+                        res = 1;
                 }
             }
-           else if (xp->e)
-               /* A ball go out */
-               xp->e = 0;
+            else if (xp->e)
+                /* A ball go out */
+                xp->e = 0;
         }
     }
     return res;