ROOT logo
// @(#)root/eve:$Id: view3ds.C 26876 2008-12-12 14:45:40Z matevz $
// Author: Bertrand Bellenot

// Loading and display of basic 3DS models.

#include "TCanvas.h"
#include "TStyle.h"
#include "TFile.h"
#include "TStopwatch.h"
#include "TError.h"

#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

class TEveTriangleSet;

TEveTriangleSet *ts[2048];

// Believe3D Model file defines
#define MAGICNUMBER 0xB3D0

// types of 3DS Chunks
#define CHUNKMAIN                   0x4D4D
#define CHUNKMAINVERSION            0x0002
#define CHUNK3D                     0x3D3D
#define CHUNK3DVERSION              0x3D3E
#define CHUNK3DOBJECT               0x4000
#define CHUNK3DOBJECTMESH           0x4100
#define CHUNK3DOBJECTMESHVERTICES   0x4110
#define CHUNK3DOBJECTMESHFACES      0x4120
#define CHUNK3DOBJECTMESHMATGROUP   0x4130
#define CHUNK3DOBJECTMESHMAPPING    0x4140

#define CHUNK3DMATERIAL             0xAFFF
// Sub defines of MATERIAL
#define MATNAME                     0xA000
#define MATDIFFUSE                  0xA020
#define MATSPECULAR                 0xA030
#define MATTRANSPARENCY             0xA050

#define COLOR_F                     0x0010
#define COLOR_24                    0x0011
#define LIN_COLOR_24                0x0012
#define LIN_COLOR_F                 0x0013
#define INT_PERCENTAGE              0x0030
#define FLOAT_PERCENTAGE            0x0031

//////////////////////////////////////
//The tMaterialInfo Struct
//////////////////////////////////////
class Material {
public:
   char     name[256];
   UChar_t  color[3];
   UShort_t transparency;

   Material() {
      sprintf(name, "");
      color[0] = color[1] = color[2] = 0;
      transparency = 0;
   }
   ~Material() { }
};


// Chunk structure
typedef struct _Chunk {
   UShort_t idnum;
   UInt_t   offset, len, endoffset;
} Chunk;

// vertex structure
typedef struct _Vertex {
   Float_t x, y, z;
   Float_t u, v;
} Vertex;

// face structure
typedef struct _Face {
   UInt_t  v1, v2, v3;
} Face;

// model structure
class Model {
public:
   char     name[256];
   char     matname[256];
   Vertex   *vlist;
   Face     *flist;
   UInt_t   numverts, numfaces;
   
   Model() {  
      sprintf(name,"");
      sprintf(matname,"");
      vlist = 0;
      flist = 0;
      numverts = numfaces = 0;
   }
   ~Model() { 
      if (vlist != 0) delete [] vlist;
      if (flist != 0) delete [] flist;
   }
};

// chunk reading routines
Int_t ReadChunk(FILE*, Chunk*);

// data reading routines
Int_t ReadMainChunk(FILE*);
Int_t Read3DChunk(FILE*, UInt_t);
Int_t ReadObjectChunk(FILE*, UInt_t);
Int_t ReadMeshChunk(FILE*, UInt_t, char*);
Int_t ReadVerticesChunk(FILE*);
Int_t ReadFacesChunk(FILE*);
Int_t ReadMappingChunk(FILE*);
Int_t ReadASCIIZ(FILE*, char*);
Int_t ReadMaterialChunk(FILE *, UInt_t);
Int_t ReadColor(FILE *, UInt_t);
Int_t ReadTransparency(FILE *, UInt_t);
Int_t ReadObjectMaterial(FILE *);
Int_t ConvertModel();

// global variables
Int_t nummodels = 0;
Model model = {"","",0,0,0,0};

Int_t nummaterials = 0;
Material *material[1024];

//______________________________________________________________________________
Int_t Read3DSFile(const char *fname)
{
   // main function

   FILE *infile;

   infile = fopen(fname, "rb");
   if (infile == 0) {
      printf("Error : Input File Could Not Be Opened!\n");
      return -1;
   }
   UShort_t magic = MAGICNUMBER;
   if (ReadMainChunk(infile) != 0) {
      printf("Error : Input File Could Not Be Read!\n");
   }
   fclose(infile);
   return 0;
}

