Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
view3ds.C
Go to the documentation of this file.
1/// \file
2/// \ingroup tutorial_eve
3/// Loading and display of basic 3DS models.
4///
5/// \image html eve_view3ds.png
6/// \macro_code
7///
8/// \author Bertrand Bellenot
9
10#include "TCanvas.h"
11#include "TStyle.h"
12#include "TFile.h"
13#include "TStopwatch.h"
14#include "TError.h"
15
16#include <math.h>
17#include <stdlib.h>
18#include <stdio.h>
19#include <string.h>
20
21class TEveTriangleSet;
22
23TEveTriangleSet *ts[2048];
24
25// Believe3D Model file defines
26#define MAGICNUMBER 0xB3D0
27
28// types of 3DS Chunks
29#define CHUNKMAIN 0x4D4D
30#define CHUNKMAINVERSION 0x0002
31#define CHUNK3D 0x3D3D
32#define CHUNK3DVERSION 0x3D3E
33#define CHUNK3DOBJECT 0x4000
34#define CHUNK3DOBJECTMESH 0x4100
35#define CHUNK3DOBJECTMESHVERTICES 0x4110
36#define CHUNK3DOBJECTMESHFACES 0x4120
37#define CHUNK3DOBJECTMESHMATGROUP 0x4130
38#define CHUNK3DOBJECTMESHMAPPING 0x4140
39
40#define CHUNK3DMATERIAL 0xAFFF
41// Sub defines of MATERIAL
42#define MATNAME 0xA000
43#define MATDIFFUSE 0xA020
44#define MATSPECULAR 0xA030
45#define MATTRANSPARENCY 0xA050
46
47#define COLOR_F 0x0010
48#define COLOR_24 0x0011
49#define LIN_COLOR_24 0x0012
50#define LIN_COLOR_F 0x0013
51#define INT_PERCENTAGE 0x0030
52#define FLOAT_PERCENTAGE 0x0031
53
54//////////////////////////////////////
55// The tMaterialInfo Struct
56//////////////////////////////////////
57class Material {
58public:
59 char name[256];
60 UChar_t color[3];
62
63 Material()
64 {
65 sprintf(name, "");
66 color[0] = color[1] = color[2] = 0;
67 transparency = 0;
68 }
69 ~Material() {}
70};
71
72// Chunk structure
73typedef struct _Chunk {
76} Chunk;
77
78// vertex structure
79typedef struct _Vertex {
80 Float_t x, y, z;
81 Float_t u, v;
82} Vertex;
83
84// face structure
85typedef struct _Face {
86 UInt_t v1, v2, v3;
87} Face;
88
89// model structure
90class Model {
91public:
92 char name[256];
93 char matname[256];
95 Face *flist;
97
98 Model()
99 {
100 sprintf(name, "");
101 sprintf(matname, "");
102 vlist = 0;
103 flist = 0;
104 numverts = numfaces = 0;
105 }
106 ~Model()
107 {
108 if (vlist != 0)
109 delete[] vlist;
110 if (flist != 0)
111 delete[] flist;
112 }
113};
114
115// chunk reading routines
116Int_t ReadChunk(FILE *, Chunk *);
117
118// data reading routines
122Int_t ReadMeshChunk(FILE *, UInt_t, char *);
126Int_t ReadASCIIZ(FILE *, char *);
132
133// global variables
134Int_t nummodels = 0;
135Model model;
136
138Material *material[1024];
139
140//______________________________________________________________________________
141Int_t Read3DSFile(const char *fname)
142{
143 // main function
144
145 FILE *infile;
146
147 infile = fopen(fname, "rb");
148 if (infile == 0) {
149 printf("Error : Input File Could Not Be Opened!\n");
150 return -1;
151 }
153 if (ReadMainChunk(infile) != 0) {
154 printf("Error : Input File Could Not Be Read!\n");
155 }
156 fclose(infile);
157 return 0;
158}
159
160//______________________________________________________________________________
161Int_t ReadChunk(FILE *f, Chunk *c)
162{
163 // reads a chunk from an opened file
164
165 if (feof(f))
166 return (-1);
167 c->idnum = 0;
168 c->offset = c->len = 0;
169 c->offset = (UInt_t)ftell(f);
170 fread(&c->idnum, sizeof(UShort_t), 1, f);
171 fread(&c->len, sizeof(UInt_t), 1, f);
172 c->endoffset = c->offset + c->len;
173 return (0);
174}
175
176//______________________________________________________________________________
178{
179 // handles the main body of the 3DS file
180
181 Chunk chunk;
182
183 ReadChunk(f, &chunk);
184 if (chunk.idnum != CHUNKMAIN)
185 return (-1);
186 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
187 if (chunk.idnum == CHUNK3D) {
188 Read3DChunk(f, chunk.endoffset);
189 } else {
190 // printf("Debug : Unknown Chunk [Main Chunk] [0x%x]\n", chunk.idnum);
191 fseek(f, chunk.offset + chunk.len, SEEK_SET);
192 }
193 }
194 return 0;
195}
196
197//______________________________________________________________________________
199{
200 // reads the 3D Edit Chunk
201
202 Chunk chunk;
203
204 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
205 if (chunk.idnum == CHUNK3DOBJECT) {
206 ReadObjectChunk(f, chunk.endoffset);
207 fseek(f, chunk.endoffset, SEEK_SET);
208 } else if (chunk.idnum == CHUNK3DMATERIAL) {
209 ReadMaterialChunk(f, chunk.endoffset);
210 fseek(f, chunk.endoffset, SEEK_SET);
211 } else {
212 if (chunk.endoffset < len) {
213 // printf("Debug : Unknown Chunk [3D Chunk] [0x%x]\n", chunk.idnum);
214 fseek(f, chunk.endoffset, SEEK_SET);
215 } else {
216 break;
217 }
218 }
219 }
220 return 0;
221}
222
223//______________________________________________________________________________
225{
226 // reads the Material sub-chunk of the 3D Edit Chunk
227
228 Chunk chunk;
229 char name[256];
230 material[nummaterials] = new Material();
231 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
232 if (chunk.idnum == MATNAME) {
233 ReadASCIIZ(f, name);
234 strcpy(material[nummaterials]->name, name);
235 fseek(f, chunk.endoffset, SEEK_SET);
236 } else if (chunk.idnum == MATDIFFUSE) {
237 ReadColor(f, chunk.endoffset);
238 fseek(f, chunk.endoffset, SEEK_SET);
239 } else if (chunk.idnum == MATTRANSPARENCY) {
240 ReadTransparency(f, chunk.endoffset);
241 fseek(f, chunk.endoffset, SEEK_SET);
242 } else {
243 if (chunk.endoffset < len) {
244 // printf("Debug : Unknown Chunk [Object Chunk] [0x%x]\n", chunk.idnum);
245 fseek(f, chunk.endoffset, SEEK_SET);
246 } else {
247 break;
248 }
249 }
250 }
251 nummaterials++;
252 return 0;
253}
254
255//______________________________________________________________________________
257{
258 // reads the Color property of the Material Chunk
259
260 Chunk chunk;
261 float fr, fg, fb;
262 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
263 if (chunk.idnum == LIN_COLOR_24) {
264 fread(&material[nummaterials]->color[0], sizeof(UChar_t), 1, f);
265 fread(&material[nummaterials]->color[1], sizeof(UChar_t), 1, f);
266 fread(&material[nummaterials]->color[2], sizeof(UChar_t), 1, f);
267 fseek(f, chunk.endoffset, SEEK_SET);
268 } else if (chunk.idnum == COLOR_24) {
269 fread(&material[nummaterials]->color[0], sizeof(UChar_t), 1, f);
270 fread(&material[nummaterials]->color[1], sizeof(UChar_t), 1, f);
271 fread(&material[nummaterials]->color[2], sizeof(UChar_t), 1, f);
272 fseek(f, chunk.endoffset, SEEK_SET);
273 } else if (chunk.idnum == LIN_COLOR_F) {
274 fread(&fr, sizeof(Float_t), 1, f);
275 fread(&fg, sizeof(Float_t), 1, f);
276 fread(&fb, sizeof(Float_t), 1, f);
277 fseek(f, chunk.endoffset, SEEK_SET);
278 } else if (chunk.idnum == COLOR_F) {
279 fread(&fr, sizeof(Float_t), 1, f);
280 fread(&fg, sizeof(Float_t), 1, f);
281 fread(&fb, sizeof(Float_t), 1, f);
282 fseek(f, chunk.endoffset, SEEK_SET);
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 } else {
288 break;
289 }
290 }
291 }
292 return 0;
293}
294
295//______________________________________________________________________________
297{
298 // reads the Transparency property of the Material Chunk
299
300 Chunk chunk;
301 float ftransp;
303 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
304 if (chunk.idnum == INT_PERCENTAGE) {
305 fread(&stransp, sizeof(UShort_t), 1, f);
306 material[nummaterials]->transparency = stransp;
307 fseek(f, chunk.endoffset, SEEK_SET);
308 } else if (chunk.idnum == FLOAT_PERCENTAGE) {
309 fread(&ftransp, sizeof(float), 1, f);
310 fseek(f, chunk.endoffset, SEEK_SET);
311 } else {
312 if (chunk.endoffset < len) {
313 // printf("Debug : Unknown Chunk [Mesh Chunk] [0x%x]\n", chunk.idnum);
314 fseek(f, chunk.endoffset, SEEK_SET);
315 } else {
316 break;
317 }
318 }
319 }
320 return 0;
321}
322
323//______________________________________________________________________________
325{
326 // reads the name of material associated to the current Chunk
327
328 ReadASCIIZ(f, model.matname);
329 return 0;
330}
331
332//______________________________________________________________________________
334{
335 // reads the Object sub-chunk of the 3D Edit Chunk
336
337 Chunk chunk;
338 char name[256];
339 ReadASCIIZ(f, name);
340 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
341 if (chunk.idnum == CHUNK3DOBJECTMESH) {
342 ReadMeshChunk(f, chunk.endoffset, name);
343 } else {
344 if (chunk.endoffset < len) {
345 // printf("Debug : Unknown Chunk [Object Chunk] [0x%x]\n", chunk.idnum);
346 fseek(f, chunk.endoffset, SEEK_SET);
347 } else {
348 break;
349 }
350 }
351 }
352 return 0;
353}
354
355//______________________________________________________________________________
357{
358 // reads the TriMesh sub-chunk of the Object Chunk
359
360 Chunk chunk;
361 model.vlist = 0;
362 model.flist = 0;
363 model.numverts = model.numfaces = 0;
364 sprintf(model.name, "%s", objname);
365 printf("Reading Mesh : %s\n", objname);
366 while ((ReadChunk(f, &chunk) == 0) && (!feof(f))) {
367 if (chunk.idnum == CHUNK3DOBJECTMESHVERTICES) {
369 } else if (chunk.idnum == CHUNK3DOBJECTMESHFACES) {
371 } else if (chunk.idnum == CHUNK3DOBJECTMESHMAPPING) {
373 } else if (chunk.idnum == CHUNK3DOBJECTMESHMATGROUP) {
375 } else {
376 if (chunk.endoffset < len) {
377 // printf("Debug : Unknown Chunk [Mesh Chunk] [0x%x]\n", chunk.idnum);
378 fseek(f, chunk.endoffset, SEEK_SET);
379 } else {
380 break;
381 }
382 }
383 }
384 ConvertModel();
385 if (model.vlist != 0)
386 delete[] model.vlist;
387 if (model.flist != 0)
388 delete[] model.flist;
389 model.vlist = 0;
390 model.flist = 0;
391 model.numverts = model.numfaces = 0;
392 sprintf(model.name, "");
393 nummodels++;
394 return 0;
395}
396
397//______________________________________________________________________________
399{
400 // reads Vertex data of the TriMesh Chunk
401
402 Int_t i;
403 UShort_t numv = 0;
404 Float_t x, y, z;
405
406 fread(&numv, sizeof(UShort_t), 1, f);
407 printf("Reading %i Vertices...", numv);
408 model.vlist = new Vertex[numv];
409 if (model.vlist == 0) {
410 for (i = 0; i < numv; i++) {
411 fread(&x, sizeof(Float_t), 1, f);
412 fread(&y, sizeof(Float_t), 1, f);
413 fread(&z, sizeof(Float_t), 1, f);
414 }
415 printf("\nWarning : Insufficient Memory to Load Vertices!\n");
416 return -1;
417 }
418 for (i = 0; i < numv; i++) {
419 fread(&model.vlist[i].x, sizeof(Float_t), 1, f);
420 fread(&model.vlist[i].y, sizeof(Float_t), 1, f);
421 fread(&model.vlist[i].z, sizeof(Float_t), 1, f);
422 }
423 model.numverts = (UInt_t)numv;
424 printf("Done!\n");
425 return 0;
426}
427
428//______________________________________________________________________________
430{
431 // reads Face data of the TriMesh Chunk
432
433 Int_t i;
434 UShort_t numf = 0, v1, v2, v3, attr;
435
436 fread(&numf, sizeof(UShort_t), 1, f);
437 printf("Reading %i Faces...", numf);
438 model.flist = new Face[numf];
439 if (model.flist == 0) {
440 for (i = 0; i < numf; i++) {
441 fread(&v1, sizeof(UShort_t), 1, f);
442 fread(&v2, sizeof(UShort_t), 1, f);
443 fread(&v3, sizeof(UShort_t), 1, f);
444 fread(&attr, sizeof(UShort_t), 1, f);
445 }
446 printf("\nWarning : Insufficient Memory to Load Faces!\n");
447 return -1;
448 }
449 for (i = 0; i < numf; i++) {
450 fread(&v1, sizeof(UShort_t), 1, f);
451 fread(&v2, sizeof(UShort_t), 1, f);
452 fread(&v3, sizeof(UShort_t), 1, f);
453 fread(&attr, sizeof(UShort_t), 1, f);
454 model.flist[i].v1 = (UInt_t)(v1);
455 model.flist[i].v2 = (UInt_t)(v2);
456 model.flist[i].v3 = (UInt_t)(v3);
457 }
458 model.numfaces = (UInt_t)(numf);
459 printf("Done!\n");
460 return 0;
461}
462
463//______________________________________________________________________________
465{
466 // reads Texture Mapping data of the TriMesh Chunk
467
468 UShort_t numuv = 0, i;
469 Float_t u, v;
470
471 fread(&numuv, sizeof(UShort_t), 1, f);
472 printf("Reading %i Texture Coordinates...", numuv);
473 if (numuv != model.numverts) {
474 for (i = 0; i < numuv; i++) {
475 fread(&u, sizeof(Float_t), 1, f);
476 fread(&v, sizeof(Float_t), 1, f);
477 }
478 printf("\nWarning : Number of Vertices and Mapping Data do not match!\n");
479 return -1;
480 }
481 for (i = 0; i < numuv; i++) {
482 fread(&model.vlist[i].u, sizeof(Float_t), 1, f);
483 fread(&model.vlist[i].v, sizeof(Float_t), 1, f);
484 }
485 printf("Done!\n");
486 return 0;
487}
488
489//______________________________________________________________________________
490Int_t ReadASCIIZ(FILE *f, char *name)
491{
492 // reads a null-terminated string from the given file
493
494 char c = -1;
495 Int_t index = 0;
496
497 do {
498 fread(&c, sizeof(char), 1, f);
499 name[index] = c;
500 index++;
501 if (index == 255) {
502 name[index] = 0;
503 c = 0;
504 }
505 } while ((c != 0) && (!feof(f)));
506 return 0;
507}
508
509//______________________________________________________________________________
511{
512 // Convert from Model structure to TEveTriangleSet
513
514 Int_t i;
515
516 ts[nummodels] = new TEveTriangleSet(model.numverts, model.numfaces);
517 if (ts[nummodels] == 0)
518 return -1;
519 for (i = 0; i < model.numverts; ++i) {
520 ts[nummodels]->SetVertex(i, model.vlist[i].x, model.vlist[i].y, model.vlist[i].z);
521 }
522 for (i = 0; i < model.numfaces; ++i) {
523 ts[nummodels]->SetTriangle(i, model.flist[i].v1, model.flist[i].v2, model.flist[i].v3);
524 }
525 ts[nummodels]->SetName(model.name);
526 ts[nummodels]->SetMainTransparency(0);
527 ts[nummodels]->SetMainColor(0);
528 for (i = 0; i < nummaterials; i++) {
529 if (strcmp(model.matname, material[i]->name) == 0) {
530 ts[nummodels]->SetMainTransparency(material[i]->transparency);
531 ts[nummodels]->SetMainColorRGB(material[i]->color[0], material[i]->color[1], material[i]->color[2]);
532 break;
533 }
534 }
535 return 0;
536}
537
538//______________________________________________________________________________
539void view3ds(const char *fname = "nasashuttle.3ds")
540{
541 // Main.
542
544
545 Int_t i;
546 for (i = 0; i < 2048; i++)
547 ts[i] = 0;
548 for (i = 0; i < 1024; i++)
549 material[i] = 0;
550 model.vlist = 0;
551 model.flist = 0;
552 nummodels = 0;
553 if (Read3DSFile(fname) == 0) {
554 TEveTriangleSet *parent = new TEveTriangleSet(0, 0);
555 parent->SetName(fname);
556 gEve->AddElement(parent);
557 for (i = 0; i < nummodels; i++) {
558 if (ts[i]) {
559 ts[i]->GenerateTriangleNormals();
560 ts[i]->RefMainTrans().RotateLF(1, 2, TMath::Pi());
561 parent->AddElement(ts[i]);
562 }
563 }
565 }
566 for (i = 0; i < nummaterials; i++)
567 if (material[i] != 0)
568 delete material[i];
569}
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
unsigned short UShort_t
Definition RtypesCore.h:40
int Int_t
Definition RtypesCore.h:45
unsigned char UChar_t
Definition RtypesCore.h:38
unsigned int UInt_t
Definition RtypesCore.h:46
float Float_t
Definition RtypesCore.h:57
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
R__EXTERN TEveManager * gEve
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t attr
char name[80]
Definition TGX11.cxx:110
virtual void AddElement(TEveElement *el)
Add el to the list of children.
void AddElement(TEveElement *element, TEveElement *parent=nullptr)
Add an element.
static TEveManager * Create(Bool_t map_window=kTRUE, Option_t *opt="FIV")
If global TEveManager* gEve is not set initialize it.
void Redraw3D(Bool_t resetCameras=kFALSE, Bool_t dropLogicals=kFALSE)
Made from a list of vertices and a list of triangles (triplets of vertex indices).
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:150
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
void Vertex(const Double_t *v)
constexpr Double_t Pi()
Definition TMath.h:37