1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtk3DSImporter.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 #include "vtk3DSImporter.h"
16
17 #include "vtkActor.h"
18 #include "vtkByteSwap.h"
19 #include "vtkCamera.h"
20 #include "vtkCellArray.h"
21 #include "vtkLight.h"
22 #include "vtkObjectFactory.h"
23 #include "vtkPolyData.h"
24 #include "vtkPolyDataMapper.h"
25 #include "vtkPolyDataNormals.h"
26 #include "vtkProperty.h"
27 #include "vtkRenderer.h"
28 #include "vtkStripper.h"
29
30 vtkStandardNewMacro(vtk3DSImporter);
31
32 // Silence warning like
33 // "dereferencing type-punned pointer will break strict-aliasing rules"
34 // This file just has too many of them.
35 // This is due to the use of (vtk3DSList **)&root in VTK_LIST_* macros
36 // defined in vtk3DS.h
37 // pragma GCC diagnostic is available since gcc>=4.2
38 #if defined(__GNUC__) && (__GNUC__>4) || (__GNUC__==4 && __GNUC_MINOR__>=2)
39 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
40 #endif
41
42 static vtk3DSColour Black = {0.0, 0.0, 0.0};
43 static char obj_name[80] = "";
44 static vtk3DSColour fog_colour = {0.0, 0.0, 0.0};
45 static vtk3DSColour col = {0.0, 0.0, 0.0};
46 static vtk3DSColour global_amb = {0.1, 0.1, 0.1};
47 static vtk3DSVector pos = {0.0, 0.0, 0.0};
48 static vtk3DSVector target = {0.0, 0.0, 0.0};
49 static float hotspot = -1;
50 static float falloff = -1;
51 /* Default material property */
52 static vtk3DSMatProp DefaultMaterial =
53 { "Default", NULL,
54 {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0},
55 70.0, // shininess
56 0.0, // transparency
57 0.0, // reflection
58 0,// self illumination
59 "", // tex_map
60 0.0, // tex_strength
61 "", // bump_map
62 0.0, // bump_strength
63 NULL};// vtkProperty
64
65 static void cleanup_name (char *);
66 static void list_insert (vtk3DSList **root, vtk3DSList *new_node);
67 static void *list_find (vtk3DSList **root, const char *name);
68 static void list_kill (vtk3DSList **root);
69 static vtk3DSMatProp *create_mprop (void);
70 static vtk3DSMesh *create_mesh (char *name, int vertices, int faces);
71 static int parse_3ds_file (vtk3DSImporter *importer);
72 static void parse_3ds (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
73 static void parse_mdata (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
74 static void parse_fog (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
75 static void parse_fog_bgnd (vtk3DSImporter *importer);
76 static void parse_mat_entry (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
77 static char *parse_mapname (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
78 static void parse_named_object (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
79 static void parse_n_tri_object (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
80 static void parse_point_array (vtk3DSImporter *importer, vtk3DSMesh *mesh);
81 static void parse_face_array (vtk3DSImporter *importer, vtk3DSMesh *mesh, vtk3DSChunk *mainchunk);
82 static void parse_msh_mat_group (vtk3DSImporter *importer, vtk3DSMesh *mesh);
83 static void parse_smooth_group (vtk3DSImporter *importer);
84 static void parse_mesh_matrix (vtk3DSImporter *importer, vtk3DSMesh *mesh);
85 static void parse_n_direct_light (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
86 static void parse_dl_spotlight (vtk3DSImporter *importer);
87 static void parse_n_camera (vtk3DSImporter *importer);
88 static void parse_colour (vtk3DSImporter *importer, vtk3DSColour *colour);
89 static void parse_colour_f (vtk3DSImporter *importer, vtk3DSColour *colour);
90 static void parse_colour_24 (vtk3DSImporter *importer, vtk3DSColour_24 *colour);
91 static float parse_percentage (vtk3DSImporter *importer);
92 static short parse_int_percentage (vtk3DSImporter *importer);
93 static float parse_float_percentage (vtk3DSImporter *importer);
94 static vtk3DSMaterial *update_materials (vtk3DSImporter *importer, const char *new_material, int ext);
95 static void start_chunk (vtk3DSImporter *importer, vtk3DSChunk *chunk);
96 static void end_chunk (vtk3DSImporter *importer, vtk3DSChunk *chunk);
97 static byte read_byte (vtk3DSImporter *importer);
98 static word read_word (vtk3DSImporter *importer);
99 static word peek_word (vtk3DSImporter *importer);
100 static dword peek_dword (vtk3DSImporter *importer);
101 static float read_float (vtk3DSImporter *importer);
102 static void read_point (vtk3DSImporter *importer, vtk3DSVector v);
103 static char *read_string (vtk3DSImporter *importer);
104
vtk3DSImporter()105 vtk3DSImporter::vtk3DSImporter ()
106 {
107 this->OmniList = NULL;
108 this->SpotLightList = NULL;
109 this->CameraList = NULL;
110 this->MeshList = NULL;
111 this->MaterialList = NULL;
112 this->MatPropList = NULL;
113 this->FileName = NULL;
114 this->FileFD = NULL;
115 this->ComputeNormals = 0;
116 }
117
ImportBegin()118 int vtk3DSImporter::ImportBegin ()
119 {
120 vtkDebugMacro(<< "Opening import file as binary");
121 this->FileFD = fopen (this->FileName, "rb");
122 if (this->FileFD == NULL)
123 {
124 vtkErrorMacro(<< "Unable to open file: "<< this->FileName);
125 return 0;
126 }
127 return this->Read3DS ();
128 }
129
ImportEnd()130 void vtk3DSImporter::ImportEnd ()
131 {
132 vtkDebugMacro(<<"Closing import file");
133 if ( this->FileFD != NULL )
134 {
135 fclose (this->FileFD);
136 }
137 this->FileFD = NULL;
138 }
139
Read3DS()140 int vtk3DSImporter::Read3DS ()
141 {
142 vtk3DSMatProp *aMaterial;
143
144 if (parse_3ds_file (this) == 0)
145 {
146 vtkErrorMacro (<< "Error readings .3ds file: " << this->FileName << "\n");
147 return 0;
148 }
149
150
151 // create a vtk3DSMatProp and fill if in with default
152 aMaterial = (vtk3DSMatProp *) malloc (sizeof (vtk3DSMatProp));
153 *aMaterial = DefaultMaterial;
154 aMaterial->aProperty = vtkProperty::New ();
155 VTK_LIST_INSERT (this->MatPropList, aMaterial);
156 return 1;
157 }
158
ImportActors(vtkRenderer * renderer)159 void vtk3DSImporter::ImportActors (vtkRenderer *renderer)
160 {
161 vtk3DSMatProp *material;
162 vtk3DSMesh *mesh;
163 vtkStripper *polyStripper;
164 vtkPolyDataNormals *polyNormals;
165 vtkPolyDataMapper *polyMapper;
166 vtkPolyData *polyData;
167 vtkActor *actor;
168
169 // walk the list of meshes, creating actors
170 for (mesh = this->MeshList; mesh != (vtk3DSMesh *) NULL;
171 mesh = (vtk3DSMesh *) mesh->next)
172 {
173 if (mesh->faces == 0)
174 {
175 vtkWarningMacro (<< "part " << mesh->name << " has zero faces... skipping\n");
176 continue;
177 }
178
179 polyData = this->GeneratePolyData (mesh);
180 mesh->aMapper = polyMapper = vtkPolyDataMapper::New ();
181 mesh->aStripper = polyStripper = vtkStripper::New ();
182
183 // if ComputeNormals is on, insert a vtkPolyDataNormals filter
184 if (this->ComputeNormals)
185 {
186 mesh->aNormals = polyNormals = vtkPolyDataNormals::New ();
187 polyNormals->SetInputData (polyData);
188 polyStripper->SetInputConnection(polyNormals->GetOutputPort());
189 }
190 else
191 {
192 polyStripper->SetInputData(polyData);
193 }
194
195 polyMapper->SetInputConnection(polyStripper->GetOutputPort());
196 vtkDebugMacro (<< "Importing Actor: " << mesh->name);
197 mesh->anActor = actor = vtkActor::New ();
198 actor->SetMapper (polyMapper);
199 material = (vtk3DSMatProp *)VTK_LIST_FIND(this->MatPropList, mesh->mtl[0]->name);
200 actor->SetProperty (material->aProperty);
201 renderer->AddActor (actor);
202 }
203 }
204
GeneratePolyData(vtk3DSMesh * mesh)205 vtkPolyData *vtk3DSImporter::GeneratePolyData (vtk3DSMesh *mesh)
206 {
207 int i;
208 vtk3DSFace *face;
209 vtkCellArray *triangles;
210 vtkPoints *vertices;
211 vtkPolyData *polyData;
212
213 face = mesh->face;
214 mesh->aCellArray = triangles = vtkCellArray::New ();
215 triangles->Allocate(mesh->faces * 3);
216 for (i = 0; i < mesh->faces; i++, face++)
217 {
218 triangles->InsertNextCell (3);
219 triangles->InsertCellPoint (face->a);
220 triangles->InsertCellPoint (face->b);
221 triangles->InsertCellPoint (face->c);
222 }
223
224 mesh->aPoints = vertices = vtkPoints::New ();
225 vertices->Allocate(mesh->vertices);
226 for (i = 0; i < mesh->vertices; i++)
227 {
228 vertices->InsertPoint (i, (float *) mesh->vertex[i]);
229 }
230 mesh->aPolyData = polyData = vtkPolyData::New ();
231 polyData->SetPolys (triangles);
232 polyData->SetPoints (vertices);
233
234 return polyData;
235 }
236
ImportCameras(vtkRenderer * renderer)237 void vtk3DSImporter::ImportCameras (vtkRenderer *renderer)
238 {
239 vtkCamera *aCamera;
240 vtk3DSCamera *camera;
241
242 // walk the list of cameras and create vtk cameras
243 for (camera = this->CameraList; camera != (vtk3DSCamera *) NULL; camera = (vtk3DSCamera *) camera->next)
244 {
245 camera->aCamera = aCamera = vtkCamera::New ();
246 aCamera->SetPosition (camera->pos[0], camera->pos[1], camera->pos[2]);
247 aCamera->SetFocalPoint (camera->target[0], camera->target[1], camera->target[2]);
248 aCamera->SetViewUp (0, 0, 1);
249 aCamera->SetClippingRange (.1,10000);
250 aCamera->Roll (camera->bank);
251 renderer->SetActiveCamera (aCamera);
252 vtkDebugMacro (<< "Importing Camera: " << camera->name);
253 }
254 }
255
ImportLights(vtkRenderer * renderer)256 void vtk3DSImporter::ImportLights (vtkRenderer *renderer)
257 {
258 vtk3DSOmniLight *omniLight;
259 vtk3DSSpotLight *spotLight;
260 vtkLight *aLight;
261
262 // just walk the list of omni lights, creating vtk lights
263 for (omniLight = this->OmniList; omniLight != (vtk3DSOmniLight *) NULL;
264 omniLight = (vtk3DSOmniLight *) omniLight->next)
265 {
266 omniLight->aLight = aLight = vtkLight::New ();
267 aLight->SetPosition (omniLight->pos[0],
268 omniLight->pos[1],
269 omniLight->pos[2]);
270 aLight->SetFocalPoint (0, 0, 0);
271 aLight->SetColor (omniLight->col.red,
272 omniLight->col.green,
273 omniLight->col.blue);
274 renderer->AddLight (aLight);
275 vtkDebugMacro (<< "Importing Omni Light: " << omniLight->name);
276 }
277
278 // now walk the list of spot lights, creating vtk lights
279 for (spotLight = this->SpotLightList; spotLight != (vtk3DSSpotLight *) NULL;
280 spotLight = (vtk3DSSpotLight *) spotLight->next)
281 {
282 spotLight->aLight = aLight = vtkLight::New ();
283 aLight->PositionalOn ();
284 aLight->SetPosition (spotLight->pos[0],
285 spotLight->pos[1],
286 spotLight->pos[2]);
287 aLight->SetFocalPoint (spotLight->target[0],
288 spotLight->target[1],
289 spotLight->target[2]);
290 aLight->SetColor (spotLight->col.red,
291 spotLight->col.green,
292 spotLight->col.blue);
293 aLight->SetConeAngle (spotLight->falloff);
294 renderer->AddLight (aLight);
295 vtkDebugMacro (<< "Importing Spot Light: " << spotLight->name);
296 }
297 }
298
ImportProperties(vtkRenderer * vtkNotUsed (renderer))299 void vtk3DSImporter::ImportProperties (vtkRenderer *vtkNotUsed(renderer))
300 {
301 float amb = 0.1, dif = 0.9;
302 float dist_white, dist_diff, phong, phong_size;
303 vtkProperty *property;
304 vtk3DSMatProp *m;
305
306 // just walk the list of material properties, creating vtk properties
307 for (m = this->MatPropList; m != (vtk3DSMatProp *) NULL; m = (vtk3DSMatProp *) m->next)
308 {
309 if (m->self_illum)
310 {
311 amb = 0.9;
312 dif = 0.1;
313 }
314
315 dist_white = fabs(1.0 - m->specular.red) +
316 fabs(1.0 - m->specular.green) +
317 fabs(1.0 - m->specular.blue);
318
319 dist_diff = fabs(m->diffuse.red - m->specular.red) +
320 fabs(m->diffuse.green - m->specular.green) +
321 fabs(m->diffuse.blue - m->specular.blue);
322
323 if (dist_diff < dist_white)
324 {
325 dif = .1; amb = .8;
326 }
327
328 phong_size = 0.7*m->shininess;
329 if (phong_size < 1.0)
330 {
331 phong_size = 1.0;
332 }
333 if (phong_size > 30.0)
334 {
335 phong = 1.0;
336 }
337 else
338 {
339 phong = phong_size/30.0;
340 }
341 property = m->aProperty;
342 property->SetAmbientColor(m->ambient.red, m->ambient.green, m->ambient.blue);
343 property->SetAmbient (amb);
344 property->SetDiffuseColor(m->diffuse.red, m->diffuse.green, m->diffuse.blue);
345 property->SetDiffuse (dif);
346 property->SetSpecularColor(m->specular.red, m->specular.green, m->specular.blue);
347 property->SetSpecular (phong);
348 property->SetSpecularPower(phong_size);
349 property->SetOpacity(1.0 - m->transparency);
350 vtkDebugMacro(<< "Importing Property: " << m->name);
351
352 m->aProperty = property;
353 }
354 }
355
356 /* Insert a new node into the list */
list_insert(vtk3DSList ** root,vtk3DSList * new_node)357 static void list_insert (vtk3DSList **root, vtk3DSList *new_node)
358 {
359 new_node->next = *root;
360 *root = new_node;
361 }
362
363
364 /* Find the node with the specified name */
list_find(vtk3DSList ** root,const char * name)365 static void *list_find (vtk3DSList **root, const char *name)
366 {
367 vtk3DSList *p;
368 for (p = *root; p != (vtk3DSList *) NULL; p = (vtk3DSList *) p->next)
369 {
370 if (strcmp (p->name, name) == 0)
371 {
372 break;
373 }
374 }
375 return (void *)p;
376 }
377
378 /* Delete the entire list */
list_kill(vtk3DSList ** root)379 static void list_kill (vtk3DSList **root)
380 {
381 vtk3DSList *temp;
382
383 while (*root != (vtk3DSList *) NULL)
384 {
385 temp = *root;
386 *root = (vtk3DSList *) (*root)->next;
387 free (temp);
388 }
389 }
390
391 /* Add a new material to the material list */
update_materials(vtk3DSImporter * importer,const char * new_material,int ext)392 static vtk3DSMaterial *update_materials (vtk3DSImporter *importer, const char *new_material, int ext)
393 {
394 vtk3DSMaterial *p;
395
396 p = (vtk3DSMaterial *) VTK_LIST_FIND (importer->MaterialList, new_material);
397
398 if (p == NULL)
399 {
400 p = (vtk3DSMaterial *) malloc (sizeof (*p));
401 strcpy (p->name, new_material);
402 p->external = ext;
403 VTK_LIST_INSERT (importer->MaterialList, p);
404 }
405 return p;
406 }
407
408
create_mprop()409 static vtk3DSMatProp *create_mprop()
410 {
411 vtk3DSMatProp *new_mprop;
412
413 new_mprop = (vtk3DSMatProp *) malloc (sizeof(*new_mprop));
414 strcpy (new_mprop->name, "");
415 new_mprop->ambient = Black;
416 new_mprop->diffuse = Black;
417 new_mprop->specular = Black;
418 new_mprop->shininess = 0.0;
419 new_mprop->transparency = 0.0;
420 new_mprop->reflection = 0.0;
421 new_mprop->self_illum = 0;
422
423 strcpy (new_mprop->tex_map, "");
424 new_mprop->tex_strength = 0.0;
425
426 strcpy (new_mprop->bump_map, "");
427 new_mprop->bump_strength = 0.0;
428
429 new_mprop->aProperty = vtkProperty::New ();
430 return new_mprop;
431 }
432
433
434 /* Create a new mesh */
create_mesh(char * name,int vertices,int faces)435 static vtk3DSMesh *create_mesh (char *name, int vertices, int faces)
436 {
437 vtk3DSMesh *new_mesh;
438
439 new_mesh = (vtk3DSMesh *) malloc (sizeof(*new_mesh));
440 strcpy (new_mesh->name, name);
441
442 new_mesh->vertices = vertices;
443
444 if (vertices <= 0)
445 {
446 new_mesh->vertex = NULL;
447 }
448 else
449 {
450 new_mesh->vertex = (vtk3DSVector *) malloc(vertices * sizeof(*new_mesh->vertex));
451 }
452
453 new_mesh->faces = faces;
454
455 if (faces <= 0)
456 {
457 new_mesh->face = NULL;
458 new_mesh->mtl = NULL;
459 }
460 else
461 {
462 new_mesh->face = (vtk3DSFace *) malloc (faces * sizeof(*new_mesh->face));
463 new_mesh->mtl = (vtk3DSMaterial **) malloc (faces * sizeof(*new_mesh->mtl));
464 }
465
466 new_mesh->hidden = 0;
467 new_mesh->shadow = 1;
468
469 new_mesh->anActor = NULL;
470 new_mesh->aMapper = NULL;
471 new_mesh->aNormals = NULL;
472 new_mesh->aStripper = NULL;
473 new_mesh->aPoints = NULL;
474 new_mesh->aCellArray = NULL;
475 new_mesh->aPolyData = NULL;
476 return new_mesh;
477 }
478
479
parse_3ds_file(vtk3DSImporter * importer)480 static int parse_3ds_file(vtk3DSImporter *importer)
481 {
482 vtk3DSChunk chunk;
483
484 start_chunk(importer, &chunk);
485
486 if (chunk.tag == 0x4D4D)
487 {
488 parse_3ds (importer, &chunk);
489 }
490 else
491 {
492 vtkGenericWarningMacro(<< "Error: Input file is not .3DS format\n");
493 return 0;
494 }
495
496 end_chunk (importer, &chunk);
497 return 1;
498 }
499
parse_3ds(vtk3DSImporter * importer,vtk3DSChunk * mainchunk)500 static void parse_3ds (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
501 {
502 vtk3DSChunk chunk;
503
504 do
505 {
506 start_chunk (importer, &chunk);
507
508 if (chunk.end <= mainchunk->end)
509 {
510 switch (chunk.tag)
511 {
512 case 0x3D3D: parse_mdata (importer, &chunk);
513 break;
514 }
515 }
516 end_chunk (importer, &chunk);
517 } while (chunk.end <= mainchunk->end);
518 }
519
520
parse_mdata(vtk3DSImporter * importer,vtk3DSChunk * mainchunk)521 static void parse_mdata (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
522 {
523 vtk3DSChunk chunk;
524 vtk3DSColour bgnd_colour;
525
526 do
527 {
528 start_chunk (importer, &chunk);
529
530 if (chunk.end <= mainchunk->end)
531 {
532 switch (chunk.tag)
533 {
534 case 0x2100: parse_colour (importer, &global_amb);
535 break;
536 case 0x1200: parse_colour (importer, &bgnd_colour);
537 break;
538 case 0x2200: parse_fog (importer, &chunk);
539 break;
540 case 0x2210: parse_fog_bgnd(importer);
541 break;
542 case 0xAFFF: parse_mat_entry (importer, &chunk);
543 break;
544 case 0x4000: parse_named_object (importer, &chunk);
545 break;
546 }
547 }
548
549 end_chunk (importer, &chunk);
550 } while (chunk.end <= mainchunk->end);
551 }
552
553
parse_fog(vtk3DSImporter * importer,vtk3DSChunk * mainchunk)554 static void parse_fog (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
555 {
556 vtk3DSChunk chunk;
557
558 (void)read_float(importer);
559 (void)read_float(importer);
560 (void) read_float(importer);
561 (void)read_float(importer);
562
563 parse_colour (importer, &fog_colour);
564
565 do
566 {
567 start_chunk (importer, &chunk);
568
569 if (chunk.end <= mainchunk->end)
570 {
571 switch (chunk.tag)
572 {
573 case 0x2210: parse_fog_bgnd(importer);
574 break;
575 }
576 }
577
578 end_chunk (importer, &chunk);
579 } while (chunk.end <= mainchunk->end);
580 }
581
582
parse_fog_bgnd(vtk3DSImporter * vtkNotUsed (importer))583 static void parse_fog_bgnd(vtk3DSImporter *vtkNotUsed(importer))
584 {
585 }
586
587
parse_mat_entry(vtk3DSImporter * importer,vtk3DSChunk * mainchunk)588 static void parse_mat_entry (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
589 {
590 vtk3DSChunk chunk;
591 vtk3DSMatProp *mprop;
592
593 mprop = create_mprop();
594
595 do
596 {
597 start_chunk (importer, &chunk);
598 if (chunk.end <= mainchunk->end)
599 {
600 switch (chunk.tag)
601 {
602 case 0xA000: strcpy (mprop->name, read_string(importer));
603 cleanup_name (mprop->name);
604 break;
605
606 case 0xA010: parse_colour (importer, &mprop->ambient);
607 break;
608
609 case 0xA020: parse_colour (importer, &mprop->diffuse);
610 break;
611
612 case 0xA030: parse_colour (importer, &mprop->specular);
613 break;
614
615 case 0xA040: mprop->shininess = 100.0*parse_percentage(importer);
616 break;
617
618 case 0xA050: mprop->transparency = parse_percentage(importer);
619 break;
620
621 case 0xA080: mprop->self_illum = 1;
622 break;
623
624 case 0xA220: mprop->reflection = parse_percentage(importer);
625 (void)parse_mapname (importer, &chunk);
626 break;
627
628 case 0xA310: if (mprop->reflection == 0.0)
629 {
630 mprop->reflection = 1.0;
631 }
632 break;
633
634 case 0xA200: mprop->tex_strength = parse_percentage(importer);
635 strcpy (mprop->tex_map, parse_mapname (importer, &chunk));
636 break;
637
638 case 0xA230: mprop->bump_strength = parse_percentage(importer);
639 strcpy (mprop->bump_map, parse_mapname (importer, &chunk));
640 break;
641 }
642 }
643
644 end_chunk (importer, &chunk);
645 } while (chunk.end <= mainchunk->end);
646
647 VTK_LIST_INSERT (importer->MatPropList, mprop);
648 }
649
650
parse_mapname(vtk3DSImporter * importer,vtk3DSChunk * mainchunk)651 static char *parse_mapname (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
652 {
653 static char name[80] = "";
654 vtk3DSChunk chunk;
655
656 do
657 {
658 start_chunk (importer, &chunk);
659
660 if (chunk.end <= mainchunk->end)
661 {
662 switch (chunk.tag)
663 {
664 case 0xA300: strcpy (name, read_string(importer));
665 break;
666 }
667 }
668
669 end_chunk (importer, &chunk);
670 } while (chunk.end <= mainchunk->end);
671
672 return name;
673 }
674
675
parse_named_object(vtk3DSImporter * importer,vtk3DSChunk * mainchunk)676 static void parse_named_object (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
677 {
678 vtk3DSMesh *mesh;
679 vtk3DSChunk chunk;
680
681 strcpy (obj_name, read_string(importer));
682 cleanup_name (obj_name);
683
684 mesh = NULL;
685
686 do
687 {
688 start_chunk (importer, &chunk);
689 if (chunk.end <= mainchunk->end)
690 {
691 switch (chunk.tag)
692 {
693 case 0x4100: parse_n_tri_object (importer, &chunk);
694 break;
695 case 0x4600: parse_n_direct_light (importer, &chunk);
696 break;
697 case 0x4700: parse_n_camera(importer);
698 break;
699 case 0x4010: if (mesh != NULL)
700 {
701 mesh->hidden = 1;
702 }
703 break;
704 case 0x4012: if (mesh != NULL)
705 {
706 mesh->shadow = 0;
707 }
708 break;
709 }
710 }
711
712 end_chunk (importer, &chunk);
713 } while (chunk.end <= mainchunk->end);
714
715 }
716
parse_n_tri_object(vtk3DSImporter * importer,vtk3DSChunk * mainchunk)717 static void parse_n_tri_object (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
718 {
719 vtk3DSMesh *mesh;
720 vtk3DSChunk chunk;
721
722 mesh = create_mesh (obj_name, 0, 0);
723
724 do
725 {
726 start_chunk (importer, &chunk);
727
728 if (chunk.end <= mainchunk->end)
729 {
730 switch (chunk.tag)
731 {
732 case 0x4110: parse_point_array(importer, mesh);
733 break;
734 case 0x4120: parse_face_array (importer, mesh, &chunk);
735 break;
736 case 0x4160: parse_mesh_matrix(importer, mesh);
737 break;
738 }
739 }
740
741 end_chunk (importer, &chunk);
742 } while (chunk.end <= mainchunk->end);
743
744 VTK_LIST_INSERT (importer->MeshList, mesh);
745 }
746
747
parse_point_array(vtk3DSImporter * importer,vtk3DSMesh * mesh)748 static void parse_point_array(vtk3DSImporter *importer, vtk3DSMesh *mesh)
749 {
750 int i;
751
752 mesh->vertices = read_word(importer);
753 mesh->vertex = (vtk3DSVector *) malloc (mesh->vertices * sizeof(*(mesh->vertex)));
754 for (i = 0; i < mesh->vertices; i++)
755 {
756 read_point (importer, mesh->vertex[i]);
757 }
758 }
759
parse_face_array(vtk3DSImporter * importer,vtk3DSMesh * mesh,vtk3DSChunk * mainchunk)760 static void parse_face_array (vtk3DSImporter *importer, vtk3DSMesh *mesh, vtk3DSChunk *mainchunk)
761 {
762 vtk3DSChunk chunk;
763 int i;
764
765 mesh->faces = read_word(importer);
766 mesh->face = (vtk3DSFace *) malloc (mesh->faces * sizeof(*(mesh->face)));
767 mesh->mtl = (vtk3DSMaterial **) malloc (mesh->faces * sizeof(*(mesh->mtl)));
768
769 for (i = 0; i < mesh->faces; i++)
770 {
771 mesh->face[i].a = read_word(importer);
772 mesh->face[i].b = read_word(importer);
773 mesh->face[i].c = read_word(importer);
774 (void)read_word(importer);
775
776 mesh->mtl[i] = NULL;
777 }
778
779 do
780 {
781 start_chunk (importer, &chunk);
782 if (chunk.end <= mainchunk->end)
783 {
784 switch (chunk.tag)
785 {
786 case 0x4130: parse_msh_mat_group(importer, mesh);
787 break;
788 case 0x4150: parse_smooth_group(importer);
789 break;
790 }
791 }
792
793 end_chunk (importer, &chunk);
794 } while (chunk.end <= mainchunk->end);
795
796 for (i = 0; i < mesh->faces; i++)
797 {
798 if (mesh->mtl[i] == (vtk3DSMaterial *) NULL)
799 {
800 mesh->mtl[i] = update_materials (importer, "Default", 0);
801 }
802 }
803 }
804
805
parse_msh_mat_group(vtk3DSImporter * importer,vtk3DSMesh * mesh)806 static void parse_msh_mat_group(vtk3DSImporter *importer, vtk3DSMesh *mesh)
807 {
808 vtk3DSMaterial *new_mtl;
809 char mtlname[80];
810 int mtlcnt;
811 int i, face;
812
813 strcpy (mtlname, read_string(importer));
814 cleanup_name (mtlname);
815
816 new_mtl = update_materials (importer, mtlname, 0);
817
818 mtlcnt = read_word(importer);
819
820 for (i = 0; i < mtlcnt; i++)
821 {
822 face = read_word(importer);
823 mesh->mtl[face] = new_mtl;
824 }
825 }
826
parse_smooth_group(vtk3DSImporter * vtkNotUsed (importer))827 static void parse_smooth_group(vtk3DSImporter *vtkNotUsed(importer))
828 {
829 }
830
parse_mesh_matrix(vtk3DSImporter * vtkNotUsed (importer),vtk3DSMesh * vtkNotUsed (mesh))831 static void parse_mesh_matrix(vtk3DSImporter *vtkNotUsed(importer), vtk3DSMesh *vtkNotUsed(mesh))
832 {
833 // vtkGenericWarningMacro(<< "mesh matrix detected but not used\n");
834 }
835
836
parse_n_direct_light(vtk3DSImporter * importer,vtk3DSChunk * mainchunk)837 static void parse_n_direct_light (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
838 {
839 vtk3DSChunk chunk;
840 vtk3DSSpotLight *s;
841 vtk3DSOmniLight *o;
842 int spot_flag = 0;
843
844 read_point (importer, pos);
845 parse_colour (importer, &col);
846
847 do
848 {
849 start_chunk (importer, &chunk);
850
851 if (chunk.end <= mainchunk->end)
852 {
853 switch (chunk.tag)
854 {
855 case 0x4620: break;
856 case 0x4610: parse_dl_spotlight(importer);
857 spot_flag = 1;
858 break;
859 }
860 }
861
862 end_chunk (importer, &chunk);
863 } while (chunk.end <= mainchunk->end);
864
865 if (!spot_flag)
866 {
867 o = (vtk3DSOmniLight *) VTK_LIST_FIND (importer->OmniList, obj_name);
868
869 if (o != NULL)
870 {
871 pos[0] = o->pos[0];
872 pos[1] = o->pos[1];
873 pos[2] = o->pos[2];
874 col = o->col;
875 }
876 else
877 {
878 o = (vtk3DSOmniLight *) malloc (sizeof (*o));
879 o->pos[0] = pos[0];
880 o->pos[1] = pos[1];
881 o->pos[2] = pos[2];
882 o->col = col ;
883 strcpy (o->name, obj_name);
884 VTK_LIST_INSERT (importer->OmniList, o);
885 }
886 }
887 else
888 {
889 s = (vtk3DSSpotLight *) VTK_LIST_FIND (importer->SpotLightList, obj_name);
890
891 if (s != NULL)
892 {
893 pos[0] = s->pos[0];
894 pos[1] = s->pos[1];
895 pos[2] = s->pos[2];
896 target[0] = s->target[0];
897 target[1] = s->target[1];
898 target[2] = s->target[2];
899 col = s->col;
900 hotspot = s->hotspot;
901 falloff = s->falloff;
902 }
903 else
904 {
905 if (falloff <= 0.0)
906 {
907 falloff = 180.0;
908 }
909 if (hotspot <= 0.0)
910 {
911 hotspot = 0.7*falloff;
912 }
913 s = (vtk3DSSpotLight *) malloc (sizeof (*s));
914 s->pos[0] = pos[0];
915 s->pos[1] = pos[1];
916 s->pos[2] = pos[2];
917 s->target[0] = target[0];
918 s->target[1] = target[1];
919 s->target[2] = target[2];
920 s->col = col ;
921 s->hotspot = hotspot;
922 s->falloff = falloff;
923 strcpy (s->name, obj_name);
924 VTK_LIST_INSERT (importer->SpotLightList, s);
925 }
926 }
927 }
928
929
parse_dl_spotlight(vtk3DSImporter * importer)930 static void parse_dl_spotlight(vtk3DSImporter *importer)
931 {
932 read_point (importer, target);
933
934 hotspot = read_float(importer);
935 falloff = read_float(importer);
936 }
937
938
parse_n_camera(vtk3DSImporter * importer)939 static void parse_n_camera(vtk3DSImporter *importer)
940 {
941 float bank;
942 float lens;
943 vtk3DSCamera *c = (vtk3DSCamera *) malloc (sizeof (vtk3DSCamera));
944
945 read_point (importer, pos);
946 read_point (importer, target);
947 bank = read_float(importer);
948 lens = read_float(importer);
949
950 strcpy (c->name, obj_name);
951 c->pos[0] = pos[0];
952 c->pos[1] = pos[1];
953 c->pos[2] = pos[2];
954 c->target[0] = target[0];
955 c->target[1] = target[1];
956 c->target[2] = target[2];
957 c->lens = lens;
958 c->bank = bank;
959
960 VTK_LIST_INSERT (importer->CameraList, c);
961 }
962
parse_colour(vtk3DSImporter * importer,vtk3DSColour * colour)963 static void parse_colour (vtk3DSImporter *importer, vtk3DSColour *colour)
964 {
965 vtk3DSChunk chunk;
966 vtk3DSColour_24 colour_24;
967
968 start_chunk (importer, &chunk);
969
970 switch (chunk.tag)
971 {
972 case 0x0010: parse_colour_f (importer, colour);
973 break;
974
975 case 0x0011: parse_colour_24 (importer, &colour_24);
976 colour->red = colour_24.red/255.0;
977 colour->green = colour_24.green/255.0;
978 colour->blue = colour_24.blue/255.0;
979 break;
980
981 default: vtkGenericWarningMacro(<< "Error parsing colour");
982 }
983
984 end_chunk (importer, &chunk);
985 }
986
987
parse_colour_f(vtk3DSImporter * importer,vtk3DSColour * colour)988 static void parse_colour_f (vtk3DSImporter *importer, vtk3DSColour *colour)
989 {
990 colour->red = read_float(importer);
991 colour->green = read_float(importer);
992 colour->blue = read_float(importer);
993 }
994
995
parse_colour_24(vtk3DSImporter * importer,vtk3DSColour_24 * colour)996 static void parse_colour_24 (vtk3DSImporter *importer, vtk3DSColour_24 *colour)
997 {
998 colour->red = read_byte(importer);
999 colour->green = read_byte(importer);
1000 colour->blue = read_byte(importer);
1001 }
1002
1003
parse_percentage(vtk3DSImporter * importer)1004 static float parse_percentage(vtk3DSImporter *importer)
1005 {
1006 vtk3DSChunk chunk;
1007 float percent = 0.0;
1008
1009 start_chunk (importer, &chunk);
1010
1011 switch (chunk.tag)
1012 {
1013 case 0x0030: percent = parse_int_percentage(importer)/100.0;
1014 break;
1015
1016 case 0x0031: percent = parse_float_percentage(importer);
1017 break;
1018
1019 default: vtkGenericWarningMacro( << "Error parsing percentage\n");
1020 }
1021
1022 end_chunk (importer, &chunk);
1023
1024 return percent;
1025 }
1026
1027
parse_int_percentage(vtk3DSImporter * importer)1028 static short parse_int_percentage(vtk3DSImporter *importer)
1029 {
1030 word percent = read_word(importer);
1031
1032 return percent;
1033 }
1034
1035
parse_float_percentage(vtk3DSImporter * importer)1036 static float parse_float_percentage(vtk3DSImporter *importer)
1037 {
1038 float percent = read_float(importer);
1039
1040 return percent;
1041 }
1042
1043
start_chunk(vtk3DSImporter * importer,vtk3DSChunk * chunk)1044 static void start_chunk (vtk3DSImporter *importer, vtk3DSChunk *chunk)
1045 {
1046 chunk->start = ftell(importer->GetFileFD());
1047 chunk->tag = peek_word(importer);
1048 chunk->length = peek_dword(importer);
1049 if (chunk->length == 0)
1050 {
1051 chunk->length = 1;
1052 }
1053 chunk->end = chunk->start + chunk->length;
1054 }
1055
1056
end_chunk(vtk3DSImporter * importer,vtk3DSChunk * chunk)1057 static void end_chunk (vtk3DSImporter *importer, vtk3DSChunk *chunk)
1058 {
1059 fseek (importer->GetFileFD(), chunk->end, 0);
1060 }
1061
1062
read_byte(vtk3DSImporter * importer)1063 static byte read_byte(vtk3DSImporter *importer)
1064 {
1065 byte data;
1066
1067 data = fgetc (importer->GetFileFD());
1068
1069 return data;
1070 }
1071
1072
read_word(vtk3DSImporter * importer)1073 static word read_word(vtk3DSImporter *importer)
1074 {
1075 word data;
1076
1077 if (fread (&data, 2, 1, importer->GetFileFD()) != 1)
1078 {
1079 vtkErrorWithObjectMacro(
1080 importer, "Pre-mature end of file in read_word\n");
1081 data = 0;
1082 }
1083 vtkByteSwap::Swap2LE ((short *) &data);
1084 return data;
1085 }
1086
peek_word(vtk3DSImporter * importer)1087 static word peek_word(vtk3DSImporter *importer)
1088 {
1089 word data;
1090
1091 if (fread (&data, 2, 1, importer->GetFileFD()) != 1)
1092 {
1093 data = 0;
1094 }
1095 vtkByteSwap::Swap2LE ((short *) &data);
1096 return data;
1097 }
1098
peek_dword(vtk3DSImporter * importer)1099 static dword peek_dword(vtk3DSImporter *importer)
1100 {
1101 dword data;
1102
1103 if (fread (&data, 4, 1, importer->GetFileFD()) != 1)
1104 {
1105 data = 0;
1106 }
1107
1108 vtkByteSwap::Swap4LE ((char *) &data);
1109 return data;
1110 }
1111
read_float(vtk3DSImporter * importer)1112 static float read_float(vtk3DSImporter *importer)
1113 {
1114 float data;
1115
1116 if (fread (&data, 4, 1, importer->GetFileFD()) != 1)
1117 {
1118 vtkErrorWithObjectMacro(
1119 importer, "Pre-mature end of file in read_float\n");
1120 data = 0;
1121 }
1122
1123 vtkByteSwap::Swap4LE ((char *) &data);
1124 return data;
1125 }
1126
1127
read_point(vtk3DSImporter * importer,vtk3DSVector v)1128 static void read_point (vtk3DSImporter *importer, vtk3DSVector v)
1129 {
1130 v[0] = read_float(importer);
1131 v[1] = read_float(importer);
1132 v[2] = read_float(importer);
1133 }
1134
1135
read_string(vtk3DSImporter * importer)1136 static char *read_string(vtk3DSImporter *importer)
1137 {
1138 static char string[80];
1139 int i;
1140
1141 for (i = 0; i < 80; i++)
1142 {
1143 string[i] = read_byte(importer);
1144
1145 if (string[i] == '\0')
1146 {
1147 break;
1148 }
1149 }
1150
1151 return string;
1152 }
1153
1154
1155
cleanup_name(char * name)1156 static void cleanup_name (char *name)
1157 {
1158 char *tmp = (char *) malloc (strlen(name)+2);
1159 int i;
1160
1161 /* Remove any leading blanks or quotes */
1162 i = 0;
1163 while ((name[i] == ' ' || name[i] == '"') && name[i] != '\0')
1164 {
1165 i++;
1166 }
1167 strcpy (tmp, &name[i]);
1168
1169 /* Remove any trailing blanks or quotes */
1170 for (i = static_cast<int>(strlen(tmp))-1; i >= 0; i--)
1171 {
1172 if (isprint(tmp[i]) && !isspace(tmp[i]) && tmp[i] != '"')
1173 {
1174 break;
1175 }
1176 else
1177 {
1178 tmp[i] = '\0';
1179 }
1180 }
1181
1182 strcpy (name, tmp);
1183
1184 /* Prefix the letter 'N' to materials that begin with a digit */
1185 if (!isdigit (name[0]))
1186 {
1187 strcpy (tmp, name);
1188 }
1189 else
1190 {
1191 tmp[0] = 'N';
1192 strcpy (&tmp[1], name);
1193 }
1194
1195 /* Replace all illegal charaters in name with underscores */
1196 for (i = 0; tmp[i] != '\0'; i++)
1197 {
1198 if (!isalnum(tmp[i]))
1199 {
1200 tmp[i] = '_';
1201 }
1202 }
1203
1204 strcpy (name, tmp);
1205
1206 free (tmp);
1207 }
1208
~vtk3DSImporter()1209 vtk3DSImporter::~vtk3DSImporter()
1210 {
1211 vtk3DSOmniLight *omniLight;
1212 vtk3DSSpotLight *spotLight;
1213
1214 // walk the light list and delete vtk objects
1215 for (omniLight = this->OmniList; omniLight != (vtk3DSOmniLight *) NULL; omniLight = (vtk3DSOmniLight *) omniLight->next)
1216 {
1217 omniLight->aLight->Delete();
1218 }
1219 VTK_LIST_KILL (this->OmniList);
1220
1221 // walk the spot light list and delete vtk objects
1222 for (spotLight = this->SpotLightList; spotLight != (vtk3DSSpotLight *) NULL;
1223 spotLight = (vtk3DSSpotLight *) spotLight->next)
1224 {
1225 spotLight->aLight->Delete();
1226 }
1227 VTK_LIST_KILL (this->SpotLightList);
1228
1229 vtk3DSCamera *camera;
1230 // walk the camera list and delete vtk objects
1231 for (camera = this->CameraList; camera != (vtk3DSCamera *) NULL;
1232 camera = (vtk3DSCamera *) camera->next)
1233 {
1234 camera->aCamera->Delete ();
1235 }
1236 VTK_LIST_KILL (this->CameraList);
1237
1238 // walk the mesh list and delete malloced datra and vtk objects
1239 vtk3DSMesh *mesh;
1240 for (mesh = this->MeshList; mesh != (vtk3DSMesh *) NULL;
1241 mesh = (vtk3DSMesh *) mesh->next)
1242 {
1243 if (mesh->anActor != NULL)
1244 {
1245 mesh->anActor->Delete ();
1246 }
1247 if (mesh->aMapper != NULL)
1248 {
1249 mesh->aMapper->Delete ();
1250 }
1251 if (mesh->aNormals != NULL)
1252 {
1253 mesh->aNormals->Delete ();
1254 }
1255 if (mesh->aStripper != NULL)
1256 {
1257 mesh->aStripper->Delete ();
1258 }
1259 if (mesh->aPoints != NULL)
1260 {
1261 mesh->aPoints->Delete ();
1262 }
1263 if (mesh->aCellArray != NULL)
1264 {
1265 mesh->aCellArray->Delete ();
1266 }
1267 if (mesh->aPolyData != NULL)
1268 {
1269 mesh->aPolyData->Delete ();
1270 }
1271 if (mesh->vertex)
1272 {
1273 free (mesh->vertex);
1274 }
1275 if (mesh->face)
1276 {
1277 free (mesh->face);
1278 }
1279 if (mesh->mtl)
1280 {
1281 free (mesh->mtl);
1282 }
1283 }
1284
1285 // then delete the list structure
1286
1287 VTK_LIST_KILL (this->MeshList);
1288 VTK_LIST_KILL (this->MaterialList);
1289
1290 // objects allocated in Material Property List
1291 vtk3DSMatProp *m;
1292 // just walk the list of material properties, deleting vtk properties
1293 for (m = this->MatPropList; m != (vtk3DSMatProp *) NULL; m = (vtk3DSMatProp *) m->next)
1294 {
1295 m->aProperty->Delete();
1296 }
1297
1298 // then delete the list structure
1299 VTK_LIST_KILL (this->MatPropList);
1300
1301 delete [] this->FileName;
1302 }
1303
PrintSelf(ostream & os,vtkIndent indent)1304 void vtk3DSImporter::PrintSelf(ostream& os, vtkIndent indent)
1305 {
1306 this->Superclass::PrintSelf(os,indent);
1307 os << indent << "File Name: "
1308 << (this->FileName ? this->FileName : "(none)") << "\n";
1309
1310 os << indent << "Compute Normals: "
1311 << (this->ComputeNormals ? "On\n" : "Off\n");
1312 }
1313
1314
1315
1316
1317
1318
1319