4 #include "TStopwatch.h"
15 Reve::TriangleSet *ts[2048];
17 // Believe3D Model file defines
18 #define MAGICNUMBER 0xB3D0
20 // types of 3DS Chunks
21 #define CHUNKMAIN 0x4D4D
22 #define CHUNKMAINVERSION 0x0002
23 #define CHUNK3D 0x3D3D
24 #define CHUNK3DVERSION 0x3D3E
25 #define CHUNK3DOBJECT 0x4000
26 #define CHUNK3DOBJECTMESH 0x4100
27 #define CHUNK3DOBJECTMESHVERTICES 0x4110
28 #define CHUNK3DOBJECTMESHFACES 0x4120
29 #define CHUNK3DOBJECTMESHMATGROUP 0x4130
30 #define CHUNK3DOBJECTMESHMAPPING 0x4140
32 #define CHUNK3DMATERIAL 0xAFFF
33 // Sub defines of MATERIAL
34 #define MATNAME 0xA000
35 #define MATDIFFUSE 0xA020
36 #define MATSPECULAR 0xA030
37 #define MATTRANSPARENCY 0xA050
39 #define COLOR_F 0x0010
40 #define COLOR_24 0x0011
41 #define LIN_COLOR_24 0x0012
42 #define LIN_COLOR_F 0x0013
43 #define INT_PERCENTAGE 0x0030
44 #define FLOAT_PERCENTAGE 0x0031
46 //////////////////////////////////////
47 //The tMaterialInfo Struct
48 //////////////////////////////////////
53 UShort_t transparency;
57 color[0] = color[1] = color[2] = 0;
65 typedef struct _Chunk {
67 ULong_t offset, len, endoffset;
71 typedef struct _Vertex {
77 typedef struct _Face {
88 ULong_t numverts, numfaces;
95 numverts = numfaces = 0;
98 if (vlist != 0) delete [] vlist;
99 if (flist != 0) delete [] flist;
103 // chunk reading routines
104 Int_t ReadChunk(FILE*, Chunk*);
106 // data reading routines
107 Int_t ReadMainChunk(FILE*);
108 Int_t Read3DChunk(FILE*, ULong_t);
109 Int_t ReadObjectChunk(FILE*, ULong_t);
110 Int_t ReadMeshChunk(FILE*, ULong_t, char*);
111 Int_t ReadVerticesChunk(FILE*);
112 Int_t ReadFacesChunk(FILE*);
113 Int_t ReadMappingChunk(FILE*);
114 Int_t ReadASCIIZ(FILE*, char*);
115 Int_t ReadMaterialChunk(FILE *, ULong_t);
116 Int_t ReadColor(FILE *, ULong_t);
117 Int_t ReadTransparency(FILE *, ULong_t);
118 Int_t ReadObjectMaterial(FILE *);
119 Int_t ConvertModel();
123 Model model = {"","",0,0,0,0};
125 Int_t nummaterials = 0;
126 Material *material[1024];
128 //______________________________________________________________________________
129 Int_t Read3DSFile(const char *fname)
135 infile = fopen(fname, "rb");
137 printf("Error : Input File Could Not Be Opened!\n");
140 UShort_t magic = MAGICNUMBER;
141 if (ReadMainChunk(infile) != 0) {
142 printf("Error : Input File Could Not Be Read!\n");
148 //______________________________________________________________________________
149 Int_t ReadChunk(FILE *f, Chunk *c)
151 // reads a chunk from an opened file
153 if (feof(f)) return(-1);
155 c->offset = c->len = 0;
156 c->offset = (ULong_t) ftell(f);
157 fread(&c->idnum, sizeof(UShort_t), 1, f);
158 fread(&c->len, sizeof(ULong_t), 1, f);
159 c->endoffset = c->offset + c->len;
163 //______________________________________________________________________________
164 Int_t ReadMainChunk(FILE *f)
166 // handles the main body of the 3DS file
170 ReadChunk(f, &chunk);
171 if (chunk.idnum != CHUNKMAIN) return(-1);
172 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
173 if (chunk.idnum == CHUNK3D) {
174 Read3DChunk(f, chunk.endoffset);
177 //printf("Debug : Unknown Chunk [Main Chunk] [0x%x]\n", chunk.idnum);
178 fseek(f, chunk.offset + chunk.len, SEEK_SET);
184 //______________________________________________________________________________
185 Int_t Read3DChunk(FILE *f, ULong_t len)
187 // reads the 3D Edit Chunk
191 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
192 if (chunk.idnum == CHUNK3DOBJECT) {
193 ReadObjectChunk(f, chunk.endoffset);
194 fseek(f, chunk.endoffset, SEEK_SET);
196 else if (chunk.idnum == CHUNK3DMATERIAL) {
197 ReadMaterialChunk(f, chunk.endoffset);
198 fseek(f, chunk.endoffset, SEEK_SET);
201 if (chunk.endoffset < len) {
202 //printf("Debug : Unknown Chunk [3D Chunk] [0x%x]\n", chunk.idnum);
203 fseek(f, chunk.endoffset, SEEK_SET);
213 //______________________________________________________________________________
214 Int_t ReadMaterialChunk(FILE *f, ULong_t len)
216 // reads the Material sub-chunk of the 3D Edit Chunk
221 material[nummaterials] = new Material();
222 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
223 if (chunk.idnum == MATNAME) {
225 strcpy(material[nummaterials]->name, name);
226 fseek(f, chunk.endoffset, SEEK_SET);
228 else if (chunk.idnum == MATDIFFUSE) {
229 ReadColor(f, chunk.endoffset);
230 fseek(f, chunk.endoffset, SEEK_SET);
232 else if (chunk.idnum == MATTRANSPARENCY) {
233 ReadTransparency(f, chunk.endoffset);
234 fseek(f, chunk.endoffset, SEEK_SET);
237 if (chunk.endoffset < len) {
238 //printf("Debug : Unknown Chunk [Object Chunk] [0x%x]\n", chunk.idnum);
239 fseek(f, chunk.endoffset, SEEK_SET);
250 //______________________________________________________________________________
251 Int_t ReadColor(FILE *f, ULong_t len)
253 // reads the Color property of the Material Chunk
258 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
259 if (chunk.idnum == LIN_COLOR_24) {
260 fread(&material[nummaterials]->color[0], sizeof(UChar_t), 1, f);
261 fread(&material[nummaterials]->color[1], sizeof(UChar_t), 1, f);
262 fread(&material[nummaterials]->color[2], sizeof(UChar_t), 1, f);
263 fseek(f, chunk.endoffset, SEEK_SET);
265 else if (chunk.idnum == COLOR_24) {
266 fread(&material[nummaterials]->color[0], sizeof(UChar_t), 1, f);
267 fread(&material[nummaterials]->color[1], sizeof(UChar_t), 1, f);
268 fread(&material[nummaterials]->color[2], sizeof(UChar_t), 1, f);
269 fseek(f, chunk.endoffset, SEEK_SET);
271 else if (chunk.idnum == LIN_COLOR_F) {
272 fread(&fr, sizeof(Float_t), 1, f);
273 fread(&fg, sizeof(Float_t), 1, f);
274 fread(&fb, sizeof(Float_t), 1, f);
275 fseek(f, chunk.endoffset, SEEK_SET);
277 else if (chunk.idnum == COLOR_F) {
278 fread(&fr, sizeof(Float_t), 1, f);
279 fread(&fg, sizeof(Float_t), 1, f);
280 fread(&fb, sizeof(Float_t), 1, f);
281 fseek(f, chunk.endoffset, SEEK_SET);
284 if (chunk.endoffset < len) {
285 //printf("Debug : Unknown Chunk [Mesh Chunk] [0x%x]\n", chunk.idnum);
286 fseek(f, chunk.endoffset, SEEK_SET);
296 //______________________________________________________________________________
297 Int_t ReadTransparency(FILE *f, ULong_t len)
299 // reads the Transparency property of the Material Chunk
305 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
306 if (chunk.idnum == INT_PERCENTAGE) {
307 fread(&stransp, sizeof(UShort_t), 1, f);
308 material[nummaterials]->transparency = stransp;
309 fseek(f, chunk.endoffset, SEEK_SET);
311 else if (chunk.idnum == FLOAT_PERCENTAGE) {
312 fread(&ftransp, sizeof(float), 1, f);
313 fseek(f, chunk.endoffset, SEEK_SET);
316 if (chunk.endoffset < len) {
317 //printf("Debug : Unknown Chunk [Mesh Chunk] [0x%x]\n", chunk.idnum);
318 fseek(f, chunk.endoffset, SEEK_SET);
328 //______________________________________________________________________________
329 Int_t ReadObjectMaterial(FILE *f)
331 // reads the name of material associated to the current Chunk
333 ReadASCIIZ(f, model.matname);
337 //______________________________________________________________________________
338 Int_t ReadObjectChunk(FILE *f, ULong_t len)
340 // reads the Object sub-chunk of the 3D Edit Chunk
345 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
346 if (chunk.idnum == CHUNK3DOBJECTMESH) {
347 ReadMeshChunk(f, chunk.endoffset, name);
350 if (chunk.endoffset < len) {
351 //printf("Debug : Unknown Chunk [Object Chunk] [0x%x]\n", chunk.idnum);
352 fseek(f, chunk.endoffset, SEEK_SET);
362 //______________________________________________________________________________
363 Int_t ReadMeshChunk(FILE *f, ULong_t len, char *objname)
365 // reads the TriMesh sub-chunk of the Object Chunk
371 model.numverts = model.numfaces = 0;
372 sprintf(model.name, "%s", objname);
373 printf("Reading Mesh : %s\n", objname);
374 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
375 if (chunk.idnum == CHUNK3DOBJECTMESHVERTICES) {
376 ReadVerticesChunk(f);
378 else if (chunk.idnum == CHUNK3DOBJECTMESHFACES) {
381 else if (chunk.idnum == CHUNK3DOBJECTMESHMAPPING) {
384 else if (chunk.idnum == CHUNK3DOBJECTMESHMATGROUP) {
385 ReadObjectMaterial(f);
388 if (chunk.endoffset < len) {
389 //printf("Debug : Unknown Chunk [Mesh Chunk] [0x%x]\n", chunk.idnum);
390 fseek(f, chunk.endoffset, SEEK_SET);
397 if (model.numverts != 0 && model.numfaces != 0 &&
398 model.vlist != 0 && model.flist != 0) {
401 if (model.vlist != 0) delete [] model.vlist;
402 if (model.flist != 0) delete [] model.flist;
405 model.numverts = model.numfaces = 0;
406 sprintf(model.name,"");
411 //______________________________________________________________________________
412 Int_t ReadVerticesChunk(FILE *f)
414 // reads Vertex data of the TriMesh Chunk
420 fread(&numv, sizeof(UShort_t), 1, f);
421 printf("Reading %i Vertices...", numv);
422 model.vlist = new Vertex[numv];
423 if (model.vlist == 0) {
424 for (i = 0; i < numv; i++) {
425 fread(&x, sizeof(Float_t), 1, f);
426 fread(&y, sizeof(Float_t), 1, f);
427 fread(&z, sizeof(Float_t), 1, f);
429 printf("\nWarning : Insufficient Memory to Load Vertices!\n");
432 for (i = 0; i < numv; i++) {
433 fread(&model.vlist[i].x, sizeof(Float_t), 1, f);
434 fread(&model.vlist[i].y, sizeof(Float_t), 1, f);
435 fread(&model.vlist[i].z, sizeof(Float_t), 1, f);
437 model.numverts = (ULong_t) numv;
442 //______________________________________________________________________________
443 Int_t ReadFacesChunk(FILE *f)
445 // reads Face data of the TriMesh Chunk
448 UShort_t numf = 0, v1, v2, v3, attr;
450 fread(&numf, sizeof(UShort_t), 1, f);
451 printf("Reading %i Faces...", numf);
452 model.flist = new Face[numf];
453 if (model.flist == 0) {
454 for (i = 0; i < numf; i++) {
455 fread(&v1, sizeof(UShort_t), 1, f);
456 fread(&v2, sizeof(UShort_t), 1, f);
457 fread(&v3, sizeof(UShort_t), 1, f);
458 fread(&attr, sizeof(UShort_t), 1, f);
460 printf("\nWarning : Insufficient Memory to Load Faces!\n");
463 for (i = 0; i < numf; i++) {
464 fread(&v1, sizeof(UShort_t), 1, f);
465 fread(&v2, sizeof(UShort_t), 1, f);
466 fread(&v3, sizeof(UShort_t), 1, f);
467 fread(&attr, sizeof(UShort_t), 1, f);
468 model.flist[i].v1 = (ULong_t)(v1);
469 model.flist[i].v2 = (ULong_t)(v2);
470 model.flist[i].v3 = (ULong_t)(v3);
472 model.numfaces = (ULong_t)(numf);
477 //______________________________________________________________________________
478 Int_t ReadMappingChunk(FILE *f)
480 // reads Texture Mapping data of the TriMesh Chunk
482 UShort_t numuv = 0, i;
485 fread(&numuv, sizeof(UShort_t), 1, f);
486 printf("Reading %i Texture Coordinates...", numuv);
487 if (numuv != model.numverts) {
488 for (i = 0; i < numuv; i++) {
489 fread(&u, sizeof(Float_t), 1, f);
490 fread(&v, sizeof(Float_t), 1, f);
492 printf("\nWarning : Number of Vertices and Mapping Data do not match!\n");
495 for (i = 0; i < numuv; i++) {
496 fread(&model.vlist[i].u, sizeof(Float_t), 1, f);
497 fread(&model.vlist[i].v, sizeof(Float_t), 1, f);
503 //______________________________________________________________________________
504 Int_t ReadASCIIZ(FILE *f, char *name)
506 // reads a null-terminated string from the given file
512 fread(&c, sizeof(char), 1, f);
519 } while ((c != 0) && (!feof(f)));
523 //______________________________________________________________________________
526 // Convert from Model structure to Reve::TriangleSet
530 ts[nummodels] = new Reve::TriangleSet(model.numverts, model.numfaces);
531 if (ts[nummodels] == 0)
533 for (i=0; i<model.numverts; ++i) {
534 ts[nummodels]->SetVertex(i, model.vlist[i].x, model.vlist[i].y,
537 for (i=0; i<model.numfaces; ++i) {
538 ts[nummodels]->SetTriangle(i, model.flist[i].v1, model.flist[i].v2,
541 ts[nummodels]->SetName(model.name);
542 ts[nummodels]->SetTransparency(0);
543 ts[nummodels]->SetColor(0);
544 for (i = 0; i < nummaterials; i++) {
545 if (strcmp(model.matname, material[i]->name) == 0) {
546 ts[nummodels]->SetTransparency(material[i]->transparency);
547 ts[nummodels]->SetColor(Color_t(TColor::GetColor(material[i]->color[0],
548 material[i]->color[1], material[i]->color[2])));
555 //______________________________________________________________________________
556 void view3ds(const char *fname = "nasashuttle.3ds") //"eventhorizon.3ds")
561 for (i=0;i<2048;i++) ts[i] = 0;
562 for (i=0;i<1024;i++) material[i] = 0;
566 if (Read3DSFile(fname) == 0) {
567 for (i=0;i<nummodels;i++) {
569 ts[i]->GenerateTriangleNormals();
570 gReve->AddRenderElement(ts[i]);
573 gReve->Redraw3D(kTRUE);
575 for (i = 0; i < nummaterials; i++)
576 if (material[i] != 0) delete material[i];