//______________________________________________________________________________
Int_t ReadChunk(FILE *f, Chunk *c)
{
   // reads a chunk from an opened file

   if (feof(f)) return(-1);
   c->idnum = 0;
   c->offset = c->len = 0;
   c->offset = (UInt_t) ftell(f);
   fread(&c->idnum, sizeof(UShort_t), 1, f);
   fread(&c->len, sizeof(UInt_t), 1, f);
   c->endoffset = c->offset + c->len;
   return(0);
}

//______________________________________________________________________________
Int_t ReadMainChunk(FILE *f)
{
   // handles the main body of the 3DS file

   Chunk chunk;

   ReadChunk(f, &chunk);
   if (chunk.idnum != CHUNKMAIN) return(-1);
   while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
      if (chunk.idnum == CHUNK3D) {
         Read3DChunk(f, chunk.endoffset);
      }
      else {
         //printf("Debug : Unknown Chunk [Main Chunk] [0x%x]\n", chunk.idnum);
         fseek(f, chunk.offset + chunk.len, SEEK_SET);
      }
   }
   return 0;
}

//______________________________________________________________________________
Int_t Read3DChunk(FILE *f, UInt_t len)
{
   // reads the 3D Edit Chunk

   Chunk chunk;

   while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
      if (chunk.idnum == CHUNK3DOBJECT) {
         ReadObjectChunk(f, chunk.endoffset);
         fseek(f, chunk.endoffset, SEEK_SET);
      }
      else if (chunk.idnum == CHUNK3DMATERIAL) {
         ReadMaterialChunk(f, chunk.endoffset);
         fseek(f, chunk.endoffset, SEEK_SET);
      }
      else {
         if (chunk.endoffset < len) {
            //printf("Debug : Unknown Chunk [3D Chunk] [0x%x]\n", chunk.idnum);
            fseek(f, chunk.endoffset, SEEK_SET);
         }
         else {
            break;
         }
      }
   }
   return 0;
}

//______________________________________________________________________________
Int_t ReadMaterialChunk(FILE *f, UInt_t len)
{
   // reads the Material sub-chunk of the 3D Edit Chunk

   Chunk chunk;
   char name[256];
   material[nummaterials] = new Material();
   while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
      if (chunk.idnum == MATNAME) {
         ReadASCIIZ(f, name);
         strcpy(material[nummaterials]->name, name);
         fseek(f, chunk.endoffset, SEEK_SET);
      }
      else if (chunk.idnum == MATDIFFUSE) {
         ReadColor(f, chunk.endoffset);
         fseek(f, chunk.endoffset, SEEK_SET);
      }
      else if (chunk.idnum == MATTRANSPARENCY) {
         ReadTransparency(f, chunk.endoffset);
         fseek(f, chunk.endoffset, SEEK_SET);
      }
      else {
         if (chunk.endoffset < len) {
            //printf("Debug : Unknown Chunk [Object Chunk] [0x%x]\n", chunk.idnum);
            fseek(f, chunk.endoffset, SEEK_SET);
         }
         else {
            break;
         }
      }
   }
   nummaterials++;
   return 0;
}

//______________________________________________________________________________
Int_t ReadColor(FILE *f, UInt_t len)
{
   // reads the Color property of the Material Chunk
   
   Chunk chunk;
   float fr, fg, fb;
   while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
      if (chunk.idnum == LIN_COLOR_24) {
         fread(&material[nummaterials]->color[0], sizeof(UChar_t), 1, f);
         fread(&material[nummaterials]->color[1], sizeof(UChar_t), 1, f);
         fread(&material[nummaterials]->color[2], sizeof(UChar_t), 1, f);
         fseek(f, chunk.endoffset, SEEK_SET);
      }
      else if (chunk.idnum == COLOR_24) {
         fread(&material[nummaterials]->color[0], sizeof(UChar_t), 1, f);
         fread(&material[nummaterials]->color[1], sizeof(UChar_t), 1, f);
         fread(&material[nummaterials]->color[2], sizeof(UChar_t), 1, f);
         fseek(f, chunk.endoffset, SEEK_SET);
      }
      else if (chunk.idnum == LIN_COLOR_F) {
         fread(&fr, sizeof(Float_t), 1, f);
         fread(&fg, sizeof(Float_t), 1, f);
         fread(&fb, sizeof(Float_t), 1, f);
         fseek(f, chunk.endoffset, SEEK_SET);
      }
      else if (chunk.idnum == COLOR_F) {
         fread(&fr, sizeof(Float_t), 1, f);
         fread(&fg, sizeof(Float_t), 1, f);
         fread(&fb, sizeof(Float_t), 1, f);
         fseek(f, chunk.endoffset, SEEK_SET);
      }
      else {
         if (chunk.endoffset < len) {
            //printf("Debug : Unknown Chunk [Mesh Chunk] [0x%x]\n", chunk.idnum);
            fseek(f, chunk.endoffset, SEEK_SET);
         }
         else {
            break;
         }
      }
   }
   return 0;
}

