FaceGen 3 SDKs Reference
Loading...
Searching...
No Matches
Fg3CmdEndianToggle.cpp
1//
2// Copyright (c) Singular Inversions Inc. 2004
3//
4// Authors: Andrew Beatty
5// Created: November 12, 2004
6//
7// Little endian stores the least significant byte FIRST.
8//
9// PC (Intel, AMD), Mac (Intel,ARM), PS2, Xbox (Intel) are little-endian.
10//
11// TCP/IP, Ethernet, Xbox360 (PPC), PS3 (Cell, proprietary PPC), old Mac (PPC G4, G5)
12// and Java binary format are big-endian.
13//
14// Integers and floats are converted the same way, so if your target
15// machine doesn't use IEEE fp format, this won't work.
16//
17// This source code is written for a little-endian machine and assumes
18// sizeof(int) = 4 (as that's the size in data files).
19//
20// IMPORTANT: Compile with optimizations OFF and floating point in STRICT mode
21// or you may (esp. with VS2005) get incorrect results.
22//
23
24#include "stdafx.h"
25
26#include "FgCommand.hpp"
27#include "FgFileSystem.hpp"
28
29#include "FgScopeGuard.hpp"
30
31using namespace std;
32
33namespace Fg {
34
35template<class T>
36static
37void
38endianToggle(T &x)
39{
40 T tmp1 = x,tmp2;
41 char *cx = (char *)&tmp2,
42 *ct = (char *)&tmp1;
43 for (unsigned int ii=0; ii<sizeof(T); ii++)
44 cx[ii] = ct[sizeof(T)-ii-1];
45 // We cannot use the pointer into 'x' directly because the VS2005 optimizer won't
46 // make a dependency out of it and results are very unexpected.
47 x = tmp2;
48}
49
50template<class T>
51static
52void
53convert(
54 FILE *inPtr,
55 FILE *outPtr,
56 bool l2b,
57 T &val)
58{
59 T rawVal;
60 if (fread((void *)&rawVal,sizeof(T),1,inPtr) != 1)
61 fgThrow("Unexpected end of file during read");
62 if (l2b)
63 val = rawVal;
64 endianToggle(rawVal);
65 if (!l2b) // Data is BE but this machine is LE (or vice versa I suppose).
66 val = rawVal;
67 if (fwrite((void *)&rawVal,sizeof(T),1,outPtr) != 1)
68 fgThrow("Unexpected end of file during write");
69}
70
71static
72void
73copyBuff(
74 FILE *inPtr,
75 FILE *outPtr,
76 size_t size,
77 char *buff)
78{
79 if (fread((void *)buff,1,size,inPtr) != size)
80 fgThrow("Unexpected end of file during read");
81 if (fwrite((void *)buff,1,size,outPtr) != size)
82 fgThrow("Unexpected end of file during write");
83}
84
85static
86void
87convertTri(
88 FILE *inPtr,
89 FILE *outPtr,
90 bool l2b)
91{
92 char cbuff[256];
93 copyBuff(inPtr,outPtr,8,cbuff);
94 cbuff[8] = 0;
95 if (string(cbuff) != "FRTRI003")
96 fgThrow("Invalid header for input TRI file");
97
98 int verts,tris,quads,vertPts,surfPts,texCoords,extension,diffMorphs,statMorphs,statVerts,itmp;
99 uint utmp;
100 float ftmp;
101 short stmp;
102
103 convert(inPtr,outPtr,l2b,verts);
104 convert(inPtr,outPtr,l2b,tris);
105 convert(inPtr,outPtr,l2b,quads);
106 convert(inPtr,outPtr,l2b,vertPts);
107 convert(inPtr,outPtr,l2b,surfPts);
108 convert(inPtr,outPtr,l2b,texCoords);
109 convert(inPtr,outPtr,l2b,extension);
110 convert(inPtr,outPtr,l2b,diffMorphs);
111 convert(inPtr,outPtr,l2b,statMorphs);
112 convert(inPtr,outPtr,l2b,statVerts);
113
114 copyBuff(inPtr,outPtr,16,cbuff);
115
116 for (int ii=0; ii<(verts+statVerts); ii++)
117 for (int jj=0; jj<3; jj++)
118 convert(inPtr,outPtr,l2b,ftmp);
119
120 for (int ii=0; ii<tris; ii++)
121 for (int jj=0; jj<3; jj++)
122 convert(inPtr,outPtr,l2b,itmp);
123
124 for (int ii=0; ii<quads; ii++)
125 for (int jj=0; jj<4; jj++)
126 convert(inPtr,outPtr,l2b,itmp);
127
128 for (int ii=0; ii<vertPts; ii++)
129 {
130 convert(inPtr,outPtr,l2b,itmp);
131 convert(inPtr,outPtr,l2b,itmp);
132 copyBuff(inPtr,outPtr,itmp,cbuff);
133 }
134
135 for (int ii=0; ii<surfPts; ii++)
136 {
137 convert(inPtr,outPtr,l2b,itmp);
138 convert(inPtr,outPtr,l2b,ftmp);
139 convert(inPtr,outPtr,l2b,ftmp);
140 convert(inPtr,outPtr,l2b,ftmp);
141 convert(inPtr,outPtr,l2b,itmp);
142 copyBuff(inPtr,outPtr,itmp,cbuff);
143 }
144
145 if ((texCoords == 0) && (extension & 0x01))
146 {
147 for (int ii=0; ii<verts; ii++)
148 for (int jj=0; jj<2; jj++)
149 convert(inPtr,outPtr,l2b,ftmp);
150 }
151 else
152 {
153 for (int ii=0; ii<texCoords; ii++)
154 for (int jj=0; jj<2; jj++)
155 convert(inPtr,outPtr,l2b,ftmp);
156 for (int ii=0; ii<tris; ii++)
157 for (int jj=0; jj<3; jj++)
158 convert(inPtr,outPtr,l2b,itmp);
159 for (int ii=0; ii<quads; ii++)
160 for (int jj=0; jj<4; jj++)
161 convert(inPtr,outPtr,l2b,itmp);
162 }
163
164 for (int ii=0; ii<diffMorphs; ii++)
165 {
166 convert(inPtr,outPtr,l2b,itmp);
167 copyBuff(inPtr,outPtr,itmp,cbuff);
168 convert(inPtr,outPtr,l2b,ftmp);
169 for (int jj=0; jj<verts; jj++)
170 for (int kk=0; kk<3; kk++)
171 convert(inPtr,outPtr,l2b,stmp);
172 }
173
174 uint numVertsStat;
175 for (int ii=0; ii<statMorphs; ii++)
176 {
177 convert(inPtr,outPtr,l2b,itmp);
178 copyBuff(inPtr,outPtr,itmp,cbuff);
179 convert(inPtr,outPtr,l2b,numVertsStat);
180 for (uint jj=0; jj<numVertsStat; jj++)
181 convert(inPtr,outPtr,l2b,utmp);
182 }
183}
184
185static
186void
187convertEgm(
188 FILE *inPtr,
189 FILE *outPtr,
190 bool l2b)
191{
192 char cbuff[256];
193 copyBuff(inPtr,outPtr,8,cbuff);
194 cbuff[8] = 0;
195 if (string(cbuff) != "FREGM002")
196 fgThrow("Invalid header for input EGM file");
197
198 int verts,modesSymm,modesAsym,itmp;
199 float ftmp;
200 short stmp;
201
202 convert(inPtr,outPtr,l2b,verts);
203 convert(inPtr,outPtr,l2b,modesSymm);
204 convert(inPtr,outPtr,l2b,modesAsym);
205 convert(inPtr,outPtr,l2b,itmp);
206
207 copyBuff(inPtr,outPtr,40,cbuff);
208
209 for (int ii=0; ii<modesSymm; ii++)
210 {
211 convert(inPtr,outPtr,l2b,ftmp);
212 for (int jj=0; jj<verts; jj++)
213 for (int kk=0; kk<3; kk++)
214 convert(inPtr,outPtr,l2b,stmp);
215 }
216
217 for (int ii=0; ii<modesAsym; ii++)
218 {
219 convert(inPtr,outPtr,l2b,ftmp);
220 for (int jj=0; jj<verts; jj++)
221 for (int kk=0; kk<3; kk++)
222 convert(inPtr,outPtr,l2b,stmp);
223 }
224}
225
226static
227void
228convertEgt(
229 FILE *inPtr,
230 FILE *outPtr,
231 bool l2b)
232{
233 char cbuff[2048];
234 copyBuff(inPtr,outPtr,8,cbuff);
235 cbuff[8] = 0;
236 if (string(cbuff) != "FREGT003")
237 fgThrow("Invalid header for input EGT file");
238
239 int rows,cols,modesSymm,modesAsym,itmp;
240 float ftmp;
241
242 convert(inPtr,outPtr,l2b,rows);
243 convert(inPtr,outPtr,l2b,cols);
244 convert(inPtr,outPtr,l2b,modesSymm);
245 convert(inPtr,outPtr,l2b,modesAsym);
246 convert(inPtr,outPtr,l2b,itmp);
247
248 copyBuff(inPtr,outPtr,36,cbuff);
249
250 for (int ii=0; ii<modesSymm; ii++)
251 {
252 convert(inPtr,outPtr,l2b,ftmp);
253 for (int jj=0; jj<3; jj++)
254 for (int kk=0; kk<rows; kk++)
255 copyBuff(inPtr,outPtr,cols,cbuff);
256 }
257
258 for (int ii=0; ii<modesAsym; ii++)
259 {
260 convert(inPtr,outPtr,l2b,ftmp);
261 for (int jj=0; jj<3; jj++)
262 for (int kk=0; kk<rows; kk++)
263 copyBuff(inPtr,outPtr,cols,cbuff);
264 }
265}
266
267static
268void
269convertFim(
270 FILE *inPtr,
271 FILE *outPtr,
272 bool l2b)
273{
274 char cbuff[2048];
275 copyBuff(inPtr,outPtr,8,cbuff);
276 cbuff[8] = 0;
277 if (string(cbuff) != "FIMFF001")
278 fgThrow("Invalid header for input FIM file");
279
280 int width,height;
281 float ftmp;
282
283 convert(inPtr,outPtr,l2b,width);
284 convert(inPtr,outPtr,l2b,height);
285
286 copyBuff(inPtr,outPtr,48,cbuff);
287
288 for (int ii=0; ii<height; ii++)
289 for (int jj=0; jj<width; jj++)
290 {
291 convert(inPtr,outPtr,l2b,ftmp);
292 convert(inPtr,outPtr,l2b,ftmp);
293 };
294}
295
296static
297void
298convertCtl(
299 FILE *inPtr,
300 FILE *outPtr,
301 bool l2b)
302{
303 char cbuff[256];
304 copyBuff(inPtr,outPtr,8,cbuff);
305 cbuff[8] = 0;
306 if (string(cbuff) != "FRCTL001")
307 fgThrow("Invalid header for input CTL file");
308
309 uint verGeo,verTex,basisGS,basisGA,basisTS,basisTA,linCtls,utmp;
310 float ftmp;
311
312 convert(inPtr,outPtr,l2b,verGeo);
313 convert(inPtr,outPtr,l2b,verTex);
314 convert(inPtr,outPtr,l2b,basisGS);
315 convert(inPtr,outPtr,l2b,basisGA);
316 convert(inPtr,outPtr,l2b,basisTS);
317 convert(inPtr,outPtr,l2b,basisTA);
318
319 convert(inPtr,outPtr,l2b,linCtls);
320 for (uint ii=0; ii<linCtls; ii++)
321 {
322 for (uint jj=0; jj<basisGS; jj++)
323 convert(inPtr,outPtr,l2b,ftmp);
324 convert(inPtr,outPtr,l2b,utmp);
325 copyBuff(inPtr,outPtr,utmp,cbuff);
326 }
327
328 convert(inPtr,outPtr,l2b,linCtls);
329 for (uint ii=0; ii<linCtls; ii++)
330 {
331 for (uint jj=0; jj<basisGA; jj++)
332 convert(inPtr,outPtr,l2b,ftmp);
333 convert(inPtr,outPtr,l2b,utmp);
334 copyBuff(inPtr,outPtr,utmp,cbuff);
335 }
336
337 convert(inPtr,outPtr,l2b,linCtls);
338 for (uint ii=0; ii<linCtls; ii++)
339 {
340 for (uint jj=0; jj<basisTS; jj++)
341 convert(inPtr,outPtr,l2b,ftmp);
342 convert(inPtr,outPtr,l2b,utmp);
343 copyBuff(inPtr,outPtr,utmp,cbuff);
344 }
345
346 convert(inPtr,outPtr,l2b,linCtls);
347 for (uint ii=0; ii<linCtls; ii++)
348 {
349 for (uint jj=0; jj<basisTA; jj++)
350 convert(inPtr,outPtr,l2b,ftmp);
351 convert(inPtr,outPtr,l2b,utmp);
352 copyBuff(inPtr,outPtr,utmp,cbuff);
353 }
354
355 for (uint ii=0; ii<5; ii++)
356 {
357 for (uint jj=0; jj<2; jj++)
358 {
359 for (uint kk=0; kk<basisGS; kk++)
360 convert(inPtr,outPtr,l2b,ftmp);
361 convert(inPtr,outPtr,l2b,ftmp);
362 for (uint kk=0; kk<basisTS; kk++)
363 convert(inPtr,outPtr,l2b,ftmp);
364 convert(inPtr,outPtr,l2b,ftmp);
365 }
366 }
367
368 for (uint ii=0; ii<20; ii++)
369 {
370 for (uint jj=0; jj<basisGS; jj++)
371 convert(inPtr,outPtr,l2b,ftmp);
372 for (uint jj=0; jj<basisTS; jj++)
373 convert(inPtr,outPtr,l2b,ftmp);
374 convert(inPtr,outPtr,l2b,ftmp);
375 }
376
377 uint basis = basisGS + basisTS;
378 for (uint ii=0; ii<5; ii++)
379 {
380 for (uint jj=0; jj<basis; jj++)
381 convert(inPtr,outPtr,l2b,ftmp);
382 for (uint jj=0; jj<basis; jj++)
383 for (uint kk=0; kk<basis; kk++)
384 convert(inPtr,outPtr,l2b,ftmp);
385
386 for (uint jj=0; jj<basisGS; jj++)
387 for (uint kk=0; kk<basisGS; kk++)
388 convert(inPtr,outPtr,l2b,ftmp);
389
390 for (uint jj=0; jj<basisTS; jj++)
391 for (uint kk=0; kk<basisTS; kk++)
392 convert(inPtr,outPtr,l2b,ftmp);
393 }
394}
395
396static
397void
398convertFg(
399 FILE *inPtr,
400 FILE *outPtr,
401 bool l2b)
402{
403 char cbuff[256];
404 copyBuff(inPtr,outPtr,8,cbuff);
405 cbuff[8] = 0;
406 if (string(cbuff) != "FRFG0001")
407 fgThrow("Invalid header for input FG file");
408
409 uint verGeo,verTex,basisGS,basisGA,basisTS,basisTA,detail,utmp;
410 short stmp;
411
412 convert(inPtr,outPtr,l2b,verGeo);
413 convert(inPtr,outPtr,l2b,verTex);
414 convert(inPtr,outPtr,l2b,basisGS);
415 convert(inPtr,outPtr,l2b,basisGA);
416 convert(inPtr,outPtr,l2b,basisTS);
417 convert(inPtr,outPtr,l2b,basisTA);
418 convert(inPtr,outPtr,l2b,utmp);
419 convert(inPtr,outPtr,l2b,detail);
420
421 for (uint ii=0; ii<basisGS; ii++)
422 convert(inPtr,outPtr,l2b,stmp);
423 for (uint ii=0; ii<basisGA; ii++)
424 convert(inPtr,outPtr,l2b,stmp);
425 for (uint ii=0; ii<basisTS; ii++)
426 convert(inPtr,outPtr,l2b,stmp);
427 for (uint ii=0; ii<basisTA; ii++)
428 convert(inPtr,outPtr,l2b,stmp);
429
430 // The detail texture section is optional. We need a fake read to trigger feof:
431 int peek = fgetc(inPtr);
432 if (feof(inPtr) == 0)
433 {
434 ungetc(peek,inPtr);
435 convert(inPtr,outPtr,l2b,utmp);
436 // JPEG encoding is always BE:
437 vector<char> vbuff(utmp);
438 copyBuff(inPtr,outPtr,utmp,&vbuff[0]);
439 }
440}
441
446void
447cmd3EndianToggle(CLArgs const & args)
448{
449 Syntax
450 syntax(args,
451 "<input>.<ext> <output>.<ext> (l2b | b2l)\n"
452 " <ext> = (tri | egm | egt | fim | ctl | fg)\n"
453 " Assumes IEC 559 / IEEE 754 floating point values.");
454
455 if (args.size() != 4)
456 syntax.errorNumArgs();
457
458 string input(args[1]),
459 output(args[2]),
460 direction(args[3]),
461 type = pathToExt(input);
462 if (!checkExt(output,type))
463 syntax.error("The output file must have the same extension as the input file");
464 bool l2b = false;
465 if (direction == "l2b")
466 l2b = true;
467 else if (direction == "b2l")
468 l2b = false;
469 else
470 syntax.error("Invalid conversion direction");
471
472 FILE *inPtr = openFile(input,false);
473 ScopeGuard inSG {[inPtr](){fclose(inPtr); }};
474 FILE *outPtr = openFile(output,true);
475 ScopeGuard outSG {[outPtr](){fclose(outPtr); }};
476 if (type == "tri")
477 convertTri(inPtr,outPtr,l2b);
478 else if (type == "egm")
479 convertEgm(inPtr,outPtr,l2b);
480 else if (type == "egt")
481 convertEgt(inPtr,outPtr,l2b);
482 else if (type == "fim")
483 convertFim(inPtr,outPtr,l2b);
484 else if (type == "ctl")
485 convertCtl(inPtr,outPtr,l2b);
486 else if (type == "fg")
487 convertFg(inPtr,outPtr,l2b);
488 else {
489 syntax.error(string("Unknown file type extension: ") + type);
490 }
491}
492Cmd
493getCmd3EndianToggle()
494{
495 return Cmd{cmd3EndianToggle,"endian","Change endianness of FaceGen 3 file formats"};
496}
497
498}
void cmd3EndianToggle(CLArgs const &args)