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