mdl.c (7037B)
1 2 #include "mdl.h" 3 #include "debug.h" 4 #include "vec3.h" 5 #include <assert.h> 6 7 8 static inline void write_tag(enum mdl_tag tag, FILE *out) 9 { 10 fwrite(&tag, 1, 1, out); 11 } 12 13 // little endian is assumed... 14 static inline void write_int(int val, FILE *out) 15 { 16 assert(val != 0); 17 fwrite(&val, sizeof(val), 1, out); 18 } 19 20 static inline void write_nfloats(float *floats, int num_floats, FILE *out) 21 { 22 fwrite(floats, sizeof(*floats), num_floats, out); 23 } 24 25 static inline void write_floats(float *floats, int num_floats, FILE *out) 26 { 27 write_int(num_floats, out); 28 write_nfloats(floats, num_floats, out); 29 } 30 31 static inline void write_ints(u32 *ints, int num_ints, FILE *out) 32 { 33 write_int(num_ints, out); 34 fwrite(ints, sizeof(*ints), num_ints, out); 35 } 36 37 void init_mdl_geometry(struct mdl_geometry *lgeom) 38 { 39 init_make_geometry(&lgeom->mkgeom); 40 vec3_set(V3(0,0,0), lgeom->min); 41 vec3_set(V3(0,0,0), lgeom->max); 42 } 43 44 void save_mdl_fd(FILE *out, struct mdl_geometry *lgeom) 45 { 46 struct make_geometry *mkgeom = &lgeom->mkgeom; 47 assert(mkgeom->vertices); 48 assert(mkgeom->normals); 49 assert(mkgeom->indices); 50 51 for (int i = 0; i < N_MDL_TAGS; i++) { 52 switch ((enum mdl_tag)i) { 53 case MDL_POSITION: 54 write_tag(MDL_POSITION, out); 55 write_floats(mkgeom->vertices, mkgeom->num_verts * 3, out); 56 break; 57 58 case MDL_NORMAL: 59 write_tag(MDL_NORMAL, out); 60 write_floats(mkgeom->normals, mkgeom->num_verts * 3, out); 61 break; 62 63 case MDL_COLOR: 64 if (mkgeom->colors) { 65 write_tag(MDL_COLOR, out); 66 write_floats(mkgeom->colors, mkgeom->num_verts * 3, out); 67 } 68 break; 69 70 case MDL_INDEX: 71 write_tag(MDL_INDEX, out); 72 write_ints(mkgeom->indices, mkgeom->num_indices , out); 73 /* debug("writing out %d indices\n", mkgeom->num_indices); */ 74 break; 75 76 case MDL_JOINT_IDS: 77 if (mkgeom->joint_ids) { 78 write_tag(MDL_JOINT_IDS, out); 79 write_ints(mkgeom->joint_ids, mkgeom->num_joint_ids, out); 80 } 81 break; 82 83 case MDL_JOINT_WEIGHTS: 84 if (mkgeom->joint_weights) { 85 write_tag(MDL_JOINT_WEIGHTS, out); 86 write_floats(mkgeom->joint_weights, 87 mkgeom->num_verts * 3, out); 88 } 89 break; 90 91 case MDL_TEX_COORD: 92 if (mkgeom->tex_coords) { 93 write_tag(MDL_TEX_COORD, out); 94 assert(mkgeom->num_uv_components == 2); 95 write_floats(mkgeom->tex_coords, 96 mkgeom->num_verts * mkgeom->num_uv_components, 97 out); 98 } 99 break; 100 101 case MDL_MAX: 102 write_tag(MDL_MAX, out); 103 write_nfloats(lgeom->max, 3, out); 104 /* debug("write max: %f %f %f\n", */ 105 /* lgeom->max[0], lgeom->max[1], lgeom->max[2]); */ 106 break; 107 108 case MDL_MIN: 109 write_tag(MDL_MIN, out); 110 write_nfloats(lgeom->min, 3, out); 111 112 /* debug("write min: %f %f %f\n", */ 113 /* lgeom->min[0], lgeom->min[1], lgeom->min[2]); */ 114 break; 115 116 case N_MDL_TAGS: 117 assert(!"this shouldn't happend"); break; 118 } 119 } 120 121 } 122 123 static inline enum mdl_tag read_tag(FILE *stream) 124 { 125 enum mdl_tag tag = 0; 126 int read = fread(&tag, 1, 1, stream); 127 /* debug("read_tag %d\n", tag); */ 128 assert(read == 1 || feof(stream)); 129 assert(tag != 0 || feof(stream)); 130 return tag; 131 } 132 133 static inline int read_int(FILE *stream) 134 { 135 int val = 0; 136 int read = fread(&val, sizeof(val), 1, stream); 137 /* debug("val %d ftell %zu\n", val, ftell(stream)-4); */ 138 assert(read == 1); 139 assert(val != 0); 140 return val; 141 } 142 143 #define MAX_MDL_ARRAY 128000 // only enforced at dev time for sanity 144 145 static inline int read_nfloats(FILE *stream, int n, float *floats) 146 { 147 return fread(floats, sizeof(float), n, stream); 148 } 149 150 static int read_floats(FILE *stream, float **floats) 151 { 152 int nfloats = read_int(stream); 153 assert(nfloats != 0); 154 assert(nfloats < MAX_MDL_ARRAY); // it's a low poly game... 155 *floats = malloc(nfloats*sizeof(float)); 156 int nread = read_nfloats(stream, nfloats, *floats); 157 assert(nread == nfloats); 158 return nread; 159 } 160 161 static int read_ints(FILE *stream, u32 **ints) 162 { 163 int nints = read_int(stream); 164 assert(nints != 0); 165 assert(nints < MAX_MDL_ARRAY); // it's a low poly game... 166 *ints = malloc(nints*sizeof(u32)); 167 int nread = fread(*ints, sizeof(u32), nints, stream); 168 assert(nread == nints); 169 return nread; 170 } 171 172 void load_mdl_fd(FILE *in, struct model *model, struct mdl_geometry *lgeom) 173 { 174 struct make_geometry *mkgeom = &lgeom->mkgeom; 175 int num; 176 (void)num; 177 178 while (1) { 179 enum mdl_tag tag = read_tag(in); 180 if (feof(in)) 181 break; 182 assert(tag < N_MDL_TAGS); 183 184 switch (tag) { 185 case MDL_POSITION: 186 mkgeom->num_verts = read_floats(in, &mkgeom->vertices) / 3; 187 break; 188 189 case MDL_NORMAL: 190 num = read_floats(in, &mkgeom->normals); 191 assert(num == mkgeom->num_verts * 3); 192 break; 193 194 case MDL_COLOR: 195 num = read_floats(in, &mkgeom->colors); 196 assert(num == mkgeom->num_verts * 3); 197 break; 198 199 case MDL_INDEX: 200 mkgeom->num_indices = read_ints(in, &mkgeom->indices); 201 /* debug("reading in %d indices\n", mkgeom->num_indices); */ 202 break; 203 204 case MDL_TEX_COORD: 205 num = read_floats(in, &mkgeom->tex_coords); 206 assert(num == mkgeom->num_verts * 2); 207 break; 208 209 case MDL_JOINT_IDS: 210 mkgeom->num_joint_ids = read_ints(in, &mkgeom->joint_ids); 211 break; 212 213 case MDL_JOINT_WEIGHTS: 214 // TODO: multiple poses 215 debug("loading joint weights\n"); 216 model->nposes = 1; 217 num = read_floats(in, &mkgeom->joint_weights); 218 assert(num == mkgeom->num_verts * 3); 219 break; 220 221 case MDL_MIN: 222 read_nfloats(in, 3, lgeom->min); 223 /* debug("read min: %f %f %f\n", */ 224 /* lgeom->min[0], lgeom->min[1], lgeom->min[2]); */ 225 break; 226 227 case MDL_MAX: 228 read_nfloats(in, 3, lgeom->max); 229 /* debug("read max: %f %f %f\n", */ 230 /* lgeom->max[0], lgeom->max[1], lgeom->max[2]); */ 231 break; 232 233 case N_MDL_TAGS: assert(!"this shouldn't happend"); break; 234 } 235 } 236 } 237 238 void save_mdl(const char *filename, struct mdl_geometry *lgeom) 239 { 240 FILE *out = fopen(filename, "wb"); 241 assert(out); 242 save_mdl_fd(out, lgeom); 243 fclose(out); 244 } 245 246 void load_mdl(const char *file, struct model *model, struct mdl_geometry *lgeom) 247 { 248 FILE *in = fopen(file, "rb"); 249 assert(in); 250 load_mdl_fd(in, model, lgeom); 251 fclose(in); 252 }