| 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 | } |