md2tool.cpp
1 2 #include "compat.h" 3 #include "build.h" 4 #include "glad/glad.h" 5 #include "mdsprite.h" 6 7 8 static md2head_t head; 9 10 11 static void quit(int32_t status) 12 { 13 exit(status); 14 } 15 16 static md2model_t *md2load(int *fd, const char *filename, int32_t ronly) 17 { 18 md2model_t *m; 19 int fil; 20 21 fil = Bopen(filename, ronly?BO_RDONLY:BO_RDWR); 22 if (fil<0) 23 { 24 Bfprintf(stderr, "Couldn't open `%s': %s\n", filename, strerror(errno)); 25 quit(2); 26 } 27 28 m = (md2model_t *)Bcalloc(1,sizeof(md2model_t)); if (!m) quit(1); 29 m->mdnum = 2; m->scale = .01f; 30 31 Bread(fil,(char *)&head,sizeof(md2head_t)); 32 33 head.id = B_LITTLE32(head.id); head.vers = B_LITTLE32(head.vers); 34 head.skinxsiz = B_LITTLE32(head.skinxsiz); head.skinysiz = B_LITTLE32(head.skinysiz); 35 head.framebytes = B_LITTLE32(head.framebytes); head.numskins = B_LITTLE32(head.numskins); 36 head.numverts = B_LITTLE32(head.numverts); head.numuv = B_LITTLE32(head.numuv); 37 head.numtris = B_LITTLE32(head.numtris); head.numglcmds = B_LITTLE32(head.numglcmds); 38 head.numframes = B_LITTLE32(head.numframes); head.ofsskins = B_LITTLE32(head.ofsskins); 39 head.ofsuv = B_LITTLE32(head.ofsuv); head.ofstris = B_LITTLE32(head.ofstris); 40 head.ofsframes = B_LITTLE32(head.ofsframes); head.ofsglcmds = B_LITTLE32(head.ofsglcmds); 41 head.ofseof = B_LITTLE32(head.ofseof); 42 43 if ((head.id != 0x32504449) || (head.vers != 8)) 44 { 45 Bfprintf(stderr, "File `%s' is not an md2 file.\n", filename); 46 quit(3); 47 } //"IDP2" 48 49 m->numskins = head.numskins; 50 m->numframes = head.numframes; 51 m->numverts = head.numverts; 52 m->numglcmds = head.numglcmds; 53 m->framebytes = head.framebytes; 54 55 m->frames = (char *)Bmalloc(m->numframes*m->framebytes); if (!m->frames) quit(1); 56 m->tris = (md2tri_t *)Bmalloc(head.numtris*sizeof(md2tri_t)); if (!m->tris) quit(1); 57 m->uv = (md2uv_t *)Bmalloc(head.numuv*sizeof(md2uv_t)); if (!m->uv) quit(1); 58 59 Blseek(fil,head.ofsframes,SEEK_SET); 60 if (Bread(fil,(char *)m->frames,m->numframes*m->framebytes) != m->numframes*m->framebytes) 61 quit(1); 62 63 Blseek(fil,head.ofstris,SEEK_SET); 64 if (Bread(fil,(char *)m->tris,head.numtris*sizeof(md2tri_t)) != (int32_t)(head.numtris*sizeof(md2tri_t))) 65 quit(1); 66 67 Blseek(fil,head.ofsuv,SEEK_SET); 68 if (Bread(fil,(char *)m->uv,head.numuv*sizeof(md2uv_t)) != (int32_t)(head.numuv*sizeof(md2uv_t))) 69 quit(1); 70 71 #if B_BIG_ENDIAN != 0 72 { 73 char *f = (char *)m->frames; 74 int32_t *l,i,j; 75 md2frame_t *fr; 76 77 for (i = m->numframes-1; i>=0; i--) 78 { 79 fr = (md2frame_t *)f; 80 l = (int32_t *)&fr->mul; 81 for (j=5; j>=0; j--) l[j] = B_LITTLE32(l[j]); 82 f += m->framebytes; 83 } 84 85 for (i = head.numtris-1; i>=0; i--) 86 { 87 m->tris[i].v[0] = B_LITTLE16(m->tris[i].v[0]); 88 m->tris[i].v[1] = B_LITTLE16(m->tris[i].v[1]); 89 m->tris[i].v[2] = B_LITTLE16(m->tris[i].v[2]); 90 m->tris[i].u[0] = B_LITTLE16(m->tris[i].u[0]); 91 m->tris[i].u[1] = B_LITTLE16(m->tris[i].u[1]); 92 m->tris[i].u[2] = B_LITTLE16(m->tris[i].u[2]); 93 } 94 for (i = head.numuv-1; i>=0; i--) 95 { 96 m->uv[i].u = B_LITTLE16(m->uv[i].u); 97 m->uv[i].v = B_LITTLE16(m->uv[i].v); 98 } 99 } 100 #endif 101 102 *fd = fil; 103 return(m); 104 } 105 106 107 static void usage_and_quit() 108 { 109 Bfprintf(stderr, 110 "Usage:\n" 111 " md2tool <modelfile>.md2: display info about model\n" 112 " md2tool -minmax <minx>,<miny>,<minz>:<maxx>,<maxy>,<maxz> <modelfile>.md2:\n" 113 " modify `scale' and `translate' fields of MD2 (in-place) to produce given bounds\n" 114 ); 115 quit(1); 116 } 117 118 int main(int argc, char **argv) 119 { 120 char *fn=NULL, *cp; 121 int32_t fd=-1, i, j; 122 123 int32_t doinfo=1; 124 125 // md2 mul[x,y,z], add[x,y,z] 126 float mx,my,mz, ax,ay,az; 127 128 // desired model bounds 129 float dminx=0,dminy=0,dminz=0, dmaxx=1,dmaxy=1,dmaxz=1; 130 131 // md2 uint8-coordinate bounds 132 uint8_t maxv[3]={0,0,0}; 133 uint8_t minv[3]={255,255,255}; 134 135 md2frame_t *fr; 136 uint8_t *vp; 137 138 md2model_t *m; 139 140 if (argc<=1) 141 usage_and_quit(); 142 143 for (i=1; i<argc; i++) 144 { 145 cp = argv[i]; 146 147 if (cp[0]=='-') 148 { 149 if (!strcmp(cp, "-minmax")) 150 { 151 doinfo=0; 152 if (i+1 >= argc) 153 usage_and_quit(); 154 if (Bsscanf(argv[i+1], "%f,%f,%f:%f,%f,%f", &dminx,&dminy,&dminz, &dmaxx,&dmaxy,&dmaxz)!=6) 155 usage_and_quit(); 156 i++; 157 } 158 else 159 { 160 Bfprintf(stderr, "unrecognized option `%s'\n", cp); 161 quit(2); 162 } 163 } 164 else 165 fn = cp; 166 } 167 168 if (!fn) 169 usage_and_quit(); 170 171 m = md2load(&fd, fn, doinfo); 172 173 fr = (md2frame_t *)m->frames; 174 mx=fr->mul.x; my=fr->mul.y; mz=fr->mul.z; 175 ax=fr->add.x; ay=fr->add.y; az=fr->add.z; 176 177 for (i=0, vp=fr->verts->v; i<m->numverts; i++, vp+=sizeof(md2vert_t)) 178 { 179 for (j=0; j<3; j++) 180 { 181 maxv[j] = max(maxv[j], vp[j]); 182 minv[j] = min(minv[j], vp[j]); 183 } 184 } 185 186 if (doinfo) 187 { 188 Bprintf("------ %s ------\n", fn); 189 Bprintf("numframes: %d\n", m->numframes); 190 Bprintf("numverts: %d\n", m->numverts); 191 Bprintf("numtris: %d\n", head.numtris); 192 Bprintf("\n"); 193 Bprintf("ofsframes: %x\n", head.ofsframes); 194 Bprintf("framebytes: %d\n", head.framebytes); 195 // Bprintf("framebytes: %d, calculated=%d\n", head.framebytes, sizeof(md2frame_t)+(m->numverts-1)*sizeof(md2vert_t)); 196 Bprintf("\n"); 197 198 Bprintf("mul=%f %f %f\n", mx, my, mz); 199 Bprintf("add=%f %f %f\n", ax, ay, az); 200 201 Bprintf("min xyz (s+t) = %f %f %f\n", minv[0]*mx+ax, minv[1]*my+ay, minv[2]*mz+az); 202 Bprintf("max xyz (s+t) = %f %f %f\n", maxv[0]*mx+ax, maxv[1]*my+ay, maxv[2]*mz+az); 203 204 Bprintf("\n"); 205 } 206 else 207 { 208 if (maxv[0]-minv[0]>0) mx = (dmaxx-dminx)/(maxv[0]-minv[0]); else mx=0; 209 if (maxv[1]-minv[1]>0) my = (dmaxy-dminy)/(maxv[1]-minv[1]); else my=0; 210 if (maxv[2]-minv[2]>0) mz = (dmaxz-dminz)/(maxv[2]-minv[2]); else mz=0; 211 212 if (mx==0||my==0||mz==0) 213 { 214 Bfprintf(stderr, "max[x,y,z]-min[x,y,z] must each be grater 0!\n"); 215 quit(2); 216 } 217 218 ax = dmaxx-maxv[0]*mx; 219 ay = dmaxy-maxv[1]*my; 220 az = dmaxz-maxv[2]*mz; 221 222 #define ISNAN(x) ((x)!=(x)) 223 #define ISINF(x) ((x!=0)&&(x/2==x)) 224 225 if (ISNAN(mx)||ISNAN(my)||ISNAN(mz)||ISNAN(ax)||ISNAN(ay)||ISNAN(az)|| 226 ISINF(mx)||ISINF(my)||ISINF(mz)||ISINF(ax)||ISINF(ay)||ISINF(az)) 227 { 228 Bfprintf(stderr, "Calculation resulted in NaN or Inf.\n"); 229 quit(2); 230 } 231 232 Blseek(fd,head.ofsframes,SEEK_SET); 233 if (Bwrite(fd, &mx, sizeof(mx))!=sizeof(mx)) { perror("write"); quit(3); } 234 if (Bwrite(fd, &my, sizeof(my))!=sizeof(my)) { perror("write"); quit(3); } 235 if (Bwrite(fd, &mz, sizeof(mz))!=sizeof(mz)) { perror("write"); quit(3); } 236 if (Bwrite(fd, &ax, sizeof(ax))!=sizeof(ax)) { perror("write"); quit(3); } 237 if (Bwrite(fd, &ay, sizeof(ay))!=sizeof(ay)) { perror("write"); quit(3); } 238 if (Bwrite(fd, &az, sizeof(az))!=sizeof(az)) { perror("write"); quit(3); } 239 Bclose(fd); 240 241 Bprintf("wrote scale and translate of `%s'.\n", fn); 242 } 243 244 return 0; 245 }