| 1 | 
#ifndef lint | 
| 2 | 
static const char RCSid[] = "$Id: writemesh.c,v 2.5 2004/03/27 12:41:45 schorsch Exp $"; | 
| 3 | 
#endif | 
| 4 | 
/* | 
| 5 | 
 *  Routines for writing compiled mesh to a file stream | 
| 6 | 
 */ | 
| 7 | 
 | 
| 8 | 
#include  "standard.h" | 
| 9 | 
#include  "octree.h" | 
| 10 | 
#include  "object.h" | 
| 11 | 
#include  "mesh.h" | 
| 12 | 
 | 
| 13 | 
#ifdef putc_unlocked            /* avoid horrendous overhead of flockfile */ | 
| 14 | 
#define putc    putc_unlocked | 
| 15 | 
#endif | 
| 16 | 
 | 
| 17 | 
static void putfullnode(OCTREE fn, FILE *fp); | 
| 18 | 
static void puttree(OCTREE ot, FILE *fp); | 
| 19 | 
static void putpatch(MESHPATCH *pp, FILE *fp); | 
| 20 | 
 | 
| 21 | 
 | 
| 22 | 
static void | 
| 23 | 
putfullnode(            /* write out a full node */ | 
| 24 | 
        OCTREE  fn, | 
| 25 | 
        FILE    *fp | 
| 26 | 
) | 
| 27 | 
{ | 
| 28 | 
        OBJECT  oset[MAXSET+1]; | 
| 29 | 
        register int  i; | 
| 30 | 
 | 
| 31 | 
        objset(oset, fn); | 
| 32 | 
        for (i = 0; i <= oset[0]; i++) | 
| 33 | 
                putint((long)oset[i], sizeof(OBJECT), fp); | 
| 34 | 
} | 
| 35 | 
 | 
| 36 | 
 | 
| 37 | 
static void | 
| 38 | 
puttree(                        /* write octree to fp in pre-order form */ | 
| 39 | 
        register OCTREE ot, | 
| 40 | 
        FILE            *fp | 
| 41 | 
) | 
| 42 | 
{ | 
| 43 | 
         | 
| 44 | 
        if (istree(ot)) { | 
| 45 | 
                register int    i; | 
| 46 | 
                putc(OT_TREE, fp);              /* indicate tree */ | 
| 47 | 
                for (i = 0; i < 8; i++)         /* write tree */ | 
| 48 | 
                        puttree(octkid(ot, i), fp); | 
| 49 | 
                return; | 
| 50 | 
        } | 
| 51 | 
        if (isfull(ot)) { | 
| 52 | 
                putc(OT_FULL, fp);              /* indicate fullnode */ | 
| 53 | 
                putfullnode(ot, fp);            /* write fullnode */ | 
| 54 | 
                return; | 
| 55 | 
        } | 
| 56 | 
        putc(OT_EMPTY, fp);                     /* indicate empty */ | 
| 57 | 
} | 
| 58 | 
 | 
| 59 | 
 | 
