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