//______________________________________________________________________________
Int_t ReadTransparency(FILE *f, UInt_t len)
{
   // reads the Transparency property of the Material Chunk
   
   Chunk    chunk;
   float    ftransp;
   UShort_t stransp;
   while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
      if (chunk.idnum == INT_PERCENTAGE) {
         fread(&stransp, sizeof(UShort_t), 1, f);
         material[nummaterials]->transparency = stransp;
         fseek(f, chunk.endoffset, SEEK_SET);
      }
      else if (chunk.idnum == FLOAT_PERCENTAGE) {
         fread(&ftransp, sizeof(float), 1, f);
         fseek(f, chunk.endoffset, SEEK_SET);
      }
      else {
         if (chunk.endoffset < len) {
            //printf("Debug : Unknown Chunk [Mesh Chunk] [0x%x]\n", chunk.idnum);
            fseek(f, chunk.endoffset, SEEK_SET);
         }
         else {
            break;
         }
      }
   }
   return 0;
}

//______________________________________________________________________________
Int_t ReadObjectMaterial(FILE *f)
{
   // reads the name of material associated to the current Chunk

   ReadASCIIZ(f, model.matname);
   return 0;
}

//______________________________________________________________________________
Int_t ReadObjectChunk(FILE *f, UInt_t len)
{
   // reads the Object sub-chunk of the 3D Edit Chunk

   Chunk chunk;
   char name[256];
   ReadASCIIZ(f, name);
   while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
      if (chunk.idnum == CHUNK3DOBJECTMESH) {
         ReadMeshChunk(f, chunk.endoffset, name);
      }
      else {
         if (chunk.endoffset < len) {
            //printf("Debug : Unknown Chunk [Object Chunk] [0x%x]\n", chunk.idnum);
            fseek(f, chunk.endoffset, SEEK_SET);
         }
         else {
            break;
         }
      }
   }
   return 0;
}

//______________________________________________________________________________
Int_t ReadMeshChunk(FILE *f, UInt_t len, char *objname)
{
   // reads the TriMesh sub-chunk of the Object Chunk

   Chunk chunk;
   model.vlist = 0;
   model.flist = 0;
   model.numverts = model.numfaces = 0;
   sprintf(model.name, "%s", objname);
   printf("Reading Mesh : %s\n", objname);
   while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
      if (chunk.idnum == CHUNK3DOBJECTMESHVERTICES) {
         ReadVerticesChunk(f);
      }
      else if (chunk.idnum == CHUNK3DOBJECTMESHFACES) {
         ReadFacesChunk(f);
      }
      else if (chunk.idnum == CHUNK3DOBJECTMESHMAPPING) {
         ReadMappingChunk(f);
      }
      else if (chunk.idnum == CHUNK3DOBJECTMESHMATGROUP) {
         ReadObjectMaterial(f);
      }
      else {
         if (chunk.endoffset < len) {
            //printf("Debug : Unknown Chunk [Mesh Chunk] [0x%x]\n", chunk.idnum);
            fseek(f, chunk.endoffset, SEEK_SET);
         }
         else {
            break;
         }
      }
   }
   ConvertModel();
   if (model.vlist != 0) delete [] model.vlist;
   if (model.flist != 0) delete [] model.flist;
   model.vlist = 0;
   model.flist = 0;
   model.numverts = model.numfaces = 0;
   sprintf(model.name,"");
   nummodels++;
   return 0;
}

