Added struct b_offs to solid_base.
[neverball] / share / solid_base.c
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_VER_MINIMUM = 6,
29     SOL_VER_PATH_FLAGS,
30     SOL_VER_CURRENT = SOL_VER_PATH_FLAGS
31 };
32
33 #define SOL_MAGIC (0xAF | 'S' << 8 | 'O' << 16 | 'L' << 24)
34
35 /*---------------------------------------------------------------------------*/
36
37 static int sol_version;
38
39 static int sol_file(fs_file fin)
40 {
41     int magic;
42     int version;
43
44     get_index(fin, &magic);
45     get_index(fin, &version);
46
47     if (magic != SOL_MAGIC || (version < SOL_VER_MINIMUM ||
48                                version > SOL_VER_CURRENT))
49         return 0;
50
51     sol_version = version;
52
53     return 1;
54 }
55
56 static void sol_load_mtrl(fs_file fin, struct b_mtrl *mp)
57 {
58     get_array(fin,  mp->d, 4);
59     get_array(fin,  mp->a, 4);
60     get_array(fin,  mp->s, 4);
61     get_array(fin,  mp->e, 4);
62     get_array(fin,  mp->h, 1);
63     get_index(fin, &mp->fl);
64
65     fs_read(mp->f, 1, PATHMAX, fin);
66 }
67
68 static void sol_load_vert(fs_file fin, struct b_vert *vp)
69 {
70     get_array(fin,  vp->p, 3);
71 }
72
73 static void sol_load_edge(fs_file fin, struct b_edge *ep)
74 {
75     get_index(fin, &ep->vi);
76     get_index(fin, &ep->vj);
77 }
78
79 static void sol_load_side(fs_file fin, struct b_side *sp)
80 {
81     get_array(fin,  sp->n, 3);
82     get_float(fin, &sp->d);
83 }
84
85 static void sol_load_texc(fs_file fin, struct b_texc *tp)
86 {
87     get_array(fin,  tp->u, 2);
88 }
89
90 static void sol_load_offs(fs_file fin, struct b_offs *op)
91 {
92     get_index(fin, &op->ti);
93     get_index(fin, &op->si);
94     get_index(fin, &op->vi);
95 }
96
97 static void sol_load_geom(fs_file fin, struct b_geom *gp)
98 {
99     get_index(fin, &gp->mi);
100     get_index(fin, &gp->oi);
101     get_index(fin, &gp->oj);
102     get_index(fin, &gp->ok);
103 }
104
105 static void sol_load_lump(fs_file fin, struct b_lump *lp)
106 {
107     get_index(fin, &lp->fl);
108     get_index(fin, &lp->v0);
109     get_index(fin, &lp->vc);
110     get_index(fin, &lp->e0);
111     get_index(fin, &lp->ec);
112     get_index(fin, &lp->g0);
113     get_index(fin, &lp->gc);
114     get_index(fin, &lp->s0);
115     get_index(fin, &lp->sc);
116 }
117
118 static void sol_load_node(fs_file fin, struct b_node *np)
119 {
120     get_index(fin, &np->si);
121     get_index(fin, &np->ni);
122     get_index(fin, &np->nj);
123     get_index(fin, &np->l0);
124     get_index(fin, &np->lc);
125 }
126
127 static void sol_load_path(fs_file fin, struct b_path *pp)
128 {
129     get_array(fin,  pp->p, 3);
130     get_float(fin, &pp->t);
131     get_index(fin, &pp->pi);
132     get_index(fin, &pp->f);
133     get_index(fin, &pp->s);
134
135     pp->tm = TIME_TO_MS(pp->t);
136     pp->t  = MS_TO_TIME(pp->tm);
137
138     if (sol_version >= SOL_VER_PATH_FLAGS)
139         get_index(fin, &pp->fl);
140
141     pp->e[0] = 1.0f;
142     pp->e[1] = 0.0f;
143     pp->e[2] = 0.0f;
144     pp->e[3] = 0.0f;
145
146     if (pp->fl & P_ORIENTED)
147         get_array(fin, pp->e, 4);
148 }
149
150 static void sol_load_body(fs_file fin, struct b_body *bp)
151 {
152     get_index(fin, &bp->pi);
153     get_index(fin, &bp->ni);
154     get_index(fin, &bp->l0);
155     get_index(fin, &bp->lc);
156     get_index(fin, &bp->g0);
157     get_index(fin, &bp->gc);
158 }
159
160 static void sol_load_item(fs_file fin, struct b_item *hp)
161 {
162     get_array(fin,  hp->p, 3);
163     get_index(fin, &hp->t);
164     get_index(fin, &hp->n);
165 }
166
167 static void sol_load_goal(fs_file fin, struct b_goal *zp)
168 {
169     get_array(fin,  zp->p, 3);
170     get_float(fin, &zp->r);
171 }
172
173 static void sol_load_swch(fs_file fin, struct b_swch *xp)
174 {
175     float f;
176     int i;
177
178     get_array(fin,  xp->p, 3);
179     get_float(fin, &xp->r);
180     get_index(fin, &xp->pi);
181     get_float(fin, &xp->t);
182     get_float(fin, &f);
183     get_index(fin, &xp->f);
184     get_index(fin, &i);
185     get_index(fin, &xp->i);
186
187     xp->tm = TIME_TO_MS(xp->t);
188     xp->t = MS_TO_TIME(xp->tm);
189 }
190
191 static void sol_load_bill(fs_file fin, struct b_bill *rp)
192 {
193     get_index(fin, &rp->fl);
194     get_index(fin, &rp->mi);
195     get_float(fin, &rp->t);
196     get_float(fin, &rp->d);
197     get_array(fin,  rp->w,  3);
198     get_array(fin,  rp->h,  3);
199     get_array(fin,  rp->rx, 3);
200     get_array(fin,  rp->ry, 3);
201     get_array(fin,  rp->rz, 3);
202     get_array(fin,  rp->p,  3);
203 }
204
205 static void sol_load_jump(fs_file fin, struct b_jump *jp)
206 {
207     get_array(fin,  jp->p, 3);
208     get_array(fin,  jp->q, 3);
209     get_float(fin, &jp->r);
210 }
211
212 static void sol_load_ball(fs_file fin, struct b_ball *up)
213 {
214     get_array(fin,  up->p, 3);
215     get_float(fin, &up->r);
216 }
217
218 static void sol_load_view(fs_file fin, struct b_view *wp)
219 {
220     get_array(fin,  wp->p, 3);
221     get_array(fin,  wp->q, 3);
222 }
223
224 static void sol_load_dict(fs_file fin, struct b_dict *dp)
225 {
226     get_index(fin, &dp->ai);
227     get_index(fin, &dp->aj);
228 }
229
230 static void sol_load_indx(fs_file fin, struct s_base *fp)
231 {
232     get_index(fin, &fp->ac);
233     get_index(fin, &fp->dc);
234     get_index(fin, &fp->mc);
235     get_index(fin, &fp->vc);
236     get_index(fin, &fp->ec);
237     get_index(fin, &fp->sc);
238     get_index(fin, &fp->tc);
239     get_index(fin, &fp->oc);
240     get_index(fin, &fp->gc);
241     get_index(fin, &fp->lc);
242     get_index(fin, &fp->nc);
243     get_index(fin, &fp->pc);
244     get_index(fin, &fp->bc);
245     get_index(fin, &fp->hc);
246     get_index(fin, &fp->zc);
247     get_index(fin, &fp->jc);
248     get_index(fin, &fp->xc);
249     get_index(fin, &fp->rc);
250     get_index(fin, &fp->uc);
251     get_index(fin, &fp->wc);
252     get_index(fin, &fp->ic);
253 }
254
255 static int sol_load_file(fs_file fin, struct s_base *fp)
256 {
257     int i;
258
259     if (!sol_file(fin))
260         return 0;
261
262     sol_load_indx(fin, fp);
263
264     if (fp->ac)
265         fp->av = (char *)          calloc(fp->ac, sizeof (*fp->av));
266     if (fp->mc)
267         fp->mv = (struct b_mtrl *) calloc(fp->mc, sizeof (*fp->mv));
268     if (fp->vc)
269         fp->vv = (struct b_vert *) calloc(fp->vc, sizeof (*fp->vv));
270     if (fp->ec)
271         fp->ev = (struct b_edge *) calloc(fp->ec, sizeof (*fp->ev));
272     if (fp->sc)
273         fp->sv = (struct b_side *) calloc(fp->sc, sizeof (*fp->sv));
274     if (fp->tc)
275         fp->tv = (struct b_texc *) calloc(fp->tc, sizeof (*fp->tv));
276     if (fp->oc)
277         fp->ov = (struct b_offs *) calloc(fp->oc, sizeof (*fp->ov));
278     if (fp->gc)
279         fp->gv = (struct b_geom *) calloc(fp->gc, sizeof (*fp->gv));
280     if (fp->lc)
281         fp->lv = (struct b_lump *) calloc(fp->lc, sizeof (*fp->lv));
282     if (fp->nc)
283         fp->nv = (struct b_node *) calloc(fp->nc, sizeof (*fp->nv));
284     if (fp->pc)
285         fp->pv = (struct b_path *) calloc(fp->pc, sizeof (*fp->pv));
286     if (fp->bc)
287         fp->bv = (struct b_body *) calloc(fp->bc, sizeof (*fp->bv));
288     if (fp->hc)
289         fp->hv = (struct b_item *) calloc(fp->hc, sizeof (*fp->hv));
290     if (fp->zc)
291         fp->zv = (struct b_goal *) calloc(fp->zc, sizeof (*fp->zv));
292     if (fp->jc)
293         fp->jv = (struct b_jump *) calloc(fp->jc, sizeof (*fp->jv));
294     if (fp->xc)
295         fp->xv = (struct b_swch *) calloc(fp->xc, sizeof (*fp->xv));
296     if (fp->rc)
297         fp->rv = (struct b_bill *) calloc(fp->rc, sizeof (*fp->rv));
298     if (fp->uc)
299         fp->uv = (struct b_ball *) calloc(fp->uc, sizeof (*fp->uv));
300     if (fp->wc)
301         fp->wv = (struct b_view *) calloc(fp->wc, sizeof (*fp->wv));
302     if (fp->dc)
303         fp->dv = (struct b_dict *) calloc(fp->dc, sizeof (*fp->dv));
304     if (fp->ic)
305         fp->iv = (int *)           calloc(fp->ic, sizeof (*fp->iv));
306
307     if (fp->ac)
308         fs_read(fp->av, 1, fp->ac, fin);
309
310     for (i = 0; i < fp->dc; i++) sol_load_dict(fin, fp->dv + i);
311     for (i = 0; i < fp->mc; i++) sol_load_mtrl(fin, fp->mv + i);
312     for (i = 0; i < fp->vc; i++) sol_load_vert(fin, fp->vv + i);
313     for (i = 0; i < fp->ec; i++) sol_load_edge(fin, fp->ev + i);
314     for (i = 0; i < fp->sc; i++) sol_load_side(fin, fp->sv + i);
315     for (i = 0; i < fp->tc; i++) sol_load_texc(fin, fp->tv + i);
316     for (i = 0; i < fp->oc; i++) sol_load_offs(fin, fp->ov + i);
317     for (i = 0; i < fp->gc; i++) sol_load_geom(fin, fp->gv + i);
318     for (i = 0; i < fp->lc; i++) sol_load_lump(fin, fp->lv + i);
319     for (i = 0; i < fp->nc; i++) sol_load_node(fin, fp->nv + i);
320     for (i = 0; i < fp->pc; i++) sol_load_path(fin, fp->pv + i);
321     for (i = 0; i < fp->bc; i++) sol_load_body(fin, fp->bv + i);
322     for (i = 0; i < fp->hc; i++) sol_load_item(fin, fp->hv + i);
323     for (i = 0; i < fp->zc; i++) sol_load_goal(fin, fp->zv + i);
324     for (i = 0; i < fp->jc; i++) sol_load_jump(fin, fp->jv + i);
325     for (i = 0; i < fp->xc; i++) sol_load_swch(fin, fp->xv + i);
326     for (i = 0; i < fp->rc; i++) sol_load_bill(fin, fp->rv + i);
327     for (i = 0; i < fp->uc; i++) sol_load_ball(fin, fp->uv + i);
328     for (i = 0; i < fp->wc; i++) sol_load_view(fin, fp->wv + i);
329     for (i = 0; i < fp->ic; i++) get_index(fin, fp->iv + i);
330
331     /* Magically "fix" all of our code. */
332
333     if (!fp->uc)
334     {
335         fp->uc = 1;
336         fp->uv = (struct b_ball *) calloc(fp->uc, sizeof (*fp->uv));
337     }
338
339     return 1;
340 }
341
342 static int sol_load_head(fs_file fin, struct s_base *fp)
343 {
344     if (!sol_file(fin))
345         return 0;
346
347     sol_load_indx(fin, fp);
348
349     if (fp->ac)
350     {
351         fp->av = (char *) calloc(fp->ac, sizeof (*fp->av));
352         fs_read(fp->av, 1, fp->ac, fin);
353     }
354
355     if (fp->dc)
356     {
357         int i;
358
359         fp->dv = (struct b_dict *) calloc(fp->dc, sizeof (*fp->dv));
360
361         for (i = 0; i < fp->dc; i++)
362             sol_load_dict(fin, fp->dv + i);
363     }
364
365     return 1;
366 }
367
368 int sol_load_base(struct s_base *fp, const char *filename)
369 {
370     fs_file fin;
371     int res = 0;
372
373     memset(fp, 0, sizeof (*fp));
374
375     if ((fin = fs_open(filename, "r")))
376     {
377         res = sol_load_file(fin, fp);
378         fs_close(fin);
379     }
380     return res;
381 }
382
383 int sol_load_meta(struct s_base *fp, const char *filename)
384 {
385     fs_file fin;
386     int res = 0;
387
388     if ((fin = fs_open(filename, "r")))
389     {
390         res = sol_load_head(fin, fp);
391         fs_close(fin);
392     }
393     return res;
394 }
395
396 void sol_free_base(struct s_base *fp)
397 {
398     if (fp->av) free(fp->av);
399     if (fp->mv) free(fp->mv);
400     if (fp->vv) free(fp->vv);
401     if (fp->ev) free(fp->ev);
402     if (fp->sv) free(fp->sv);
403     if (fp->tv) free(fp->tv);
404     if (fp->ov) free(fp->ov);
405     if (fp->gv) free(fp->gv);
406     if (fp->lv) free(fp->lv);
407     if (fp->nv) free(fp->nv);
408     if (fp->pv) free(fp->pv);
409     if (fp->bv) free(fp->bv);
410     if (fp->hv) free(fp->hv);
411     if (fp->zv) free(fp->zv);
412     if (fp->jv) free(fp->jv);
413     if (fp->xv) free(fp->xv);
414     if (fp->rv) free(fp->rv);
415     if (fp->uv) free(fp->uv);
416     if (fp->wv) free(fp->wv);
417     if (fp->dv) free(fp->dv);
418     if (fp->iv) free(fp->iv);
419
420     memset(fp, 0, sizeof (*fp));
421 }
422
423 /*---------------------------------------------------------------------------*/
424
425 static void sol_stor_mtrl(fs_file fout, struct b_mtrl *mp)
426 {
427     put_array(fout, mp->d, 4);
428     put_array(fout, mp->a, 4);
429     put_array(fout, mp->s, 4);
430     put_array(fout, mp->e, 4);
431     put_array(fout, mp->h, 1);
432     put_index(fout, mp->fl);
433
434     fs_write(mp->f, 1, PATHMAX, fout);
435 }
436
437 static void sol_stor_vert(fs_file fout, struct b_vert *vp)
438 {
439     put_array(fout,  vp->p, 3);
440 }
441
442 static void sol_stor_edge(fs_file fout, struct b_edge *ep)
443 {
444     put_index(fout, ep->vi);
445     put_index(fout, ep->vj);
446 }
447
448 static void sol_stor_side(fs_file fout, struct b_side *sp)
449 {
450     put_array(fout, sp->n, 3);
451     put_float(fout, sp->d);
452 }
453
454 static void sol_stor_texc(fs_file fout, struct b_texc *tp)
455 {
456     put_array(fout,  tp->u, 2);
457 }
458
459 static void sol_stor_offs(fs_file fout, struct b_offs *op)
460 {
461     put_index(fout, op->ti);
462     put_index(fout, op->si);
463     put_index(fout, op->vi);
464 }
465
466 static void sol_stor_geom(fs_file fout, struct b_geom *gp)
467 {
468     put_index(fout, gp->mi);
469     put_index(fout, gp->oi);
470     put_index(fout, gp->oj);
471     put_index(fout, gp->ok);
472 }
473
474 static void sol_stor_lump(fs_file fout, struct b_lump *lp)
475 {
476     put_index(fout, lp->fl);
477     put_index(fout, lp->v0);
478     put_index(fout, lp->vc);
479     put_index(fout, lp->e0);
480     put_index(fout, lp->ec);
481     put_index(fout, lp->g0);
482     put_index(fout, lp->gc);
483     put_index(fout, lp->s0);
484     put_index(fout, lp->sc);
485 }
486
487 static void sol_stor_node(fs_file fout, struct b_node *np)
488 {
489     put_index(fout, np->si);
490     put_index(fout, np->ni);
491     put_index(fout, np->nj);
492     put_index(fout, np->l0);
493     put_index(fout, np->lc);
494 }
495
496 static void sol_stor_path(fs_file fout, struct b_path *pp)
497 {
498     put_array(fout, pp->p, 3);
499     put_float(fout, pp->t);
500     put_index(fout, pp->pi);
501     put_index(fout, pp->f);
502     put_index(fout, pp->s);
503     put_index(fout, pp->fl);
504
505     if (pp->fl & P_ORIENTED)
506         put_array(fout, pp->e, 4);
507 }
508
509 static void sol_stor_body(fs_file fout, struct b_body *bp)
510 {
511     put_index(fout, bp->pi);
512     put_index(fout, bp->ni);
513     put_index(fout, bp->l0);
514     put_index(fout, bp->lc);
515     put_index(fout, bp->g0);
516     put_index(fout, bp->gc);
517 }
518
519 static void sol_stor_item(fs_file fout, struct b_item *hp)
520 {
521     put_array(fout, hp->p, 3);
522     put_index(fout, hp->t);
523     put_index(fout, hp->n);
524 }
525
526 static void sol_stor_goal(fs_file fout, struct b_goal *zp)
527 {
528     put_array(fout, zp->p, 3);
529     put_float(fout, zp->r);
530 }
531
532 static void sol_stor_swch(fs_file fout, struct b_swch *xp)
533 {
534     put_array(fout, xp->p, 3);
535     put_float(fout, xp->r);
536     put_index(fout, xp->pi);
537     put_float(fout, xp->t);
538     put_float(fout, xp->t);
539     put_index(fout, xp->f);
540     put_index(fout, xp->f);
541     put_index(fout, xp->i);
542 }
543
544 static void sol_stor_bill(fs_file fout, struct b_bill *rp)
545 {
546     put_index(fout, rp->fl);
547     put_index(fout, rp->mi);
548     put_float(fout, rp->t);
549     put_float(fout, rp->d);
550     put_array(fout, rp->w,  3);
551     put_array(fout, rp->h,  3);
552     put_array(fout, rp->rx, 3);
553     put_array(fout, rp->ry, 3);
554     put_array(fout, rp->rz, 3);
555     put_array(fout, rp->p,  3);
556 }
557
558 static void sol_stor_jump(fs_file fout, struct b_jump *jp)
559 {
560     put_array(fout, jp->p, 3);
561     put_array(fout, jp->q, 3);
562     put_float(fout, jp->r);
563 }
564
565 static void sol_stor_ball(fs_file fout, struct b_ball *bp)
566 {
567     put_array(fout, bp->p, 3);
568     put_float(fout, bp->r);
569 }
570
571 static void sol_stor_view(fs_file fout, struct b_view *wp)
572 {
573     put_array(fout,  wp->p, 3);
574     put_array(fout,  wp->q, 3);
575 }
576
577 static void sol_stor_dict(fs_file fout, struct b_dict *dp)
578 {
579     put_index(fout, dp->ai);
580     put_index(fout, dp->aj);
581 }
582
583 static void sol_stor_file(fs_file fout, struct s_base *fp)
584 {
585     int i;
586     int magic   = SOL_MAGIC;
587     int version = SOL_VER_CURRENT;
588
589     put_index(fout, magic);
590     put_index(fout, version);
591
592     put_index(fout, fp->ac);
593     put_index(fout, fp->dc);
594     put_index(fout, fp->mc);
595     put_index(fout, fp->vc);
596     put_index(fout, fp->ec);
597     put_index(fout, fp->sc);
598     put_index(fout, fp->tc);
599     put_index(fout, fp->oc);
600     put_index(fout, fp->gc);
601     put_index(fout, fp->lc);
602     put_index(fout, fp->nc);
603     put_index(fout, fp->pc);
604     put_index(fout, fp->bc);
605     put_index(fout, fp->hc);
606     put_index(fout, fp->zc);
607     put_index(fout, fp->jc);
608     put_index(fout, fp->xc);
609     put_index(fout, fp->rc);
610     put_index(fout, fp->uc);
611     put_index(fout, fp->wc);
612     put_index(fout, fp->ic);
613
614     fs_write(fp->av, 1, fp->ac, fout);
615
616     for (i = 0; i < fp->dc; i++) sol_stor_dict(fout, fp->dv + i);
617     for (i = 0; i < fp->mc; i++) sol_stor_mtrl(fout, fp->mv + i);
618     for (i = 0; i < fp->vc; i++) sol_stor_vert(fout, fp->vv + i);
619     for (i = 0; i < fp->ec; i++) sol_stor_edge(fout, fp->ev + i);
620     for (i = 0; i < fp->sc; i++) sol_stor_side(fout, fp->sv + i);
621     for (i = 0; i < fp->tc; i++) sol_stor_texc(fout, fp->tv + i);
622     for (i = 0; i < fp->oc; i++) sol_stor_offs(fout, fp->ov + i);
623     for (i = 0; i < fp->gc; i++) sol_stor_geom(fout, fp->gv + i);
624     for (i = 0; i < fp->lc; i++) sol_stor_lump(fout, fp->lv + i);
625     for (i = 0; i < fp->nc; i++) sol_stor_node(fout, fp->nv + i);
626     for (i = 0; i < fp->pc; i++) sol_stor_path(fout, fp->pv + i);
627     for (i = 0; i < fp->bc; i++) sol_stor_body(fout, fp->bv + i);
628     for (i = 0; i < fp->hc; i++) sol_stor_item(fout, fp->hv + i);
629     for (i = 0; i < fp->zc; i++) sol_stor_goal(fout, fp->zv + i);
630     for (i = 0; i < fp->jc; i++) sol_stor_jump(fout, fp->jv + i);
631     for (i = 0; i < fp->xc; i++) sol_stor_swch(fout, fp->xv + i);
632     for (i = 0; i < fp->rc; i++) sol_stor_bill(fout, fp->rv + i);
633     for (i = 0; i < fp->uc; i++) sol_stor_ball(fout, fp->uv + i);
634     for (i = 0; i < fp->wc; i++) sol_stor_view(fout, fp->wv + i);
635     for (i = 0; i < fp->ic; i++) put_index(fout, fp->iv[i]);
636 }
637
638 int sol_stor_base(struct s_base *fp, const char *filename)
639 {
640     fs_file fout;
641
642     if ((fout = fs_open(filename, "w")))
643     {
644         sol_stor_file(fout, fp);
645         fs_close(fout);
646
647         return 1;
648     }
649     return 0;
650 }
651
652 /*---------------------------------------------------------------------------*/