00001
00002
00003
00004
00005
00006 #include "TCanvas.h"
00007 #include "TStyle.h"
00008 #include "TFile.h"
00009 #include "TStopwatch.h"
00010 #include "TError.h"
00011
00012 #include <math.h>
00013 #include <stdlib.h>
00014 #include <stdio.h>
00015 #include <string.h>
00016
00017 class TEveTriangleSet;
00018
00019 TEveTriangleSet *ts[2048];
00020
00021
00022 #define MAGICNUMBER 0xB3D0
00023
00024
00025 #define CHUNKMAIN 0x4D4D
00026 #define CHUNKMAINVERSION 0x0002
00027 #define CHUNK3D 0x3D3D
00028 #define CHUNK3DVERSION 0x3D3E
00029 #define CHUNK3DOBJECT 0x4000
00030 #define CHUNK3DOBJECTMESH 0x4100
00031 #define CHUNK3DOBJECTMESHVERTICES 0x4110
00032 #define CHUNK3DOBJECTMESHFACES 0x4120
00033 #define CHUNK3DOBJECTMESHMATGROUP 0x4130
00034 #define CHUNK3DOBJECTMESHMAPPING 0x4140
00035
00036 #define CHUNK3DMATERIAL 0xAFFF
00037
00038 #define MATNAME 0xA000
00039 #define MATDIFFUSE 0xA020
00040 #define MATSPECULAR 0xA030
00041 #define MATTRANSPARENCY 0xA050
00042
00043 #define COLOR_F 0x0010
00044 #define COLOR_24 0x0011
00045 #define LIN_COLOR_24 0x0012
00046 #define LIN_COLOR_F 0x0013
00047 #define INT_PERCENTAGE 0x0030
00048 #define FLOAT_PERCENTAGE 0x0031
00049
00050
00051
00052
00053 class Material {
00054 public:
00055 char name[256];
00056 UChar_t color[3];
00057 UShort_t transparency;
00058
00059 Material() {
00060 sprintf(name, "");
00061 color[0] = color[1] = color[2] = 0;
00062 transparency = 0;
00063 }
00064 ~Material() { }
00065 };
00066
00067
00068
00069 typedef struct _Chunk {
00070 UShort_t idnum;
00071 UInt_t offset, len, endoffset;
00072 } Chunk;
00073
00074
00075 typedef struct _Vertex {
00076 Float_t x, y, z;
00077 Float_t u, v;
00078 } Vertex;
00079
00080
00081 typedef struct _Face {
00082 UInt_t v1, v2, v3;
00083 } Face;
00084
00085
00086 class Model {
00087 public:
00088 char name[256];
00089 char matname[256];
00090 Vertex *vlist;
00091 Face *flist;
00092 UInt_t numverts, numfaces;
00093
00094 Model() {
00095 sprintf(name,"");
00096 sprintf(matname,"");
00097 vlist = 0;
00098 flist = 0;
00099 numverts = numfaces = 0;
00100 }
00101 ~Model() {
00102 if (vlist != 0) delete [] vlist;
00103 if (flist != 0) delete [] flist;
00104 }
00105 };
00106
00107
00108 Int_t ReadChunk(FILE*, Chunk*);
00109
00110
00111 Int_t ReadMainChunk(FILE*);
00112 Int_t Read3DChunk(FILE*, UInt_t);
00113 Int_t ReadObjectChunk(FILE*, UInt_t);
00114 Int_t ReadMeshChunk(FILE*, UInt_t, char*);
00115 Int_t ReadVerticesChunk(FILE*);
00116 Int_t ReadFacesChunk(FILE*);
00117 Int_t ReadMappingChunk(FILE*);
00118 Int_t ReadASCIIZ(FILE*, char*);
00119 Int_t ReadMaterialChunk(FILE *, UInt_t);
00120 Int_t ReadColor(FILE *, UInt_t);
00121 Int_t ReadTransparency(FILE *, UInt_t);
00122 Int_t ReadObjectMaterial(FILE *);
00123 Int_t ConvertModel();
00124
00125
00126 Int_t nummodels = 0;
00127 Model model = {"","",0,0,0,0};
00128
00129 Int_t nummaterials = 0;
00130 Material *material[1024];
00131
00132
00133 Int_t Read3DSFile(const char *fname)
00134 {
00135
00136
00137 FILE *infile;
00138
00139 infile = fopen(fname, "rb");
00140 if (infile == 0) {
00141 printf("Error : Input File Could Not Be Opened!\n");
00142 return -1;
00143 }
00144 UShort_t magic = MAGICNUMBER;
00145 if (ReadMainChunk(infile) != 0) {
00146 printf("Error : Input File Could Not Be Read!\n");
00147 }
00148 fclose(infile);
00149 return 0;
00150 }
00151
00152
00153 Int_t ReadChunk(FILE *f, Chunk *c)
00154 {
00155
00156
00157 if (feof(f)) return(-1);
00158 c->idnum = 0;
00159 c->offset = c->len = 0;
00160 c->offset = (UInt_t) ftell(f);
00161 fread(&c->idnum, sizeof(UShort_t), 1, f);
00162 fread(&c->len, sizeof(UInt_t), 1, f);
00163 c->endoffset = c->offset + c->len;
00164 return(0);
00165 }
00166
00167
00168 Int_t ReadMainChunk(FILE *f)
00169 {
00170
00171
00172 Chunk chunk;
00173
00174 ReadChunk(f, &chunk);
00175 if (chunk.idnum != CHUNKMAIN) return(-1);
00176 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
00177 if (chunk.idnum == CHUNK3D) {
00178 Read3DChunk(f, chunk.endoffset);
00179 }
00180 else {
00181
00182 fseek(f, chunk.offset + chunk.len, SEEK_SET);
00183 }
00184 }
00185 return 0;
00186 }
00187
00188
00189 Int_t Read3DChunk(FILE *f, UInt_t len)
00190 {
00191
00192
00193 Chunk chunk;
00194
00195 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
00196 if (chunk.idnum == CHUNK3DOBJECT) {
00197 ReadObjectChunk(f, chunk.endoffset);
00198 fseek(f, chunk.endoffset, SEEK_SET);
00199 }
00200 else if (chunk.idnum == CHUNK3DMATERIAL) {
00201 ReadMaterialChunk(f, chunk.endoffset);
00202 fseek(f, chunk.endoffset, SEEK_SET);
00203 }
00204 else {
00205 if (chunk.endoffset < len) {
00206
00207 fseek(f, chunk.endoffset, SEEK_SET);
00208 }
00209 else {
00210 break;
00211 }
00212 }
00213 }
00214 return 0;
00215 }
00216
00217
00218 Int_t ReadMaterialChunk(FILE *f, UInt_t len)
00219 {
00220
00221
00222 Chunk chunk;
00223 char name[256];
00224 material[nummaterials] = new Material();
00225 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
00226 if (chunk.idnum == MATNAME) {
00227 ReadASCIIZ(f, name);
00228 strcpy(material[nummaterials]->name, name);
00229 fseek(f, chunk.endoffset, SEEK_SET);
00230 }
00231 else if (chunk.idnum == MATDIFFUSE) {
00232 ReadColor(f, chunk.endoffset);
00233 fseek(f, chunk.endoffset, SEEK_SET);
00234 }
00235 else if (chunk.idnum == MATTRANSPARENCY) {
00236 ReadTransparency(f, chunk.endoffset);
00237 fseek(f, chunk.endoffset, SEEK_SET);
00238 }
00239 else {
00240 if (chunk.endoffset < len) {
00241
00242 fseek(f, chunk.endoffset, SEEK_SET);
00243 }
00244 else {
00245 break;
00246 }
00247 }
00248 }
00249 nummaterials++;
00250 return 0;
00251 }
00252
00253
00254 Int_t ReadColor(FILE *f, UInt_t len)
00255 {
00256
00257
00258 Chunk chunk;
00259 float fr, fg, fb;
00260 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
00261 if (chunk.idnum == LIN_COLOR_24) {
00262 fread(&material[nummaterials]->color[0], sizeof(UChar_t), 1, f);
00263 fread(&material[nummaterials]->color[1], sizeof(UChar_t), 1, f);
00264 fread(&material[nummaterials]->color[2], sizeof(UChar_t), 1, f);
00265 fseek(f, chunk.endoffset, SEEK_SET);
00266 }
00267 else if (chunk.idnum == COLOR_24) {
00268 fread(&material[nummaterials]->color[0], sizeof(UChar_t), 1, f);
00269 fread(&material[nummaterials]->color[1], sizeof(UChar_t), 1, f);
00270 fread(&material[nummaterials]->color[2], sizeof(UChar_t), 1, f);
00271 fseek(f, chunk.endoffset, SEEK_SET);
00272 }
00273 else if (chunk.idnum == LIN_COLOR_F) {
00274 fread(&fr, sizeof(Float_t), 1, f);
00275 fread(&fg, sizeof(Float_t), 1, f);
00276 fread(&fb, sizeof(Float_t), 1, f);
00277 fseek(f, chunk.endoffset, SEEK_SET);
00278 }
00279 else if (chunk.idnum == COLOR_F) {
00280 fread(&fr, sizeof(Float_t), 1, f);
00281 fread(&fg, sizeof(Float_t), 1, f);
00282 fread(&fb, sizeof(Float_t), 1, f);
00283 fseek(f, chunk.endoffset, SEEK_SET);
00284 }
00285 else {
00286 if (chunk.endoffset < len) {
00287
00288 fseek(f, chunk.endoffset, SEEK_SET);
00289 }
00290 else {
00291 break;
00292 }
00293 }
00294 }
00295 return 0;
00296 }
00297
00298
00299 Int_t ReadTransparency(FILE *f, UInt_t len)
00300 {
00301
00302
00303 Chunk chunk;
00304 float ftransp;
00305 UShort_t stransp;
00306 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
00307 if (chunk.idnum == INT_PERCENTAGE) {
00308 fread(&stransp, sizeof(UShort_t), 1, f);
00309 material[nummaterials]->transparency = stransp;
00310 fseek(f, chunk.endoffset, SEEK_SET);
00311 }
00312 else if (chunk.idnum == FLOAT_PERCENTAGE) {
00313 fread(&ftransp, sizeof(float), 1, f);
00314 fseek(f, chunk.endoffset, SEEK_SET);
00315 }
00316 else {
00317 if (chunk.endoffset < len) {
00318
00319 fseek(f, chunk.endoffset, SEEK_SET);
00320 }
00321 else {
00322 break;
00323 }
00324 }
00325 }
00326 return 0;
00327 }
00328
00329
00330 Int_t ReadObjectMaterial(FILE *f)
00331 {
00332
00333
00334 ReadASCIIZ(f, model.matname);
00335 return 0;
00336 }
00337
00338
00339 Int_t ReadObjectChunk(FILE *f, UInt_t len)
00340 {
00341
00342
00343 Chunk chunk;
00344 char name[256];
00345 ReadASCIIZ(f, name);
00346 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
00347 if (chunk.idnum == CHUNK3DOBJECTMESH) {
00348 ReadMeshChunk(f, chunk.endoffset, name);
00349 }
00350 else {
00351 if (chunk.endoffset < len) {
00352
00353 fseek(f, chunk.endoffset, SEEK_SET);
00354 }
00355 else {
00356 break;
00357 }
00358 }
00359 }
00360 return 0;
00361 }
00362
00363
00364 Int_t ReadMeshChunk(FILE *f, UInt_t len, char *objname)
00365 {
00366
00367
00368 Chunk chunk;
00369 model.vlist = 0;
00370 model.flist = 0;
00371 model.numverts = model.numfaces = 0;
00372 sprintf(model.name, "%s", objname);
00373 printf("Reading Mesh : %s\n", objname);
00374 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
00375 if (chunk.idnum == CHUNK3DOBJECTMESHVERTICES) {
00376 ReadVerticesChunk(f);
00377 }
00378 else if (chunk.idnum == CHUNK3DOBJECTMESHFACES) {
00379 ReadFacesChunk(f);
00380 }
00381 else if (chunk.idnum == CHUNK3DOBJECTMESHMAPPING) {
00382 ReadMappingChunk(f);
00383 }
00384 else if (chunk.idnum == CHUNK3DOBJECTMESHMATGROUP) {
00385 ReadObjectMaterial(f);
00386 }
00387 else {
00388 if (chunk.endoffset < len) {
00389
00390 fseek(f, chunk.endoffset, SEEK_SET);
00391 }
00392 else {
00393 break;
00394 }
00395 }
00396 }
00397 ConvertModel();
00398 if (model.vlist != 0) delete [] model.vlist;
00399 if (model.flist != 0) delete [] model.flist;
00400 model.vlist = 0;
00401 model.flist = 0;
00402 model.numverts = model.numfaces = 0;
00403 sprintf(model.name,"");
00404 nummodels++;
00405 return 0;
00406 }
00407
00408
00409 Int_t ReadVerticesChunk(FILE *f)
00410 {
00411
00412
00413 Int_t i;
00414 UShort_t numv = 0;
00415 Float_t x, y, z;
00416
00417 fread(&numv, sizeof(UShort_t), 1, f);
00418 printf("Reading %i Vertices...", numv);
00419 model.vlist = new Vertex[numv];
00420 if (model.vlist == 0) {
00421 for (i = 0; i < numv; i++) {
00422 fread(&x, sizeof(Float_t), 1, f);
00423 fread(&y, sizeof(Float_t), 1, f);
00424 fread(&z, sizeof(Float_t), 1, f);
00425 }
00426 printf("\nWarning : Insufficient Memory to Load Vertices!\n");
00427 return -1;
00428 }
00429 for (i = 0; i < numv; i++) {
00430 fread(&model.vlist[i].x, sizeof(Float_t), 1, f);
00431 fread(&model.vlist[i].y, sizeof(Float_t), 1, f);
00432 fread(&model.vlist[i].z, sizeof(Float_t), 1, f);
00433 }
00434 model.numverts = (UInt_t) numv;
00435 printf("Done!\n");
00436 return 0;
00437 }
00438
00439
00440 Int_t ReadFacesChunk(FILE *f)
00441 {
00442
00443
00444 Int_t i;
00445 UShort_t numf = 0, v1, v2, v3, attr;
00446
00447 fread(&numf, sizeof(UShort_t), 1, f);
00448 printf("Reading %i Faces...", numf);
00449 model.flist = new Face[numf];
00450 if (model.flist == 0) {
00451 for (i = 0; i < numf; i++) {
00452 fread(&v1, sizeof(UShort_t), 1, f);
00453 fread(&v2, sizeof(UShort_t), 1, f);
00454 fread(&v3, sizeof(UShort_t), 1, f);
00455 fread(&attr, sizeof(UShort_t), 1, f);
00456 }
00457 printf("\nWarning : Insufficient Memory to Load Faces!\n");
00458 return -1;
00459 }
00460 for (i = 0; i < numf; i++) {
00461 fread(&v1, sizeof(UShort_t), 1, f);
00462 fread(&v2, sizeof(UShort_t), 1, f);
00463 fread(&v3, sizeof(UShort_t), 1, f);
00464 fread(&attr, sizeof(UShort_t), 1, f);
00465 model.flist[i].v1 = (UInt_t)(v1);
00466 model.flist[i].v2 = (UInt_t)(v2);
00467 model.flist[i].v3 = (UInt_t)(v3);
00468 }
00469 model.numfaces = (UInt_t)(numf);
00470 printf("Done!\n");
00471 return 0;
00472 }
00473
00474
00475 Int_t ReadMappingChunk(FILE *f)
00476 {
00477
00478
00479 UShort_t numuv = 0, i;
00480 Float_t u, v;
00481
00482 fread(&numuv, sizeof(UShort_t), 1, f);
00483 printf("Reading %i Texture Coordinates...", numuv);
00484 if (numuv != model.numverts) {
00485 for (i = 0; i < numuv; i++) {
00486 fread(&u, sizeof(Float_t), 1, f);
00487 fread(&v, sizeof(Float_t), 1, f);
00488 }
00489 printf("\nWarning : Number of Vertices and Mapping Data do not match!\n");
00490 return -1;
00491 }
00492 for (i = 0; i < numuv; i++) {
00493 fread(&model.vlist[i].u, sizeof(Float_t), 1, f);
00494 fread(&model.vlist[i].v, sizeof(Float_t), 1, f);
00495 }
00496 printf("Done!\n");
00497 return 0;
00498 }
00499
00500
00501 Int_t ReadASCIIZ(FILE *f, char *name)
00502 {
00503
00504
00505 char c = -1;
00506 Int_t index = 0;
00507
00508 do {
00509 fread(&c, sizeof(char), 1, f);
00510 name[index] = c;
00511 index++;
00512 if (index == 255) {
00513 name[index] = 0;
00514 c = 0;
00515 }
00516 } while ((c != 0) && (!feof(f)));
00517 return 0;
00518 }
00519
00520
00521 Int_t ConvertModel()
00522 {
00523
00524
00525 Int_t i;
00526
00527 ts[nummodels] = new TEveTriangleSet(model.numverts, model.numfaces);
00528 if (ts[nummodels] == 0)
00529 return -1;
00530 for (i=0; i<model.numverts; ++i) {
00531 ts[nummodels]->SetVertex(i, model.vlist[i].x, model.vlist[i].y,
00532 model.vlist[i].z);
00533 }
00534 for (i=0; i<model.numfaces; ++i) {
00535 ts[nummodels]->SetTriangle(i, model.flist[i].v1, model.flist[i].v2,
00536 model.flist[i].v3);
00537 }
00538 ts[nummodels]->SetName(model.name);
00539 ts[nummodels]->SetMainTransparency(0);
00540 ts[nummodels]->SetMainColor(0);
00541 for (i = 0; i < nummaterials; i++) {
00542 if (strcmp(model.matname, material[i]->name) == 0) {
00543 ts[nummodels]->SetMainTransparency(material[i]->transparency);
00544 ts[nummodels]->SetMainColorRGB(material[i]->color[0],
00545 material[i]->color[1],
00546 material[i]->color[2]);
00547 break;
00548 }
00549 }
00550 return 0;
00551 }
00552
00553
00554 void view3ds(const char *fname = "nasashuttle.3ds")
00555 {
00556
00557
00558 TEveManager::Create();
00559
00560 Int_t i;
00561 for (i=0;i<2048;i++) ts[i] = 0;
00562 for (i=0;i<1024;i++) material[i] = 0;
00563 model.vlist = 0;
00564 model.flist = 0;
00565 nummodels = 0;
00566 if (Read3DSFile(fname) == 0) {
00567 TEveTriangleSet* parent = new TEveTriangleSet(0, 0);
00568 parent->SetName(fname);
00569 gEve->AddElement(parent);
00570 for (i=0;i<nummodels;i++) {
00571 if (ts[i]) {
00572 ts[i]->GenerateTriangleNormals();
00573 ts[i]->RefMainTrans().RotateLF(1, 2, TMath::Pi());
00574 parent->AddElement(ts[i]);
00575 }
00576 }
00577 gEve->Redraw3D(kTRUE);
00578 }
00579 for (i = 0; i < nummaterials; i++)
00580 if (material[i] != 0) delete material[i];
00581 }