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