//______________________________________________________________________________
Int_t ReadVerticesChunk(FILE *f)
{
   // reads Vertex data of the TriMesh Chunk

   Int_t i;
   UShort_t numv = 0;
   Float_t x, y, z;

   fread(&numv, sizeof(UShort_t), 1, f);
   printf("Reading %i Vertices...", numv);
   model.vlist = new Vertex[numv];
   if (model.vlist == 0) {
      for (i = 0; i < numv; i++) {
         fread(&x, sizeof(Float_t), 1, f);
         fread(&y, sizeof(Float_t), 1, f);
         fread(&z, sizeof(Float_t), 1, f);
      }
      printf("\nWarning : Insufficient Memory to Load Vertices!\n");
      return -1;
   }
   for (i = 0; i < numv; i++) {
      fread(&model.vlist[i].x, sizeof(Float_t), 1, f);
      fread(&model.vlist[i].y, sizeof(Float_t), 1, f);
      fread(&model.vlist[i].z, sizeof(Float_t), 1, f);
   }
   model.numverts = (UInt_t) numv;
   printf("Done!\n");
   return 0;
}

//______________________________________________________________________________
Int_t ReadFacesChunk(FILE *f)
{
   // reads Face data of the TriMesh Chunk

   Int_t i;
   UShort_t numf = 0, v1, v2, v3, attr;

   fread(&numf, sizeof(UShort_t), 1, f);
   printf("Reading %i Faces...", numf);
   model.flist = new Face[numf];
   if (model.flist == 0) {
      for (i = 0; i < numf; i++) {
         fread(&v1, sizeof(UShort_t), 1, f);
         fread(&v2, sizeof(UShort_t), 1, f);
         fread(&v3, sizeof(UShort_t), 1, f);
         fread(&attr, sizeof(UShort_t), 1, f);
      }
      printf("\nWarning : Insufficient Memory to Load Faces!\n");
      return -1;
   }
   for (i = 0; i < numf; i++) {
      fread(&v1, sizeof(UShort_t), 1, f);
      fread(&v2, sizeof(UShort_t), 1, f);
      fread(&v3, sizeof(UShort_t), 1, f);
      fread(&attr, sizeof(UShort_t), 1, f);
      model.flist[i].v1 = (UInt_t)(v1);
      model.flist[i].v2 = (UInt_t)(v2);
      model.flist[i].v3 = (UInt_t)(v3);
   }
   model.numfaces = (UInt_t)(numf);
   printf("Done!\n");
   return 0;
}

//______________________________________________________________________________
Int_t ReadMappingChunk(FILE *f)
{
   // reads Texture Mapping data of the TriMesh Chunk

   UShort_t numuv = 0, i;
   Float_t u, v;

   fread(&numuv, sizeof(UShort_t), 1, f);
   printf("Reading %i Texture Coordinates...", numuv);
   if (numuv != model.numverts) {
      for (i = 0; i < numuv; i++) {
         fread(&u, sizeof(Float_t), 1, f);
         fread(&v, sizeof(Float_t), 1, f);
      }
      printf("\nWarning : Number of Vertices and Mapping Data do not match!\n");
      return -1;
   }
   for (i = 0; i < numuv; i++) {
      fread(&model.vlist[i].u, sizeof(Float_t), 1, f);
      fread(&model.vlist[i].v, sizeof(Float_t), 1, f);
   }
   printf("Done!\n");
   return 0;
}

//______________________________________________________________________________
Int_t ReadASCIIZ(FILE *f, char *name)
{
   // reads a null-terminated string from the given file

   char c = -1;
   Int_t index = 0;

   do {
      fread(&c, sizeof(char), 1, f);
      name[index] = c;
      index++;
      if (index == 255) {
         name[index] = 0;
         c = 0;
      }
   } while ((c != 0) && (!feof(f)));
   return 0;
}

