Add missing credit for Esperanto translation
[neverball.git] / share / solid_base.c
blob45ae351b0d7fafb5eaf6f8b4d60ec1a61387ea5f
1 /*
2 * Copyright (C) 2003 Robert Kooima
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.
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.
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
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"
26 enum
28 SOL_VERSION_1_5 = 6,
29 SOL_VERSION_DEV
32 #define SOL_VERSION_MIN SOL_VERSION_1_5
33 #define SOL_VERSION_CURR SOL_VERSION_DEV
35 #define SOL_MAGIC (0xAF | 'S' << 8 | 'O' << 16 | 'L' << 24)
37 /*---------------------------------------------------------------------------*/
39 static int sol_version;
41 static int sol_file(fs_file fin)
43 int magic;
44 int version;
46 magic = get_index(fin);
47 version = get_index(fin);
49 if (magic != SOL_MAGIC || (version < SOL_VERSION_MIN ||
50 version > SOL_VERSION_CURR))
51 return 0;
53 sol_version = version;
55 return 1;
58 static void sol_load_mtrl(fs_file fin, struct b_mtrl *mp)
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);
66 mp->fl = get_index(fin);
68 fs_read(mp->f, 1, PATHMAX, fin);
70 if (sol_version >= SOL_VERSION_DEV)
72 if (mp->fl & M_ALPHA_TEST)
74 mp->alpha_func = get_index(fin);
75 mp->alpha_ref = get_float(fin);
79 /* Convert 1.5.4 material flags. */
81 if (sol_version == SOL_VERSION_1_5)
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 }
94 if (mp->fl)
96 int i, f;
98 for (f = 0, i = 0; i < ARRAYSIZE(flags); i++)
99 if (mp->fl & flags[i][0])
100 f |= flags[i][1];
102 mp->fl = f;
104 else
106 /* Must be "mtrl/invisible". */
108 mp->fl = M_TRANSPARENT;
109 mp->d[3] = 0.0f;
114 static void sol_load_vert(fs_file fin, struct b_vert *vp)
116 get_array(fin, vp->p, 3);
119 static void sol_load_edge(fs_file fin, struct b_edge *ep)
121 ep->vi = get_index(fin);
122 ep->vj = get_index(fin);
125 static void sol_load_side(fs_file fin, struct b_side *sp)
127 get_array(fin, sp->n, 3);
129 sp->d = get_float(fin);
132 static void sol_load_texc(fs_file fin, struct b_texc *tp)
134 get_array(fin, tp->u, 2);
137 static void sol_load_offs(fs_file fin, struct b_offs *op)
139 op->ti = get_index(fin);
140 op->si = get_index(fin);
141 op->vi = get_index(fin);
144 static void sol_load_geom(fs_file fin, struct b_geom *gp, struct s_base *fp)
146 gp->mi = get_index(fin);
148 if (sol_version >= SOL_VERSION_DEV)
150 gp->oi = get_index(fin);
151 gp->oj = get_index(fin);
152 gp->ok = get_index(fin);
154 else
156 struct b_offs ov[3];
157 int i, j, iv[3], oc;
158 void *p;
160 oc = 0;
162 for (i = 0; i < 3; i++)
164 ov[i].ti = get_index(fin);
165 ov[i].si = get_index(fin);
166 ov[i].vi = get_index(fin);
168 iv[i] = -1;
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)
175 iv[i] = j;
176 break;
179 if (j == fp->oc)
180 oc++;
183 if (oc && (p = realloc(fp->ov, sizeof (struct b_offs) * (fp->oc + oc))))
185 fp->ov = p;
187 for (i = 0; i < 3; i++)
188 if (iv[i] < 0)
190 fp->ov[fp->oc] = ov[i];
191 iv[i] = fp->oc++;
195 gp->oi = iv[0];
196 gp->oj = iv[1];
197 gp->ok = iv[2];
201 static void sol_load_lump(fs_file fin, struct b_lump *lp)
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);
214 static void sol_load_node(fs_file fin, struct b_node *np)
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);
223 static void sol_load_path(fs_file fin, struct b_path *pp)
225 get_array(fin, pp->p, 3);
227 pp->t = get_float(fin);
228 pp->pi = get_index(fin);
229 pp->f = get_index(fin);
230 pp->s = get_index(fin);
232 pp->tm = TIME_TO_MS(pp->t);
233 pp->t = MS_TO_TIME(pp->tm);
235 if (sol_version >= SOL_VERSION_DEV)
236 pp->fl = get_index(fin);
238 pp->e[0] = 1.0f;
239 pp->e[1] = 0.0f;
240 pp->e[2] = 0.0f;
241 pp->e[3] = 0.0f;
243 if (pp->fl & P_ORIENTED)
244 get_array(fin, pp->e, 4);
247 static void sol_load_body(fs_file fin, struct b_body *bp)
249 bp->pi = get_index(fin);
251 if (sol_version >= SOL_VERSION_DEV)
253 bp->pj = get_index(fin);
255 if (bp->pj < 0)
256 bp->pj = bp->pi;
258 else
259 bp->pj = bp->pi;
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);
268 static void sol_load_item(fs_file fin, struct b_item *hp)
270 get_array(fin, hp->p, 3);
272 hp->t = get_index(fin);
273 hp->n = get_index(fin);
276 static void sol_load_goal(fs_file fin, struct b_goal *zp)
278 get_array(fin, zp->p, 3);
280 zp->r = get_float(fin);
283 static void sol_load_swch(fs_file fin, struct b_swch *xp)
285 get_array(fin, xp->p, 3);
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);
295 xp->tm = TIME_TO_MS(xp->t);
296 xp->t = MS_TO_TIME(xp->tm);
299 static void sol_load_bill(fs_file fin, struct b_bill *rp)
301 rp->fl = get_index(fin);
302 rp->mi = get_index(fin);
303 rp->t = get_float(fin);
304 rp->d = get_float(fin);
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);
314 static void sol_load_jump(fs_file fin, struct b_jump *jp)
316 get_array(fin, jp->p, 3);
317 get_array(fin, jp->q, 3);
319 jp->r = get_float(fin);
322 static void sol_load_ball(fs_file fin, struct b_ball *up)
324 get_array(fin, up->p, 3);
326 up->r = get_float(fin);
329 static void sol_load_view(fs_file fin, struct b_view *wp)
331 get_array(fin, wp->p, 3);
332 get_array(fin, wp->q, 3);
335 static void sol_load_dict(fs_file fin, struct b_dict *dp)
337 dp->ai = get_index(fin);
338 dp->aj = get_index(fin);
341 static void sol_load_indx(fs_file fin, struct s_base *fp)
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);
351 if (sol_version >= SOL_VERSION_DEV)
352 fp->oc = get_index(fin);
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);
369 static int sol_load_file(fs_file fin, struct s_base *fp)
371 int i;
373 if (!sol_file(fin))
374 return 0;
376 sol_load_indx(fin, fp);
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));
421 if (fp->ac)
422 fs_read(fp->av, 1, fp->ac, fin);
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);
445 /* Magically "fix" all of our code. */
447 if (!fp->uc)
449 fp->uc = 1;
450 fp->uv = (struct b_ball *) calloc(fp->uc, sizeof (*fp->uv));
453 return 1;
456 static int sol_load_head(fs_file fin, struct s_base *fp)
458 if (!sol_file(fin))
459 return 0;
461 sol_load_indx(fin, fp);
463 if (fp->ac)
465 fp->av = (char *) calloc(fp->ac, sizeof (*fp->av));
466 fs_read(fp->av, 1, fp->ac, fin);
469 if (fp->dc)
471 int i;
473 fp->dv = (struct b_dict *) calloc(fp->dc, sizeof (*fp->dv));
475 for (i = 0; i < fp->dc; i++)
476 sol_load_dict(fin, fp->dv + i);
479 return 1;
482 int sol_load_base(struct s_base *fp, const char *filename)
484 fs_file fin;
485 int res = 0;
487 memset(fp, 0, sizeof (*fp));
489 if ((fin = fs_open(filename, "r")))
491 res = sol_load_file(fin, fp);
492 fs_close(fin);
494 return res;
497 int sol_load_meta(struct s_base *fp, const char *filename)
499 fs_file fin;
500 int res = 0;
502 memset(fp, 0, sizeof (*fp));
504 if ((fin = fs_open(filename, "r")))
506 res = sol_load_head(fin, fp);
507 fs_close(fin);
509 return res;
512 void sol_free_base(struct s_base *fp)
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);
536 memset(fp, 0, sizeof (*fp));
539 /*---------------------------------------------------------------------------*/
541 static void sol_stor_mtrl(fs_file fout, struct b_mtrl *mp)
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);
550 fs_write(mp->f, 1, PATHMAX, fout);
552 if (mp->fl & M_ALPHA_TEST)
554 put_index(fout, mp->alpha_func);
555 put_float(fout, mp->alpha_ref);
559 static void sol_stor_vert(fs_file fout, struct b_vert *vp)
561 put_array(fout, vp->p, 3);
564 static void sol_stor_edge(fs_file fout, struct b_edge *ep)
566 put_index(fout, ep->vi);
567 put_index(fout, ep->vj);
570 static void sol_stor_side(fs_file fout, struct b_side *sp)
572 put_array(fout, sp->n, 3);
573 put_float(fout, sp->d);
576 static void sol_stor_texc(fs_file fout, struct b_texc *tp)
578 put_array(fout, tp->u, 2);
581 static void sol_stor_offs(fs_file fout, struct b_offs *op)
583 put_index(fout, op->ti);
584 put_index(fout, op->si);
585 put_index(fout, op->vi);
588 static void sol_stor_geom(fs_file fout, struct b_geom *gp)
590 put_index(fout, gp->mi);
591 put_index(fout, gp->oi);
592 put_index(fout, gp->oj);
593 put_index(fout, gp->ok);
596 static void sol_stor_lump(fs_file fout, struct b_lump *lp)
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);
609 static void sol_stor_node(fs_file fout, struct b_node *np)
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);
618 static void sol_stor_path(fs_file fout, struct b_path *pp)
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);
627 if (pp->fl & P_ORIENTED)
628 put_array(fout, pp->e, 4);
631 static void sol_stor_body(fs_file fout, struct b_body *bp)
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);
642 static void sol_stor_item(fs_file fout, struct b_item *hp)
644 put_array(fout, hp->p, 3);
645 put_index(fout, hp->t);
646 put_index(fout, hp->n);
649 static void sol_stor_goal(fs_file fout, struct b_goal *zp)
651 put_array(fout, zp->p, 3);
652 put_float(fout, zp->r);
655 static void sol_stor_swch(fs_file fout, struct b_swch *xp)
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);
667 static void sol_stor_bill(fs_file fout, struct b_bill *rp)
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);
681 static void sol_stor_jump(fs_file fout, struct b_jump *jp)
683 put_array(fout, jp->p, 3);
684 put_array(fout, jp->q, 3);
685 put_float(fout, jp->r);
688 static void sol_stor_ball(fs_file fout, struct b_ball *bp)
690 put_array(fout, bp->p, 3);
691 put_float(fout, bp->r);
694 static void sol_stor_view(fs_file fout, struct b_view *wp)
696 put_array(fout, wp->p, 3);
697 put_array(fout, wp->q, 3);
700 static void sol_stor_dict(fs_file fout, struct b_dict *dp)
702 put_index(fout, dp->ai);
703 put_index(fout, dp->aj);
706 static void sol_stor_file(fs_file fout, struct s_base *fp)
708 int i;
709 int magic = SOL_MAGIC;
710 int version = SOL_VERSION_CURR;
712 put_index(fout, magic);
713 put_index(fout, version);
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);
737 fs_write(fp->av, 1, fp->ac, fout);
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]);
761 int sol_stor_base(struct s_base *fp, const char *filename)
763 fs_file fout;
765 if ((fout = fs_open(filename, "w")))
767 sol_stor_file(fout, fp);
768 fs_close(fout);
770 return 1;
772 return 0;
775 /*---------------------------------------------------------------------------*/
777 const struct path tex_paths[4] = {
778 { "textures/", ".png" },
779 { "textures/", ".jpg" },
780 { "", ".png" },
781 { "", ".jpg" }
784 const struct path mtrl_paths[2] = {
785 { "textures/", "" },
786 { "", "" }
789 /*---------------------------------------------------------------------------*/
792 * This has to match up with mtrl_func_syms in mtrl.c.
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"
805 static const struct
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 },
822 int mtrl_read(struct b_mtrl *mp, const char *name)
824 static char line[MAXSTR];
825 static char word[MAXSTR];
827 fs_file fp;
828 int i;
830 if (mp && name && *name)
832 SAFECPY(mp->f, name);
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;
843 mp->alpha_func = 0;
844 mp->alpha_ref = 0.0f;
846 fp = NULL;
848 for (i = 0; i < ARRAYSIZE(mtrl_paths); i++)
850 CONCAT_PATH(line, &mtrl_paths[i], name);
852 if ((fp = fs_open(line, "r")))
853 break;
856 if (fp)
858 char str[16] = "";
860 while (fs_gets(line, sizeof (line), fp))
862 char *p = strip_newline(line);
864 if (sscanf(p, "diffuse %f %f %f %f",
865 &mp->d[0], &mp->d[1],
866 &mp->d[2], &mp->d[3]) == 4)
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)
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)
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)
884 else if (sscanf(p, "shininess %f", &mp->h[0]) == 1)
887 else if (strncmp(p, "flags ", 6) == 0)
889 int f = 0;
890 int n;
892 p += 6;
894 while (sscanf(p, "%s%n", word, &n) > 0)
896 for (i = 0; i < ARRAYSIZE(mtrl_flags); i++)
897 if (strcmp(word, mtrl_flags[i].name) == 0)
899 f |= mtrl_flags[i].flag;
900 break;
903 p += n;
906 mp->fl = f;
908 else if (sscanf(p, "angle %f", &mp->angle) == 1)
911 else if (sscanf(p, "alpha-test %15s %f",
912 str, &mp->alpha_ref) == 2)
914 mp->fl |= M_ALPHA_TEST;
916 for (i = 0; i < ARRAYSIZE(mtrl_func_names); i++)
917 if (strcmp(str, mtrl_func_names[i]) == 0)
919 mp->alpha_func = i;
920 break;
923 else /* Unknown directive */;
926 fs_close(fp);
927 return 1;
929 else /* Unknown material */;
931 return 0;
934 /*---------------------------------------------------------------------------*/