view3ds.C

Go to the documentation of this file.
00001 // @(#)root/eve:$Id: view3ds.C 30704 2009-10-13 14:12:09Z matevz $
00002 // Author: Bertrand Bellenot
00003 
00004 // Loading and display of basic 3DS models.
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 // Believe3D Model file defines
00022 #define MAGICNUMBER 0xB3D0
00023 
00024 // types of 3DS Chunks
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 // Sub defines of MATERIAL
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 //The tMaterialInfo Struct
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 // Chunk structure
00069 typedef struct _Chunk {
00070    UShort_t idnum;
00071    UInt_t   offset, len, endoffset;
00072 } Chunk;
00073 
00074 // vertex structure
00075 typedef struct _Vertex {
00076    Float_t x, y, z;
00077    Float_t u, v;
00078 } Vertex;
00079 
00080 // face structure
00081 typedef struct _Face {
00082    UInt_t  v1, v2, v3;
00083 } Face;
00084 
00085 // model structure
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 // chunk reading routines
00108 Int_t ReadChunk(FILE*, Chunk*);
00109 
00110 // data reading routines
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 // global variables
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    // main function
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    // reads a chunk from an opened file
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    // handles the main body of the 3DS file
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          //printf("Debug : Unknown Chunk [Main Chunk] [0x%x]\n", chunk.idnum);
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    // reads the 3D Edit Chunk
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             //printf("Debug : Unknown Chunk [3D Chunk] [0x%x]\n", chunk.idnum);
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    // reads the Material sub-chunk of the 3D Edit Chunk
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             //printf("Debug : Unknown Chunk [Object Chunk] [0x%x]\n", chunk.idnum);
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    // reads the Color property of the Material Chunk
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             //printf("Debug : Unknown Chunk [Mesh Chunk] [0x%x]\n", chunk.idnum);
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    // reads the Transparency property of the Material Chunk
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             //printf("Debug : Unknown Chunk [Mesh Chunk] [0x%x]\n", chunk.idnum);
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    // reads the name of material associated to the current Chunk
00333 
00334    ReadASCIIZ(f, model.matname);
00335    return 0;
00336 }
00337 
00338 //______________________________________________________________________________
00339 Int_t ReadObjectChunk(FILE *f, UInt_t len)
00340 {
00341    // reads the Object sub-chunk of the 3D Edit Chunk
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             //printf("Debug : Unknown Chunk [Object Chunk] [0x%x]\n", chunk.idnum);
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    // reads the TriMesh sub-chunk of the Object Chunk
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             //printf("Debug : Unknown Chunk [Mesh Chunk] [0x%x]\n", chunk.idnum);
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    // reads Vertex data of the TriMesh Chunk
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    // reads Face data of the TriMesh Chunk
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    // reads Texture Mapping data of the TriMesh Chunk
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    // reads a null-terminated string from the given file
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    // Convert from Model structure to TEveTriangleSet
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    // Main.
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 }

Generated on Tue Jul 5 15:44:06 2011 for ROOT_528-00b_version by  doxygen 1.5.1