//______________________________________________________________________________
Int_t ConvertModel()
{
   // Convert from Model structure to TEveTriangleSet

   Int_t i;

   ts[nummodels] = new TEveTriangleSet(model.numverts, model.numfaces);
   if (ts[nummodels] == 0)
      return -1;
   for (i=0; i<model.numverts; ++i) {
      ts[nummodels]->SetVertex(i, model.vlist[i].x, model.vlist[i].y,
                               model.vlist[i].z);
   }
   for (i=0; i<model.numfaces; ++i) {
      ts[nummodels]->SetTriangle(i, model.flist[i].v1, model.flist[i].v2,
                                 model.flist[i].v3);
   }
   ts[nummodels]->SetName(model.name);
   ts[nummodels]->SetMainTransparency(0);
   ts[nummodels]->SetMainColor(0);
   for (i = 0; i < nummaterials; i++) {
      if (strcmp(model.matname, material[i]->name) == 0) {
         ts[nummodels]->SetMainTransparency(material[i]->transparency);
         ts[nummodels]->SetMainColorRGB(material[i]->color[0], 
                                        material[i]->color[1], 
                                        material[i]->color[2]);
         break;
      }
   }
   return 0;
}

//______________________________________________________________________________
void view3ds(const char *fname = "nasashuttle.3ds")
{
   // Main.

   TEveManager::Create();

   Int_t i;
   for (i=0;i<2048;i++) ts[i] = 0;
   for (i=0;i<1024;i++) material[i] = 0;
   model.vlist = 0;
   model.flist = 0;
   nummodels = 0;
   if (Read3DSFile(fname) == 0) {
      TEveTriangleSet* parent = new TEveTriangleSet(0, 0);
      parent->SetName(fname);
      gEve->AddElement(parent);
      for (i=0;i<nummodels;i++) {
         if (ts[i]) {
            ts[i]->GenerateTriangleNormals();
            ts[i]->RefMainTrans().RotateLF(1, 2, TMath::Pi());
            gEve->AddElement(ts[i], parent);
         }
      }
      gEve->Redraw3D(kTRUE);
   }
   for (i = 0; i < nummaterials; i++)
      if (material[i] != 0) delete material[i];
}
 view3ds.C:1
 view3ds.C:2
 view3ds.C:3
 view3ds.C:4
 view3ds.C:5
 view3ds.C:6
 view3ds.C:7
 view3ds.C:8
 view3ds.C:9
 view3ds.C:10
 view3ds.C:11
 view3ds.C:12
 view3ds.C:13
 view3ds.C:14
 view3ds.C:15
 view3ds.C:16
 view3ds.C:17
 view3ds.C:18
 view3ds.C:19
 view3ds.C:20
 view3ds.C:21
 view3ds.C:22
 view3ds.C:23
 view3ds.C:24
 view3ds.C:25
 view3ds.C:26
 view3ds.C:27
 view3ds.C:28
 view3ds.C:29
 view3ds.C:30
 view3ds.C:31
 view3ds.C:32
 view3ds.C:33
 view3ds.C:34
 view3ds.C:35
 view3ds.C:36
 view3ds.C:37
 view3ds.C:38
 view3ds.C:39
 view3ds.C:40
 view3ds.C:41
 view3ds.C:42
 view3ds.C:43
 view3ds.C:44
 view3ds.C:45
 view3ds.C:46
 view3ds.C:47
 view3ds.C:48
 view3ds.C:49
 view3ds.C:50
 view3ds.C:51
 view3ds.C:52
 view3ds.C:53
 view3ds.C:54
 view3ds.C:55
 view3ds.C:56
 view3ds.C:57
 view3ds.C:58
 view3ds.C:59
 view3ds.C:60
 view3ds.C:61
 view3ds.C:62
 view3ds.C:63
 view3ds.C:64
 view3ds.C:65
 view3ds.C:66
 view3ds.C:67
 view3ds.C:68
 view3ds.C:69
 view3ds.C:70
 view3ds.C:71
 view3ds.C:72
 view3ds.C:73
 view3ds.C:74
 view3ds.C:75
 view3ds.C:76
 view3ds.C:77
 view3ds.C:78
 view3ds.C:79
 view3ds.C:80
 view3ds.C:81
 view3ds.C:82
 view3ds.C:83
 view3ds.C:84
 view3ds.C:85
 view3ds.C:86
 view3ds.C:87
 view3ds.C:88
 view3ds.C:89
 view3ds.C:90
 view3ds.C:91
 view3ds.C:92
 view3ds.C:93
 view3ds.C:94
 view3ds.C:95
 view3ds.C:96
 view3ds.C:97
 view3ds.C:98
 view3ds.C:99
 view3ds.C:100
 view3ds.C:101
 view3ds.C:102
 view3ds.C:103
 view3ds.C:104
 view3ds.C:105
 view3ds.C:106
 view3ds.C:107
 view3ds.C:108
 view3ds.C:109
 view3ds.C:110
 view3ds.C:111
 view3ds.C:112
 view3ds.C:113
 view3ds.C:114
 view3ds.C:115
 view3ds.C:116
 view3ds.C:117
 view3ds.C:118
 view3ds.C:119
 view3ds.C:120
 view3ds.C:121
 view3ds.C:122
 view3ds.C:123
 view3ds.C:124
 view3ds.C:125
 view3ds.C:126
 view3ds.C:127
 view3ds.C:128
 view3ds.C:129
 view3ds.C:130
 view3ds.C:131
 view3ds.C:132
 view3ds.C:133
 view3ds.C:134
 view3ds.C:135
 view3ds.C:136
 view3ds.C:137
 view3ds.C:138
 view3ds.C:139
 view3ds.C:140
 view3ds.C:141
 view3ds.C:142
 view3ds.C:143
 view3ds.C:144
 view3ds.C:145
 view3ds.C:146
 view3ds.C:147
 view3ds.C:148
 view3ds.C:149
 view3ds.C:150
 view3ds.C:151
 view3ds.C:152
 view3ds.C:153
 view3ds.C:154
 view3ds.C:155
 view3ds.C:156
 view3ds.C:157
 view3ds.C:158
 view3ds.C:159
 view3ds.C:160
 view3ds.C:161
 view3ds.C:162
 view3ds.C:163
 view3ds.C:164
 view3ds.C:165
 view3ds.C:166
 view3ds.C:167
 view3ds.C:168
 view3ds.C:169
 view3ds.C:170
 view3ds.C:171
 view3ds.C:172
 view3ds.C:173
 view3ds.C:174
 view3ds.C:175
 view3ds.C:176
 view3ds.C:177
 view3ds.C:178
 view3ds.C:179
 view3ds.C:180
 view3ds.C:181
 view3ds.C:182
 view3ds.C:183
 view3ds.C:184
 view3ds.C:185
 view3ds.C:186
 view3ds.C:187
 view3ds.C:188
 view3ds.C:189
 view3ds.C:190
 view3ds.C:191
 view3ds.C:192
 view3ds.C:193
 view3ds.C:194
 view3ds.C:195
 view3ds.C:196
 view3ds.C:197
 view3ds.C:198
 view3ds.C:199
 view3ds.C:200
 view3ds.C:201
 view3ds.C:202
 view3ds.C:203
 view3ds.C:204
 view3ds.C:205
 view3ds.C:206
 view3ds.C:207
 view3ds.C:208
 view3ds.C:209
 view3ds.C:210
 view3ds.C:211
 view3ds.C:212
 view3ds.C:213
 view3ds.C:214
 view3ds.C:215
 view3ds.C:216
 view3ds.C:217
 view3ds.C:218
 view3ds.C:219
 view3ds.C:220
 view3ds.C:221
 view3ds.C:222
 view3ds.C:223
 view3ds.C:224
 view3ds.C:225
 view3ds.C:226
 view3ds.C:227
 view3ds.C:228
 view3ds.C:229
 view3ds.C:230
 view3ds.C:231
 view3ds.C:232
 view3ds.C:233
 view3ds.C:234
 view3ds.C:235
 view3ds.C:236
 view3ds.C:237
 view3ds.C:238
 view3ds.C:239
 view3ds.C:240
 view3ds.C:241
 view3ds.C:242
 view3ds.C:243
 view3ds.C:244
 view3ds.C:245
 view3ds.C:246
 view3ds.C:247
 view3ds.C:248
 view3ds.C:249
 view3ds.C:250
 view3ds.C:251
 view3ds.C:252
 view3ds.C:253
 view3ds.C:254
 view3ds.C:255
 view3ds.C:256
 view3ds.C:257
 view3ds.C:258
 view3ds.C:259
 view3ds.C:260
 view3ds.C:261
 view3ds.C:262
 view3ds.C:263
 view3ds.C:264
 view3ds.C:265
 view3ds.C:266
 view3ds.C:267
 view3ds.C:268
 view3ds.C:269
 view3ds.C:270
 view3ds.C:271
 view3ds.C:272
 view3ds.C:273
 view3ds.C:274
 view3ds.C:275
 view3ds.C:276
 view3ds.C:277
 view3ds.C:278
 view3ds.C:279
 view3ds.C:280
 view3ds.C:281
 view3ds.C:282
 view3ds.C:283
 view3ds.C:284
 view3ds.C:285
 view3ds.C:286
 view3ds.C:287
 view3ds.C:288
 view3ds.C:289
 view3ds.C:290
 view3ds.C:291
 view3ds.C:292
 view3ds.C:293
 view3ds.C:294
 view3ds.C:295
 view3ds.C:296
 view3ds.C:297
 view3ds.C:298
 view3ds.C:299
 view3ds.C:300
 view3ds.C:301
 view3ds.C:302
 view3ds.C:303
 view3ds.C:304
 view3ds.C:305
 view3ds.C:306
 view3ds.C:307
 view3ds.C:308
 view3ds.C:309
 view3ds.C:310
 view3ds.C:311
 view3ds.C:312
 view3ds.C:313
 view3ds.C:314
 view3ds.C:315
 view3ds.C:316
 view3ds.C:317
 view3ds.C:318
 view3ds.C:319
 view3ds.C:320
 view3ds.C:321
 view3ds.C:322
 view3ds.C:323
 view3ds.C:324
 view3ds.C:325
 view3ds.C:326
 view3ds.C:327
 view3ds.C:328
 view3ds.C:329
 view3ds.C:330
 view3ds.C:331
 view3ds.C:332
 view3ds.C:333
 view3ds.C:334
 view3ds.C:335
 view3ds.C:336
 view3ds.C:337
 view3ds.C:338
 view3ds.C:339
 view3ds.C:340
 view3ds.C:341
 view3ds.C:342
 view3ds.C:343
 view3ds.C:344
 view3ds.C:345
 view3ds.C:346
 view3ds.C:347
 view3ds.C:348
 view3ds.C:349
 view3ds.C:350
 view3ds.C:351
 view3ds.C:352
 view3ds.C:353
 view3ds.C:354
 view3ds.C:355
 view3ds.C:356
 view3ds.C:357
 view3ds.C:358
 view3ds.C:359
 view3ds.C:360
 view3ds.C:361
 view3ds.C:362
 view3ds.C:363
 view3ds.C:364
 view3ds.C:365
 view3ds.C:366
 view3ds.C:367
 view3ds.C:368
 view3ds.C:369
 view3ds.C:370
 view3ds.C:371
 view3ds.C:372
 view3ds.C:373
 view3ds.C:374
 view3ds.C:375
 view3ds.C:376
 view3ds.C:377
 view3ds.C:378
 view3ds.C:379
 view3ds.C:380
 view3ds.C:381
 view3ds.C:382
 view3ds.C:383
 view3ds.C:384
 view3ds.C:385
 view3ds.C:386
 view3ds.C:387
 view3ds.C:388
 view3ds.C:389
 view3ds.C:390
 view3ds.C:391
 view3ds.C:392
 view3ds.C:393
 view3ds.C:394
 view3ds.C:395
 view3ds.C:396
 view3ds.C:397
 view3ds.C:398
 view3ds.C:399
 view3ds.C:400
 view3ds.C:401
 view3ds.C:402
 view3ds.C:403
 view3ds.C:404
 view3ds.C:405
 view3ds.C:406
 view3ds.C:407
 view3ds.C:408
 view3ds.C:409
 view3ds.C:410
 view3ds.C:411
 view3ds.C:412
 view3ds.C:413
 view3ds.C:414
 view3ds.C:415
 view3ds.C:416
 view3ds.C:417
 view3ds.C:418
 view3ds.C:419
 view3ds.C:420
 view3ds.C:421
 view3ds.C:422
 view3ds.C:423
 view3ds.C:424
 view3ds.C:425
 view3ds.C:426
 view3ds.C:427
 view3ds.C:428
 view3ds.C:429
 view3ds.C:430
 view3ds.C:431
 view3ds.C:432
 view3ds.C:433
 view3ds.C:434
 view3ds.C:435
 view3ds.C:436
 view3ds.C:437
 view3ds.C:438
 view3ds.C:439
 view3ds.C:440
 view3ds.C:441
 view3ds.C:442
 view3ds.C:443
 view3ds.C:444
 view3ds.C:445
 view3ds.C:446
 view3ds.C:447
 view3ds.C:448
 view3ds.C:449
 view3ds.C:450
 view3ds.C:451
 view3ds.C:452
 view3ds.C:453
 view3ds.C:454
 view3ds.C:455
 view3ds.C:456
 view3ds.C:457
 view3ds.C:458
 view3ds.C:459
 view3ds.C:460
 view3ds.C:461
 view3ds.C:462
 view3ds.C:463
 view3ds.C:464
 view3ds.C:465
 view3ds.C:466
 view3ds.C:467
 view3ds.C:468
 view3ds.C:469
 view3ds.C:470
 view3ds.C:471
 view3ds.C:472
 view3ds.C:473
 view3ds.C:474
 view3ds.C:475
 view3ds.C:476
 view3ds.C:477
 view3ds.C:478
 view3ds.C:479
 view3ds.C:480
 view3ds.C:481
 view3ds.C:482
 view3ds.C:483
 view3ds.C:484
 view3ds.C:485
 view3ds.C:486
 view3ds.C:487
 view3ds.C:488
 view3ds.C:489
 view3ds.C:490
 view3ds.C:491
 view3ds.C:492
 view3ds.C:493
 view3ds.C:494
 view3ds.C:495
 view3ds.C:496
 view3ds.C:497
 view3ds.C:498
 view3ds.C:499
 view3ds.C:500
 view3ds.C:501
 view3ds.C:502
 view3ds.C:503
 view3ds.C:504
 view3ds.C:505
 view3ds.C:506
 view3ds.C:507
 view3ds.C:508
 view3ds.C:509
 view3ds.C:510
 view3ds.C:511
 view3ds.C:512
 view3ds.C:513
 view3ds.C:514
 view3ds.C:515
 view3ds.C:516
 view3ds.C:517
 view3ds.C:518
 view3ds.C:519
 view3ds.C:520
 view3ds.C:521
 view3ds.C:522
 view3ds.C:523
 view3ds.C:524
 view3ds.C:525
 view3ds.C:526
 view3ds.C:527
 view3ds.C:528
 view3ds.C:529
 view3ds.C:530
 view3ds.C:531
 view3ds.C:532
 view3ds.C:533
 view3ds.C:534
 view3ds.C:535
 view3ds.C:536
 view3ds.C:537
 view3ds.C:538
 view3ds.C:539
 view3ds.C:540
 view3ds.C:541
 view3ds.C:542
 view3ds.C:543
 view3ds.C:544
 view3ds.C:545
 view3ds.C:546
 view3ds.C:547
 view3ds.C:548
 view3ds.C:549
 view3ds.C:550
 view3ds.C:551
 view3ds.C:552
 view3ds.C:553
 view3ds.C:554
 view3ds.C:555
 view3ds.C:556
 view3ds.C:557
 view3ds.C:558
 view3ds.C:559
 view3ds.C:560
 view3ds.C:561
 view3ds.C:562
 view3ds.C:563
 view3ds.C:564
 view3ds.C:565
 view3ds.C:566
 view3ds.C:567
 view3ds.C:568
 view3ds.C:569
 view3ds.C:570
 view3ds.C:571
 view3ds.C:572
 view3ds.C:573
 view3ds.C:574
 view3ds.C:575
 view3ds.C:576
 view3ds.C:577
 view3ds.C:578
 view3ds.C:579
 view3ds.C:580
 view3ds.C:581
 view3ds.C:582
thumb