New files, 3DS import demo from Bertrand.
[u/mrichter/AliRoot.git] / EVE / test-macros / view3ds.C
CommitLineData
ab257ffc 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
12namespace Reve {
13 class TriangleSet;
14}
15Reve::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//////////////////////////////////////
49class Material {
50public:
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
65typedef struct _Chunk {
66 UShort_t idnum;
67 ULong_t offset, len, endoffset;
68} Chunk;
69
70// vertex structure
71typedef struct _Vertex {
72 Float_t x, y, z;
73 Float_t u, v;
74} Vertex;
75
76// face structure
77typedef struct _Face {
78 ULong_t v1, v2, v3;
79} Face;
80
81// model structure
82class Model {
83public:
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
104Int_t ReadChunk(FILE*, Chunk*);
105
106// data reading routines
107Int_t ReadMainChunk(FILE*);
108Int_t Read3DChunk(FILE*, ULong_t);
109Int_t ReadObjectChunk(FILE*, ULong_t);
110Int_t ReadMeshChunk(FILE*, ULong_t, char*);
111Int_t ReadVerticesChunk(FILE*);
112Int_t ReadFacesChunk(FILE*);
113Int_t ReadMappingChunk(FILE*);
114Int_t ReadASCIIZ(FILE*, char*);
115Int_t ReadMaterialChunk(FILE *, ULong_t);
116Int_t ReadColor(FILE *, ULong_t);
117Int_t ReadTransparency(FILE *, ULong_t);
118Int_t ReadObjectMaterial(FILE *);
119Int_t ConvertModel();
120
121// global variables
122Int_t nummodels = 0;
123Model model = {"","",0,0,0,0};
124
125Int_t nummaterials = 0;
126Material *material[1024];
127
128//______________________________________________________________________________
129Int_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//______________________________________________________________________________
149Int_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//______________________________________________________________________________
164Int_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//______________________________________________________________________________
185Int_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//______________________________________________________________________________
214Int_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//______________________________________________________________________________
251Int_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//______________________________________________________________________________
297Int_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//______________________________________________________________________________
329Int_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//______________________________________________________________________________
338Int_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//______________________________________________________________________________
363Int_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//______________________________________________________________________________
412Int_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//______________________________________________________________________________
443Int_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//______________________________________________________________________________
478Int_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//______________________________________________________________________________
504Int_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//______________________________________________________________________________
524Int_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//______________________________________________________________________________
556void 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}