First big commit of the mchview program and its accompanying library,
[u/mrichter/AliRoot.git] / EVE / test-macros / view3ds.C
1 #include "TCanvas.h"
2 #include "TStyle.h"
3 #include "TFile.h"
4 #include "TStopwatch.h"
5 #include "TError.h"
6
7 #include <math.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11
12 namespace Reve {
13    class TriangleSet;
14 }
15 Reve::TriangleSet *ts[2048];
16
17 // Believe3D Model file defines
18 #define MAGICNUMBER 0xB3D0
19
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
31
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
38
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
45
46 //////////////////////////////////////
47 //The tMaterialInfo Struct
48 //////////////////////////////////////
49 class Material {
50 public:
51    char     name[256];
52    UChar_t  color[3];
53    UShort_t transparency;
54
55    Material() {
56       sprintf(name, "");
57       color[0] = color[1] = color[2] = 0;
58       transparency = 0;
59    }
60    ~Material() { }
61 };
62
63
64 // Chunk structure
65 typedef struct _Chunk {
66    UShort_t idnum;
67    ULong_t  offset, len, endoffset;
68 } Chunk;
69
70 // vertex structure
71 typedef struct _Vertex {
72    Float_t x, y, z;
73    Float_t u, v;
74 } Vertex;
75
76 // face structure
77 typedef struct _Face {
78    ULong_t v1, v2, v3;
79 } Face;
80
81 // model structure
82 class Model {
83 public:
84    char     name[256];
85    char     matname[256];
86    Vertex   *vlist;
87    Face     *flist;
88    ULong_t  numverts, numfaces;
89    
90    Model() {  
91       sprintf(name,"");
92       sprintf(matname,"");
93       vlist = 0;
94       flist = 0;
95       numverts = numfaces = 0;
96    }
97    ~Model() { 
98       if (vlist != 0) delete [] vlist;
99       if (flist != 0) delete [] flist;
100    }
101 };
102
103 // chunk reading routines
104 Int_t ReadChunk(FILE*, Chunk*);
105
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();
120
121 // global variables
122 Int_t nummodels = 0;
123 Model model = {"","",0,0,0,0};
124
125 Int_t nummaterials = 0;
126 Material *material[1024];
127
128 //______________________________________________________________________________
129 Int_t Read3DSFile(const char *fname)
130 {
131    // main function
132
133    FILE *infile;
134
135    infile = fopen(fname, "rb");
136    if (infile == 0) {
137       printf("Error : Input File Could Not Be Opened!\n");
138       return -1;
139    }
140    UShort_t magic = MAGICNUMBER;
141    if (ReadMainChunk(infile) != 0) {
142       printf("Error : Input File Could Not Be Read!\n");
143    }
144    fclose(infile);
145    return 0;
146 }
147
148 //______________________________________________________________________________
149 Int_t ReadChunk(FILE *f, Chunk *c)
150 {
151    // reads a chunk from an opened file
152
153    if (feof(f)) return(-1);
154    c->idnum = 0;
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;
160    return(0);
161 }
162
163 //______________________________________________________________________________
164 Int_t ReadMainChunk(FILE *f)
165 {
166    // handles the main body of the 3DS file
167
168    Chunk chunk;
169
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);
175       }
176       else {
177          //printf("Debug : Unknown Chunk [Main Chunk] [0x%x]\n", chunk.idnum);
178          fseek(f, chunk.offset + chunk.len, SEEK_SET);
179       }
180    }
181    return 0;
182 }
183
184 //______________________________________________________________________________
185 Int_t Read3DChunk(FILE *f, ULong_t len)
186 {
187    // reads the 3D Edit Chunk
188
189    Chunk chunk;
190
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);
195       }
196       else if (chunk.idnum == CHUNK3DMATERIAL) {
197          ReadMaterialChunk(f, chunk.endoffset);
198          fseek(f, chunk.endoffset, SEEK_SET);
199       }
200       else {
201          if (chunk.endoffset < len) {
202             //printf("Debug : Unknown Chunk [3D Chunk] [0x%x]\n", chunk.idnum);
203             fseek(f, chunk.endoffset, SEEK_SET);
204          }
205          else {
206             break;
207          }
208       }
209    }
210    return 0;
211 }
212
213 //______________________________________________________________________________
214 Int_t ReadMaterialChunk(FILE *f, ULong_t len)
215 {
216    // reads the Material sub-chunk of the 3D Edit Chunk
217
218    Chunk chunk;
219    char name[256];
220    char rgb[3];
221    material[nummaterials] = new Material();
222    while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
223       if (chunk.idnum == MATNAME) {
224          ReadASCIIZ(f, name);
225          strcpy(material[nummaterials]->name, name);
226          fseek(f, chunk.endoffset, SEEK_SET);
227       }
228       else if (chunk.idnum == MATDIFFUSE) {
229          ReadColor(f, chunk.endoffset);
230          fseek(f, chunk.endoffset, SEEK_SET);
231       }
232       else if (chunk.idnum == MATTRANSPARENCY) {
233          ReadTransparency(f, chunk.endoffset);
234          fseek(f, chunk.endoffset, SEEK_SET);
235       }
236       else {
237          if (chunk.endoffset < len) {
238             //printf("Debug : Unknown Chunk [Object Chunk] [0x%x]\n", chunk.idnum);
239             fseek(f, chunk.endoffset, SEEK_SET);
240          }
241          else {
242             break;
243          }
244       }
245    }
246    nummaterials++;
247    return 0;
248 }
249
250 //______________________________________________________________________________
251 Int_t ReadColor(FILE *f, ULong_t len)
252 {
253    // reads the Color property of the Material Chunk
254    
255    Chunk chunk;
256    float fr, fg, fb;
257    int   irgb[3];
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);
264       }
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);
270       }
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);
276       }
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);
282       }
283       else {
284          if (chunk.endoffset < len) {
285             //printf("Debug : Unknown Chunk [Mesh Chunk] [0x%x]\n", chunk.idnum);
286             fseek(f, chunk.endoffset, SEEK_SET);
287          }
288          else {
289             break;
290          }
291       }
292    }
293    return 0;
294 }
295
296 //______________________________________________________________________________
297 Int_t ReadTransparency(FILE *f, ULong_t len)
298 {
299    // reads the Transparency property of the Material Chunk
300    
301    Chunk    chunk;
302    char     byte[2];
303    float    ftransp;
304    UShort_t stransp;
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);
310       }
311       else if (chunk.idnum == FLOAT_PERCENTAGE) {
312          fread(&ftransp, sizeof(float), 1, f);
313          fseek(f, chunk.endoffset, SEEK_SET);
314       }
315       else {
316          if (chunk.endoffset < len) {
317             //printf("Debug : Unknown Chunk [Mesh Chunk] [0x%x]\n", chunk.idnum);
318             fseek(f, chunk.endoffset, SEEK_SET);
319          }
320          else {
321             break;
322          }
323       }
324    }
325    return 0;
326 }
327
328 //______________________________________________________________________________
329 Int_t ReadObjectMaterial(FILE *f)
330 {
331    // reads the name of material associated to the current Chunk
332
333    ReadASCIIZ(f, model.matname);
334    return 0;
335 }
336
337 //______________________________________________________________________________
338 Int_t ReadObjectChunk(FILE *f, ULong_t len)
339 {
340    // reads the Object sub-chunk of the 3D Edit Chunk
341
342    Chunk chunk;
343    char name[256];
344    ReadASCIIZ(f, name);
345    while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
346       if (chunk.idnum == CHUNK3DOBJECTMESH) {
347          ReadMeshChunk(f, chunk.endoffset, name);
348       }
349       else {
350          if (chunk.endoffset < len) {
351             //printf("Debug : Unknown Chunk [Object Chunk] [0x%x]\n", chunk.idnum);
352             fseek(f, chunk.endoffset, SEEK_SET);
353          }
354          else {
355             break;
356          }
357       }
358    }
359    return 0;
360 }
361
362 //______________________________________________________________________________
363 Int_t ReadMeshChunk(FILE *f, ULong_t len, char *objname)
364 {
365    // reads the TriMesh sub-chunk of the Object Chunk
366
367    Int_t i;
368    Chunk chunk;
369    model.vlist = 0;
370    model.flist = 0;
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);
377       }
378       else if (chunk.idnum == CHUNK3DOBJECTMESHFACES) {
379          ReadFacesChunk(f);
380       }
381       else if (chunk.idnum == CHUNK3DOBJECTMESHMAPPING) {
382          ReadMappingChunk(f);
383       }
384       else if (chunk.idnum == CHUNK3DOBJECTMESHMATGROUP) {
385          ReadObjectMaterial(f);
386       }
387       else {
388          if (chunk.endoffset < len) {
389             //printf("Debug : Unknown Chunk [Mesh Chunk] [0x%x]\n", chunk.idnum);
390             fseek(f, chunk.endoffset, SEEK_SET);
391          }
392          else {
393             break;
394          }
395       }
396    }
397    if (model.numverts != 0 && model.numfaces != 0 &&
398        model.vlist != 0 && model.flist != 0) {
399       ConvertModel();
400    }
401    if (model.vlist != 0) delete [] model.vlist;
402    if (model.flist != 0) delete [] model.flist;
403    model.vlist = 0;
404    model.flist = 0;
405    model.numverts = model.numfaces = 0;
406    sprintf(model.name,"");
407    nummodels++;
408    return 0;
409 }
410
411 //______________________________________________________________________________
412 Int_t ReadVerticesChunk(FILE *f)
413 {
414    // reads Vertex data of the TriMesh Chunk
415
416    Int_t i;
417    UShort_t numv = 0;
418    Float_t x, y, z;
419
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);
428       }
429       printf("\nWarning : Insufficient Memory to Load Vertices!\n");
430       return -1;
431    }
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);
436    }
437    model.numverts = (ULong_t) numv;
438    printf("Done!\n");
439    return 0;
440 }
441
442 //______________________________________________________________________________
443 Int_t ReadFacesChunk(FILE *f)
444 {
445    // reads Face data of the TriMesh Chunk
446
447    Int_t i;
448    UShort_t numf = 0, v1, v2, v3, attr;
449
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);
459       }
460       printf("\nWarning : Insufficient Memory to Load Faces!\n");
461       return -1;
462    }
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);
471    }
472    model.numfaces = (ULong_t)(numf);
473    printf("Done!\n");
474    return 0;
475 }
476
477 //______________________________________________________________________________
478 Int_t ReadMappingChunk(FILE *f)
479 {
480    // reads Texture Mapping data of the TriMesh Chunk
481
482    UShort_t numuv = 0, i;
483    Float_t u, v;
484
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);
491       }
492       printf("\nWarning : Number of Vertices and Mapping Data do not match!\n");
493       return -1;
494    }
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);
498    }
499    printf("Done!\n");
500    return 0;
501 }
502
503 //______________________________________________________________________________
504 Int_t ReadASCIIZ(FILE *f, char *name)
505 {
506    // reads a null-terminated string from the given file
507
508    char c = -1;
509    Int_t index = 0;
510
511    do {
512       fread(&c, sizeof(char), 1, f);
513       name[index] = c;
514       index++;
515       if (index == 255) {
516          name[index] = 0;
517          c = 0;
518       }
519    } while ((c != 0) && (!feof(f)));
520    return 0;
521 }
522
523 //______________________________________________________________________________
524 Int_t ConvertModel()
525 {
526    // Convert from Model structure to Reve::TriangleSet
527
528    Int_t i;
529
530    ts[nummodels] = new Reve::TriangleSet(model.numverts, model.numfaces);
531    if (ts[nummodels] == 0)
532       return -1;
533    for (i=0; i<model.numverts; ++i) {
534       ts[nummodels]->SetVertex(i, model.vlist[i].x, model.vlist[i].y,
535                                model.vlist[i].z);
536    }
537    for (i=0; i<model.numfaces; ++i) {
538       ts[nummodels]->SetTriangle(i, model.flist[i].v1, model.flist[i].v2,
539                                  model.flist[i].v3);
540    }
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])));
549          break;
550       }
551    }
552    return 0;
553 }
554
555 //______________________________________________________________________________
556 void view3ds(const char *fname = "nasashuttle.3ds") //"eventhorizon.3ds")
557 {
558    // main...
559
560    Int_t i;
561    for (i=0;i<2048;i++) ts[i] = 0;
562    for (i=0;i<1024;i++) material[i] = 0;
563    model.vlist = 0;
564    model.flist = 0;
565    nummodels = 0;
566    if (Read3DSFile(fname) == 0) {
567       for (i=0;i<nummodels;i++) {
568          if (ts[i]) {
569             ts[i]->GenerateTriangleNormals();
570             gReve->AddRenderElement(ts[i]);
571          }
572       }
573       gReve->Redraw3D(kTRUE);
574    }
575    for (i = 0; i < nummaterials; i++)
576       if (material[i] != 0) delete material[i];
577 }