1 /*
2  * Copyright (C) 2003 Robert Kooima
3  *
4  * NEVERBALL is  free software; you can redistribute  it and/or modify
5  * it under the  terms of the GNU General  Public License as published
6  * by the Free  Software Foundation; either version 2  of the License,
7  * or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
11  * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
12  * General Public License for more details.
13  */
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include "solid_base.h"
20 #include "base_config.h"
21 #include "binary.h"
22 #include "common.h"
23 #include "fs.h"
24 #include "vec3.h"
25 
26 enum
27 {
28     SOL_VERSION_1_5 = 6,
29     SOL_VERSION_DEV
30 };
31 
32 #define SOL_VERSION_MIN  SOL_VERSION_1_5
33 #define SOL_VERSION_CURR SOL_VERSION_DEV
34 
35 #define SOL_MAGIC (0xAF | 'S' << 8 | 'O' << 16 | 'L' << 24)
36 
37 /*---------------------------------------------------------------------------*/
38 
39 static int sol_version;
40 
sol_file(fs_file fin)41 static int sol_file(fs_file fin)
42 {
43     int magic;
44     int version;
45 
46     magic   = get_index(fin);
47     version = get_index(fin);
48 
49     if (magic != SOL_MAGIC || (version < SOL_VERSION_MIN ||
50                                version > SOL_VERSION_CURR))
51         return 0;
52 
53     sol_version = version;
54 
55     return 1;
56 }
57 
sol_load_mtrl(fs_file fin,struct b_mtrl * mp)58 static void sol_load_mtrl(fs_file fin, struct b_mtrl *mp)
59 {
60     get_array(fin, mp->d, 4);
61     get_array(fin, mp->a, 4);
62     get_array(fin, mp->s, 4);
63     get_array(fin, mp->e, 4);
64     get_array(fin, mp->h, 1);
65 
66     mp->fl = get_index(fin);
67 
68     fs_read(mp->f, 1, PATHMAX, fin);
69 
70     if (sol_version >= SOL_VERSION_DEV)
71     {
72         if (mp->fl & M_ALPHA_TEST)
73         {
74             mp->alpha_func = get_index(fin);
75             mp->alpha_ref  = get_float(fin);
76         }
77     }
78 
79     /* Convert 1.5.4 material flags. */
80 
81     if (sol_version == SOL_VERSION_1_5)
82     {
83         static const int flags[][2] = {
84             { 1, M_SHADOWED },
85             { 2, M_TRANSPARENT },
86             { 4, M_REFLECTIVE | M_SHADOWED },
87             { 8, M_ENVIRONMENT },
88             { 16, M_ADDITIVE },
89             { 32, M_CLAMP_S | M_CLAMP_T },
90             { 64, M_DECAL | M_SHADOWED },
91             { 128, M_TWO_SIDED }
92         };
93 
94         if (mp->fl)
95         {
96             int i, f;
97 
98             for (f = 0, i = 0; i < ARRAYSIZE(flags); i++)
99                 if (mp->fl & flags[i][0])
100                     f |= flags[i][1];
101 
102             mp->fl = f;
103         }
104         else
105         {
106             /* Must be "mtrl/invisible". */
107 
108             mp->fl = M_TRANSPARENT;
109             mp->d[3] = 0.0f;
110         }
111     }
112 }
113 
sol_load_vert(fs_file fin,struct b_vert * vp)114 static void sol_load_vert(fs_file fin, struct b_vert *vp)
115 {
116     get_array(fin, vp->p, 3);
117 }
118 
sol_load_edge(fs_file fin,struct b_edge * ep)119 static void sol_load_edge(fs_file fin, struct b_edge *ep)
120 {
121     ep->vi = get_index(fin);
122     ep->vj = get_index(fin);
123 }
124 
sol_load_side(fs_file fin,struct b_side * sp)125 static void sol_load_side(fs_file fin, struct b_side *sp)
126 {
127     get_array(fin, sp->n, 3);
128 
129     sp->d = get_float(fin);
130 }
131 
sol_load_texc(fs_file fin,struct b_texc * tp)132 static void sol_load_texc(fs_file fin, struct b_texc *tp)
133 {
134     get_array(fin, tp->u, 2);
135 }
136 
sol_load_offs(fs_file fin,struct b_offs * op)137 static void sol_load_offs(fs_file fin, struct b_offs *op)
138 {
139     op->ti = get_index(fin);
140     op->si = get_index(fin);
141     op->vi = get_index(fin);
142 }
143 
sol_load_geom(fs_file fin,struct b_geom * gp,struct s_base * fp)144 static void sol_load_geom(fs_file fin, struct b_geom *gp, struct s_base *fp)
145 {
146     gp->mi = get_index(fin);
147 
148     if (sol_version >= SOL_VERSION_DEV)
149     {
150         gp->oi = get_index(fin);
151         gp->oj = get_index(fin);
152         gp->ok = get_index(fin);
153     }
154     else
155     {
156         struct b_offs ov[3];
157         int i, j, iv[3], oc;
158         void *p;
159 
160         oc = 0;
161 
162         for (i = 0; i < 3; i++)
163         {
164             ov[i].ti = get_index(fin);
165             ov[i].si = get_index(fin);
166             ov[i].vi = get_index(fin);
167 
168             iv[i] = -1;
169 
170             for (j = 0; j < fp->oc; j++)
171                 if (ov[i].ti == fp->ov[j].ti &&
172                     ov[i].si == fp->ov[j].si &&
173                     ov[i].vi == fp->ov[j].vi)
174                 {
175                     iv[i] = j;
176                     break;
177                 }
178 
179             if (j == fp->oc)
180                 oc++;
181         }
182 
183         if (oc && (p = realloc(fp->ov, sizeof (struct b_offs) * (fp->oc + oc))))
184         {
185             fp->ov = p;
186 
187             for (i = 0; i < 3; i++)
188                 if (iv[i] < 0)
189                 {
190                     fp->ov[fp->oc] = ov[i];
191                     iv[i] = fp->oc++;
192                 }
193         }
194 
195         gp->oi = iv[0];
196         gp->oj = iv[1];
197         gp->ok = iv[2];
198     }
199 }
200 
sol_load_lump(fs_file fin,struct b_lump * lp)201 static void sol_load_lump(fs_file fin, struct b_lump *lp)
202 {
203     lp->fl = get_index(fin);
204     lp->v0 = get_index(fin);
205     lp->vc = get_index(fin);
206     lp->e0 = get_index(fin);
207     lp->ec = get_index(fin);
208     lp->g0 = get_index(fin);
209     lp->gc = get_index(fin);
210     lp->s0 = get_index(fin);
211     lp->sc = get_index(fin);
212 }
213 
sol_load_node(fs_file fin,struct b_node * np)214 static void sol_load_node(fs_file fin, struct b_node *np)
215 {
216     np->si = get_index(fin);
217     np->ni = get_index(fin);
218     np->nj = get_index(fin);
219     np->l0 = get_index(fin);
220     np->lc = get_index(fin);
221 }
222 
sol_load_path(fs_file fin,struct b_path * pp)223 static void sol_load_path(fs_file fin, struct b_path *pp)
224 {
225     get_array(fin, pp->p, 3);
226 
227     pp->t  = get_float(fin);
228     pp->pi = get_index(fin);
229     pp->f  = get_index(fin);
230     pp->s  = get_index(fin);
231 
232     pp->tm = TIME_TO_MS(pp->t);
233     pp->t  = MS_TO_TIME(pp->tm);
234 
235     if (sol_version >= SOL_VERSION_DEV)
236         pp->fl = get_index(fin);
237 
238     pp->e[0] = 1.0f;
239     pp->e[1] = 0.0f;
240     pp->e[2] = 0.0f;
241     pp->e[3] = 0.0f;
242 
243     if (pp->fl & P_ORIENTED)
244         get_array(fin, pp->e, 4);
245 }
246 
sol_load_body(fs_file fin,struct b_body * bp)247 static void sol_load_body(fs_file fin, struct b_body *bp)
248 {
249     bp->pi = get_index(fin);
250 
251     if (sol_version >= SOL_VERSION_DEV)
252     {
253         bp->pj = get_index(fin);
254 
255         if (bp->pj < 0)
256             bp->pj = bp->pi;
257     }
258     else
259         bp->pj = bp->pi;
260 
261     bp->ni = get_index(fin);
262     bp->l0 = get_index(fin);
263     bp->lc = get_index(fin);
264     bp->g0 = get_index(fin);
265     bp->gc = get_index(fin);
266 }
267 
sol_load_item(fs_file fin,struct b_item * hp)268 static void sol_load_item(fs_file fin, struct b_item *hp)
269 {
270     get_array(fin, hp->p, 3);
271 
272     hp->t = get_index(fin);
273     hp->n = get_index(fin);
274 }
275 
sol_load_goal(fs_file fin,struct b_goal * zp)276 static void sol_load_goal(fs_file fin, struct b_goal *zp)
277 {
278     get_array(fin, zp->p, 3);
279 
280     zp->r = get_float(fin);
281 }
282 
sol_load_swch(fs_file fin,struct b_swch * xp)283 static void sol_load_swch(fs_file fin, struct b_swch *xp)
284 {
285     get_array(fin, xp->p, 3);
286 
287     xp->r  = get_float(fin);
288     xp->pi = get_index(fin);
289     xp->t  = get_float(fin);
290     (void)   get_float(fin);
291     xp->f  = get_index(fin);
292     (void)   get_index(fin);
293     xp->i  = get_index(fin);
294 
295     xp->tm = TIME_TO_MS(xp->t);
296     xp->t = MS_TO_TIME(xp->tm);
297 }
298 
sol_load_bill(fs_file fin,struct b_bill * rp)299 static void sol_load_bill(fs_file fin, struct b_bill *rp)
300 {
301     rp->fl = get_index(fin);
302     rp->mi = get_index(fin);
303     rp->t  = get_float(fin);
304     rp->d  = get_float(fin);
305 
306     get_array(fin, rp->w,  3);
307     get_array(fin, rp->h,  3);
308     get_array(fin, rp->rx, 3);
309     get_array(fin, rp->ry, 3);
310     get_array(fin, rp->rz, 3);
311     get_array(fin, rp->p,  3);
312 }
313 
sol_load_jump(fs_file fin,struct b_jump * jp)314 static void sol_load_jump(fs_file fin, struct b_jump *jp)
315 {
316     get_array(fin, jp->p, 3);
317     get_array(fin, jp->q, 3);
318 
319     jp->r = get_float(fin);
320 }
321 
sol_load_ball(fs_file fin,struct b_ball * up)322 static void sol_load_ball(fs_file fin, struct b_ball *up)
323 {
324     get_array(fin, up->p, 3);
325 
326     up->r = get_float(fin);
327 }
328 
sol_load_view(fs_file fin,struct b_view * wp)329 static void sol_load_view(fs_file fin, struct b_view *wp)
330 {
331     get_array(fin, wp->p, 3);
332     get_array(fin, wp->q, 3);
333 }
334 
sol_load_dict(fs_file fin,struct b_dict * dp)335 static void sol_load_dict(fs_file fin, struct b_dict *dp)
336 {
337     dp->ai = get_index(fin);
338     dp->aj = get_index(fin);
339 }
340 
sol_load_indx(fs_file fin,struct s_base * fp)341 static void sol_load_indx(fs_file fin, struct s_base *fp)
342 {
343     fp->ac = get_index(fin);
344     fp->dc = get_index(fin);
345     fp->mc = get_index(fin);
346     fp->vc = get_index(fin);
347     fp->ec = get_index(fin);
348     fp->sc = get_index(fin);
349     fp->tc = get_index(fin);
350 
351     if (sol_version >= SOL_VERSION_DEV)
352         fp->oc = get_index(fin);
353 
354     fp->gc = get_index(fin);
355     fp->lc = get_index(fin);
356     fp->nc = get_index(fin);
357     fp->pc = get_index(fin);
358     fp->bc = get_index(fin);
359     fp->hc = get_index(fin);
360     fp->zc = get_index(fin);
361     fp->jc = get_index(fin);
362     fp->xc = get_index(fin);
363     fp->rc = get_index(fin);
364     fp->uc = get_index(fin);
365     fp->wc = get_index(fin);
366     fp->ic = get_index(fin);
367 }
368 
sol_load_file(fs_file fin,struct s_base * fp)369 static int sol_load_file(fs_file fin, struct s_base *fp)
370 {
371     int i;
372 
373     if (!sol_file(fin))
374         return 0;
375 
376     sol_load_indx(fin, fp);
377 
378     if (fp->ac)
379         fp->av = (char *)          calloc(fp->ac, sizeof (*fp->av));
380     if (fp->mc)
381         fp->mv = (struct b_mtrl *) calloc(fp->mc, sizeof (*fp->mv));
382     if (fp->vc)
383         fp->vv = (struct b_vert *) calloc(fp->vc, sizeof (*fp->vv));
384     if (fp->ec)
385         fp->ev = (struct b_edge *) calloc(fp->ec, sizeof (*fp->ev));
386     if (fp->sc)
387         fp->sv = (struct b_side *) calloc(fp->sc, sizeof (*fp->sv));
388     if (fp->tc)
389         fp->tv = (struct b_texc *) calloc(fp->tc, sizeof (*fp->tv));
390     if (fp->oc)
391         fp->ov = (struct b_offs *) calloc(fp->oc, sizeof (*fp->ov));
392     if (fp->gc)
393         fp->gv = (struct b_geom *) calloc(fp->gc, sizeof (*fp->gv));
394     if (fp->lc)
395         fp->lv = (struct b_lump *) calloc(fp->lc, sizeof (*fp->lv));
396     if (fp->nc)
397         fp->nv = (struct b_node *) calloc(fp->nc, sizeof (*fp->nv));
398     if (fp->pc)
399         fp->pv = (struct b_path *) calloc(fp->pc, sizeof (*fp->pv));
400     if (fp->bc)
401         fp->bv = (struct b_body *) calloc(fp->bc, sizeof (*fp->bv));
402     if (fp->hc)
403         fp->hv = (struct b_item *) calloc(fp->hc, sizeof (*fp->hv));
404     if (fp->zc)
405         fp->zv = (struct b_goal *) calloc(fp->zc, sizeof (*fp->zv));
406     if (fp->jc)
407         fp->jv = (struct b_jump *) calloc(fp->jc, sizeof (*fp->jv));
408     if (fp->xc)
409         fp->xv = (struct b_swch *) calloc(fp->xc, sizeof (*fp->xv));
410     if (fp->rc)
411         fp->rv = (struct b_bill *) calloc(fp->rc, sizeof (*fp->rv));
412     if (fp->uc)
413         fp->uv = (struct b_ball *) calloc(fp->uc, sizeof (*fp->uv));
414     if (fp->wc)
415         fp->wv = (struct b_view *) calloc(fp->wc, sizeof (*fp->wv));
416     if (fp->dc)
417         fp->dv = (struct b_dict *) calloc(fp->dc, sizeof (*fp->dv));
418     if (fp->ic)
419         fp->iv = (int *)           calloc(fp->ic, sizeof (*fp->iv));
420 
421     if (fp->ac)
422         fs_read(fp->av, 1, fp->ac, fin);
423 
424     for (i = 0; i < fp->dc; i++) sol_load_dict(fin, fp->dv + i);
425     for (i = 0; i < fp->mc; i++) sol_load_mtrl(fin, fp->mv + i);
426     for (i = 0; i < fp->vc; i++) sol_load_vert(fin, fp->vv + i);
427     for (i = 0; i < fp->ec; i++) sol_load_edge(fin, fp->ev + i);
428     for (i = 0; i < fp->sc; i++) sol_load_side(fin, fp->sv + i);
429     for (i = 0; i < fp->tc; i++) sol_load_texc(fin, fp->tv + i);
430     for (i = 0; i < fp->oc; i++) sol_load_offs(fin, fp->ov + i);
431     for (i = 0; i < fp->gc; i++) sol_load_geom(fin, fp->gv + i, fp);
432     for (i = 0; i < fp->lc; i++) sol_load_lump(fin, fp->lv + i);
433     for (i = 0; i < fp->nc; i++) sol_load_node(fin, fp->nv + i);
434     for (i = 0; i < fp->pc; i++) sol_load_path(fin, fp->pv + i);
435     for (i = 0; i < fp->bc; i++) sol_load_body(fin, fp->bv + i);
436     for (i = 0; i < fp->hc; i++) sol_load_item(fin, fp->hv + i);
437     for (i = 0; i < fp->zc; i++) sol_load_goal(fin, fp->zv + i);
438     for (i = 0; i < fp->jc; i++) sol_load_jump(fin, fp->jv + i);
439     for (i = 0; i < fp->xc; i++) sol_load_swch(fin, fp->xv + i);
440     for (i = 0; i < fp->rc; i++) sol_load_bill(fin, fp->rv + i);
441     for (i = 0; i < fp->uc; i++) sol_load_ball(fin, fp->uv + i);
442     for (i = 0; i < fp->wc; i++) sol_load_view(fin, fp->wv + i);
443     for (i = 0; i < fp->ic; i++) fp->iv[i] = get_index(fin);
444 
445     /* Magically "fix" all of our code. */
446 
447     if (!fp->uc)
448     {
449         fp->uc = 1;
450         fp->uv = (struct b_ball *) calloc(fp->uc, sizeof (*fp->uv));
451     }
452 
453     return 1;
454 }
455 
sol_load_head(fs_file fin,struct s_base * fp)456 static int sol_load_head(fs_file fin, struct s_base *fp)
457 {
458     if (!sol_file(fin))
459         return 0;
460 
461     sol_load_indx(fin, fp);
462 
463     if (fp->ac)
464     {
465         fp->av = (char *) calloc(fp->ac, sizeof (*fp->av));
466         fs_read(fp->av, 1, fp->ac, fin);
467     }
468 
469     if (fp->dc)
470     {
471         int i;
472 
473         fp->dv = (struct b_dict *) calloc(fp->dc, sizeof (*fp->dv));
474 
475         for (i = 0; i < fp->dc; i++)
476             sol_load_dict(fin, fp->dv + i);
477     }
478 
479     return 1;
480 }
481 
sol_load_base(struct s_base * fp,const char * filename)482 int sol_load_base(struct s_base *fp, const char *filename)
483 {
484     fs_file fin;
485     int res = 0;
486 
487     memset(fp, 0, sizeof (*fp));
488 
489     if ((fin = fs_open(filename, "r")))
490     {
491         res = sol_load_file(fin, fp);
492         fs_close(fin);
493     }
494     return res;
495 }
496 
sol_load_meta(struct s_base * fp,const char * filename)497 int sol_load_meta(struct s_base *fp, const char *filename)
498 {
499     fs_file fin;
500     int res = 0;
501 
502     memset(fp, 0, sizeof (*fp));
503 
504     if ((fin = fs_open(filename, "r")))
505     {
506         res = sol_load_head(fin, fp);
507         fs_close(fin);
508     }
509     return res;
510 }
511 
sol_free_base(struct s_base * fp)512 void sol_free_base(struct s_base *fp)
513 {
514     if (fp->av) free(fp->av);
515     if (fp->mv) free(fp->mv);
516     if (fp->vv) free(fp->vv);
517     if (fp->ev) free(fp->ev);
518     if (fp->sv) free(fp->sv);
519     if (fp->tv) free(fp->tv);
520     if (fp->ov) free(fp->ov);
521     if (fp->gv) free(fp->gv);
522     if (fp->lv) free(fp->lv);
523     if (fp->nv) free(fp->nv);
524     if (fp->pv) free(fp->pv);
525     if (fp->bv) free(fp->bv);
526     if (fp->hv) free(fp->hv);
527     if (fp->zv) free(fp->zv);
528     if (fp->jv) free(fp->jv);
529     if (fp->xv) free(fp->xv);
530     if (fp->rv) free(fp->rv);
531     if (fp->uv) free(fp->uv);
532     if (fp->wv) free(fp->wv);
533     if (fp->dv) free(fp->dv);
534     if (fp->iv) free(fp->iv);
535 
536     memset(fp, 0, sizeof (*fp));
537 }
538 
539 /*---------------------------------------------------------------------------*/
540 
sol_stor_mtrl(fs_file fout,struct b_mtrl * mp)541 static void sol_stor_mtrl(fs_file fout, struct b_mtrl *mp)
542 {
543     put_array(fout, mp->d, 4);
544     put_array(fout, mp->a, 4);
545     put_array(fout, mp->s, 4);
546     put_array(fout, mp->e, 4);
547     put_array(fout, mp->h, 1);
548     put_index(fout, mp->fl);
549 
550     fs_write(mp->f, 1, PATHMAX, fout);
551 
552     if (mp->fl & M_ALPHA_TEST)
553     {
554         put_index(fout, mp->alpha_func);
555         put_float(fout, mp->alpha_ref);
556     }
557 }
558 
sol_stor_vert(fs_file fout,struct b_vert * vp)559 static void sol_stor_vert(fs_file fout, struct b_vert *vp)
560 {
561     put_array(fout,  vp->p, 3);
562 }
563 
sol_stor_edge(fs_file fout,struct b_edge * ep)564 static void sol_stor_edge(fs_file fout, struct b_edge *ep)
565 {
566     put_index(fout, ep->vi);
567     put_index(fout, ep->vj);
568 }
569 
sol_stor_side(fs_file fout,struct b_side * sp)570 static void sol_stor_side(fs_file fout, struct b_side *sp)
571 {
572     put_array(fout, sp->n, 3);
573     put_float(fout, sp->d);
574 }
575 
sol_stor_texc(fs_file fout,struct b_texc * tp)576 static void sol_stor_texc(fs_file fout, struct b_texc *tp)
577 {
578     put_array(fout,  tp->u, 2);
579 }
580 
sol_stor_offs(fs_file fout,struct b_offs * op)581 static void sol_stor_offs(fs_file fout, struct b_offs *op)
582 {
583     put_index(fout, op->ti);
584     put_index(fout, op->si);
585     put_index(fout, op->vi);
586 }
587 
sol_stor_geom(fs_file fout,struct b_geom * gp)588 static void sol_stor_geom(fs_file fout, struct b_geom *gp)
589 {
590     put_index(fout, gp->mi);
591     put_index(fout, gp->oi);
592     put_index(fout, gp->oj);
593     put_index(fout, gp->ok);
594 }
595 
sol_stor_lump(fs_file fout,struct b_lump * lp)596 static void sol_stor_lump(fs_file fout, struct b_lump *lp)
597 {
598     put_index(fout, lp->fl);
599     put_index(fout, lp->v0);
600     put_index(fout, lp->vc);
601     put_index(fout, lp->e0);
602     put_index(fout, lp->ec);
603     put_index(fout, lp->g0);
604     put_index(fout, lp->gc);
605     put_index(fout, lp->s0);
606     put_index(fout, lp->sc);
607 }
608 
sol_stor_node(fs_file fout,struct b_node * np)609 static void sol_stor_node(fs_file fout, struct b_node *np)
610 {
611     put_index(fout, np->si);
612     put_index(fout, np->ni);
613     put_index(fout, np->nj);
614     put_index(fout, np->l0);
615     put_index(fout, np->lc);
616 }
617 
sol_stor_path(fs_file fout,struct b_path * pp)618 static void sol_stor_path(fs_file fout, struct b_path *pp)
619 {
620     put_array(fout, pp->p, 3);
621     put_float(fout, pp->t);
622     put_index(fout, pp->pi);
623     put_index(fout, pp->f);
624     put_index(fout, pp->s);
625     put_index(fout, pp->fl);
626 
627     if (pp->fl & P_ORIENTED)
628         put_array(fout, pp->e, 4);
629 }
630 
sol_stor_body(fs_file fout,struct b_body * bp)631 static void sol_stor_body(fs_file fout, struct b_body *bp)
632 {
633     put_index(fout, bp->pi);
634     put_index(fout, bp->pj);
635     put_index(fout, bp->ni);
636     put_index(fout, bp->l0);
637     put_index(fout, bp->lc);
638     put_index(fout, bp->g0);
639     put_index(fout, bp->gc);
640 }
641 
sol_stor_item(fs_file fout,struct b_item * hp)642 static void sol_stor_item(fs_file fout, struct b_item *hp)
643 {
644     put_array(fout, hp->p, 3);
645     put_index(fout, hp->t);
646     put_index(fout, hp->n);
647 }
648 
sol_stor_goal(fs_file fout,struct b_goal * zp)649 static void sol_stor_goal(fs_file fout, struct b_goal *zp)
650 {
651     put_array(fout, zp->p, 3);
652     put_float(fout, zp->r);
653 }
654 
sol_stor_swch(fs_file fout,struct b_swch * xp)655 static void sol_stor_swch(fs_file fout, struct b_swch *xp)
656 {
657     put_array(fout, xp->p, 3);
658     put_float(fout, xp->r);
659     put_index(fout, xp->pi);
660     put_float(fout, xp->t);
661     put_float(fout, xp->t);
662     put_index(fout, xp->f);
663     put_index(fout, xp->f);
664     put_index(fout, xp->i);
665 }
666 
sol_stor_bill(fs_file fout,struct b_bill * rp)667 static void sol_stor_bill(fs_file fout, struct b_bill *rp)
668 {
669     put_index(fout, rp->fl);
670     put_index(fout, rp->mi);
671     put_float(fout, rp->t);
672     put_float(fout, rp->d);
673     put_array(fout, rp->w,  3);
674     put_array(fout, rp->h,  3);
675     put_array(fout, rp->rx, 3);
676     put_array(fout, rp->ry, 3);
677     put_array(fout, rp->rz, 3);
678     put_array(fout, rp->p,  3);
679 }
680 
sol_stor_jump(fs_file fout,struct b_jump * jp)681 static void sol_stor_jump(fs_file fout, struct b_jump *jp)
682 {
683     put_array(fout, jp->p, 3);
684     put_array(fout, jp->q, 3);
685     put_float(fout, jp->r);
686 }
687 
sol_stor_ball(fs_file fout,struct b_ball * bp)688 static void sol_stor_ball(fs_file fout, struct b_ball *bp)
689 {
690     put_array(fout, bp->p, 3);
691     put_float(fout, bp->r);
692 }
693 
sol_stor_view(fs_file fout,struct b_view * wp)694 static void sol_stor_view(fs_file fout, struct b_view *wp)
695 {
696     put_array(fout,  wp->p, 3);
697     put_array(fout,  wp->q, 3);
698 }
699 
sol_stor_dict(fs_file fout,struct b_dict * dp)700 static void sol_stor_dict(fs_file fout, struct b_dict *dp)
701 {
702     put_index(fout, dp->ai);
703     put_index(fout, dp->aj);
704 }
705 
sol_stor_file(fs_file fout,struct s_base * fp)706 static void sol_stor_file(fs_file fout, struct s_base *fp)
707 {
708     int i;
709     int magic   = SOL_MAGIC;
710     int version = SOL_VERSION_CURR;
711 
712     put_index(fout, magic);
713     put_index(fout, version);
714 
715     put_index(fout, fp->ac);
716     put_index(fout, fp->dc);
717     put_index(fout, fp->mc);
718     put_index(fout, fp->vc);
719     put_index(fout, fp->ec);
720     put_index(fout, fp->sc);
721     put_index(fout, fp->tc);
722     put_index(fout, fp->oc);
723     put_index(fout, fp->gc);
724     put_index(fout, fp->lc);
725     put_index(fout, fp->nc);
726     put_index(fout, fp->pc);
727     put_index(fout, fp->bc);
728     put_index(fout, fp->hc);
729     put_index(fout, fp->zc);
730     put_index(fout, fp->jc);
731     put_index(fout, fp->xc);
732     put_index(fout, fp->rc);
733     put_index(fout, fp->uc);
734     put_index(fout, fp->wc);
735     put_index(fout, fp->ic);
736 
737     fs_write(fp->av, 1, fp->ac, fout);
738 
739     for (i = 0; i < fp->dc; i++) sol_stor_dict(fout, fp->dv + i);
740     for (i = 0; i < fp->mc; i++) sol_stor_mtrl(fout, fp->mv + i);
741     for (i = 0; i < fp->vc; i++) sol_stor_vert(fout, fp->vv + i);
742     for (i = 0; i < fp->ec; i++) sol_stor_edge(fout, fp->ev + i);
743     for (i = 0; i < fp->sc; i++) sol_stor_side(fout, fp->sv + i);
744     for (i = 0; i < fp->tc; i++) sol_stor_texc(fout, fp->tv + i);
745     for (i = 0; i < fp->oc; i++) sol_stor_offs(fout, fp->ov + i);
746     for (i = 0; i < fp->gc; i++) sol_stor_geom(fout, fp->gv + i);
747     for (i = 0; i < fp->lc; i++) sol_stor_lump(fout, fp->lv + i);
748     for (i = 0; i < fp->nc; i++) sol_stor_node(fout, fp->nv + i);
749     for (i = 0; i < fp->pc; i++) sol_stor_path(fout, fp->pv + i);
750     for (i = 0; i < fp->bc; i++) sol_stor_body(fout, fp->bv + i);
751     for (i = 0; i < fp->hc; i++) sol_stor_item(fout, fp->hv + i);
752     for (i = 0; i < fp->zc; i++) sol_stor_goal(fout, fp->zv + i);
753     for (i = 0; i < fp->jc; i++) sol_stor_jump(fout, fp->jv + i);
754     for (i = 0; i < fp->xc; i++) sol_stor_swch(fout, fp->xv + i);
755     for (i = 0; i < fp->rc; i++) sol_stor_bill(fout, fp->rv + i);
756     for (i = 0; i < fp->uc; i++) sol_stor_ball(fout, fp->uv + i);
757     for (i = 0; i < fp->wc; i++) sol_stor_view(fout, fp->wv + i);
758     for (i = 0; i < fp->ic; i++) put_index(fout, fp->iv[i]);
759 }
760 
sol_stor_base(struct s_base * fp,const char * filename)761 int sol_stor_base(struct s_base *fp, const char *filename)
762 {
763     fs_file fout;
764 
765     if ((fout = fs_open(filename, "w")))
766     {
767         sol_stor_file(fout, fp);
768         fs_close(fout);
769 
770         return 1;
771     }
772     return 0;
773 }
774 
775 /*---------------------------------------------------------------------------*/
776 
777 const struct path tex_paths[4] = {
778     { "textures/", ".png" },
779     { "textures/", ".jpg" },
780     { "",          ".png" },
781     { "",          ".jpg" }
782 };
783 
784 const struct path mtrl_paths[2] = {
785     { "textures/", "" },
786     { "",          "" }
787 };
788 
789 /*---------------------------------------------------------------------------*/
790 
791 /*
792  * This has to match up with mtrl_func_syms in mtrl.c.
793  */
794 static const char mtrl_func_names[8][16] = {
795     "always",
796     "equal",
797     "gequal",
798     "greater",
799     "lequal",
800     "less",
801     "never",
802     "notequal"
803 };
804 
805 static const struct
806 {
807     char name[16];
808     int flag;
809 } mtrl_flags[] = {
810     { "additive",    M_ADDITIVE },
811     { "clamp-s",     M_CLAMP_S },
812     { "clamp-t",     M_CLAMP_T },
813     { "decal",       M_DECAL },
814     { "environment", M_ENVIRONMENT },
815     { "reflective",  M_REFLECTIVE },
816     { "shadowed",    M_SHADOWED },
817     { "transparent", M_TRANSPARENT },
818     { "two-sided",   M_TWO_SIDED },
819     { "particle",    M_PARTICLE },
820 };
821 
mtrl_read(struct b_mtrl * mp,const char * name)822 int mtrl_read(struct b_mtrl *mp, const char *name)
823 {
824     static char line[MAXSTR];
825     static char word[MAXSTR];
826 
827     fs_file fp;
828     int i;
829 
830     if (mp && name && *name)
831     {
832         SAFECPY(mp->f, name);
833 
834         mp->a[0] = mp->a[1] = mp->a[2] = 0.2f;
835         mp->d[0] = mp->d[1] = mp->d[2] = 0.8f;
836         mp->s[0] = mp->s[1] = mp->s[2] = 0.0f;
837         mp->e[0] = mp->e[1] = mp->e[2] = 0.0f;
838         mp->a[3] = mp->d[3] = mp->s[3] = mp->e[3] = 1.0f;
839         mp->h[0] = 0.0f;
840         mp->fl   = 0;
841         mp->angle = 45.0f;
842 
843         mp->alpha_func = 0;
844         mp->alpha_ref  = 0.0f;
845 
846         fp = NULL;
847 
848         for (i = 0; i < ARRAYSIZE(mtrl_paths); i++)
849         {
850             CONCAT_PATH(line, &mtrl_paths[i], name);
851 
852             if ((fp = fs_open(line, "r")))
853                 break;
854         }
855 
856         if (fp)
857         {
858             char str[16] = "";
859 
860             while (fs_gets(line, sizeof (line), fp))
861             {
862                 char *p = strip_newline(line);
863 
864                 if (sscanf(p, "diffuse %f %f %f %f",
865                            &mp->d[0], &mp->d[1],
866                            &mp->d[2], &mp->d[3]) == 4)
867                 {
868                 }
869                 else if (sscanf(p, "ambient %f %f %f %f",
870                                 &mp->a[0], &mp->a[1],
871                                 &mp->a[2], &mp->a[3]) == 4)
872                 {
873                 }
874                 else if (sscanf(p, "specular %f %f %f %f",
875                                 &mp->s[0], &mp->s[1],
876                                 &mp->s[2], &mp->s[3]) == 4)
877                 {
878                 }
879                 else if (sscanf(p, "emissive %f %f %f %f",
880                                 &mp->e[0], &mp->e[1],
881                                 &mp->e[2], &mp->e[3]) == 4)
882                 {
883                 }
884                 else if (sscanf(p, "shininess %f", &mp->h[0]) == 1)
885                 {
886                 }
887                 else if (strncmp(p, "flags ", 6) == 0)
888                 {
889                     int f = 0;
890                     int n;
891 
892                     p += 6;
893 
894                     while (sscanf(p, "%s%n", word, &n) > 0)
895                     {
896                         for (i = 0; i < ARRAYSIZE(mtrl_flags); i++)
897                             if (strcmp(word, mtrl_flags[i].name) == 0)
898                             {
899                                 f |= mtrl_flags[i].flag;
900                                 break;
901                             }
902 
903                         p += n;
904                     }
905 
906                     mp->fl = f;
907                 }
908                 else if (sscanf(p, "angle %f", &mp->angle) == 1)
909                 {
910                 }
911                 else if (sscanf(p, "alpha-test %15s %f",
912                                 str, &mp->alpha_ref) == 2)
913                 {
914                     mp->fl |= M_ALPHA_TEST;
915 
916                     for (i = 0; i < ARRAYSIZE(mtrl_func_names); i++)
917                         if (strcmp(str, mtrl_func_names[i]) == 0)
918                         {
919                             mp->alpha_func = i;
920                             break;
921                         }
922                 }
923                 else /* Unknown directive */;
924             }
925 
926             fs_close(fp);
927             return 1;
928         }
929         else /* Unknown material */;
930     }
931     return 0;
932 }
933 
934 /*---------------------------------------------------------------------------*/
935