| 60 | 
static void | 
| 61 | 
putpatch(                       /* write out a mesh patch */ | 
| 62 | 
        register MESHPATCH      *pp, | 
| 63 | 
        FILE                    *fp | 
| 64 | 
) | 
| 65 | 
{ | 
| 66 | 
        int     flags = MT_V; | 
| 67 | 
        int     i, j; | 
| 68 | 
                                        /* vertex flags */ | 
| 69 | 
        if (pp->norm != NULL) | 
| 70 | 
                flags |= MT_N; | 
| 71 | 
        if (pp->uv != NULL) | 
| 72 | 
                flags |= MT_UV; | 
| 73 | 
        putint((long)flags, 1, fp); | 
| 74 | 
                                        /* number of vertices */ | 
| 75 | 
        putint((long)pp->nverts, 2, fp); | 
| 76 | 
                                        /* vertex xyz locations */ | 
| 77 | 
        for (i = 0; i < pp->nverts; i++) | 
| 78 | 
                for (j = 0; j < 3; j++) | 
| 79 | 
                        putint((long)pp->xyz[i][j], 4, fp); | 
| 80 | 
                                        /* vertex normals */ | 
| 81 | 
        if (flags & MT_N) | 
| 82 | 
                for (i = 0; i < pp->nverts; i++) | 
| 83 | 
                        putint((long)pp->norm[i], 4, fp); | 
| 84 | 
                                        /* uv coordinates */ | 
| 85 | 
        if (flags & MT_UV) | 
| 86 | 
                for (i = 0; i < pp->nverts; i++) | 
| 87 | 
                        for (j = 0; j < 2; j++) | 
| 88 | 
                                putint((long)pp->uv[i][j], 4, fp); | 
| 89 | 
                                        /* local triangles */ | 
| 90 | 
        putint((long)pp->ntris, 2, fp); | 
| 91 | 
        for (i = 0; i < pp->ntris; i++) { | 
| 92 | 
                putint((long)pp->tri[i].v1, 1, fp); | 
| 93 | 
                putint((long)pp->tri[i].v2, 1, fp); | 
| 94 | 
                putint((long)pp->tri[i].v3, 1, fp); | 
| 95 | 
        } | 
| 96 | 
                                        /* local triangle material(s) */ | 
| 97 | 
        if (pp->trimat == NULL) { | 
| 98 | 
                putint(1L, 2, fp); | 
| 99 | 
                putint((long)pp->solemat, 2, fp); | 
| 100 | 
        } else { | 
| 101 | 
                putint((long)pp->ntris, 2, fp); | 
| 102 | 
                for (i = 0; i < pp->ntris; i++) | 
| 103 | 
                        putint((long)pp->trimat[i], 2, fp); | 
| 104 | 
        } | 
| 105 | 
                                        /* joiner triangles */ | 
| 106 | 
        putint((long)pp->nj1tris, 2, fp); | 
| 107 | 
        for (i = 0; i < pp->nj1tris; i++) { | 
| 108 | 
                putint((long)pp->j1tri[i].v1j, 4, fp); | 
| 109 | 
                putint((long)pp->j1tri[i].v2, 1, fp); | 
| 110 | 
                putint((long)pp->j1tri[i].v3, 1, fp); | 
| 111 | 
                putint((long)pp->j1tri[i].mat, 2, fp); | 
| 112 | 
        } | 
| 113 | 
                                        /* double joiner triangles */ | 
| 114 | 
        putint((long)pp->nj2tris, 2, fp); | 
| 115 | 
        for (i = 0; i < pp->nj2tris; i++) { | 
| 116 | 
                putint((long)pp->j2tri[i].v1j, 4, fp); | 
| 117 | 
                putint((long)pp->j2tri[i].v2j, 4, fp); | 
| 118 | 
                putint((long)pp->j2tri[i].v3, 1, fp); | 
| 119 | 
                putint((long)pp->j2tri[i].mat, 2, fp); | 
| 120 | 
        } | 
| 121 | 
} | 
| 122 | 
 | 
| 123 | 
 | 
| 124 | 
void | 
| 125 | 
writemesh(mp, fp)                       /* write mesh structures to fp */ | 
| 126 | 
MESH    *mp; | 
| 127 | 
FILE    *fp; | 
| 128 | 
{ | 
| 129 | 
        char    *err; | 
| 130 | 
        char    sbuf[64]; | 
| 131 | 
        int     i; | 
| 132 | 
                                        /* do we have everything? */ | 
| 133 | 
        if ((mp->ldflags & (IO_SCENE|IO_TREE|IO_BOUNDS)) != | 
| 134 | 
                        (IO_SCENE|IO_TREE|IO_BOUNDS)) | 
| 135 | 
                error(INTERNAL, "missing data in writemesh"); | 
| 136 | 
                                        /* validate mesh data */ | 
| 137 | 
        if ((err = checkmesh(mp)) != NULL) | 
| 138 | 
                error(USER, err); | 
| 139 | 
                                        /* write format number */ | 
| 140 | 
        putint((long)(MESHMAGIC+sizeof(OBJECT)), 2, fp); | 
| 141 | 
                                        /* write boundaries */ | 
| 142 | 
        for (i = 0; i < 3; i++) { | 
| 143 | 
                sprintf(sbuf, "%.12g", mp->mcube.cuorg[i]); | 
| 144 | 
                putstr(sbuf, fp); | 
| 145 | 
        } | 
| 146 | 
        sprintf(sbuf, "%.12g", mp->mcube.cusize); | 
| 147 | 
        putstr(sbuf, fp); | 
| 148 | 
        for (i = 0; i < 2; i++) { | 
| 149 | 
                putflt(mp->uvlim[0][i], fp); | 
| 150 | 
                putflt(mp->uvlim[1][i], fp); | 
| 151 | 
        } | 
| 152 | 
                                        /* write the octree */ | 
| 153 | 
        puttree(mp->mcube.cutree, fp); | 
| 154 | 
                                        /* write the materials */ | 
| 155 | 
        writescene(mp->mat0, mp->nmats, fp); | 
| 156 | 
                                        /* write the patches */ | 
| 157 | 
        putint((long)mp->npatches, 4, fp); | 
| 158 | 
        for (i = 0; i < mp->npatches; i++) | 
| 159 | 
                putpatch(&mp->patch[i], fp); | 
| 160 | 
        if (ferror(fp)) | 
| 161 | 
                error(SYSTEM, "write error in writemesh"); | 
| 162 | 
} |