You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1294 lines
31 KiB
1294 lines
31 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtk3DSImporter.cxx,v $
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
#include "vtk3DSImporter.h"
|
|
|
|
#include "vtkActor.h"
|
|
#include "vtkByteSwap.h"
|
|
#include "vtkCamera.h"
|
|
#include "vtkCellArray.h"
|
|
#include "vtkLight.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPolyData.h"
|
|
#include "vtkPolyDataMapper.h"
|
|
#include "vtkPolyDataNormals.h"
|
|
#include "vtkProperty.h"
|
|
#include "vtkRenderer.h"
|
|
#include "vtkStripper.h"
|
|
|
|
vtkCxxRevisionMacro(vtk3DSImporter, "$Revision: 1.38 $");
|
|
vtkStandardNewMacro(vtk3DSImporter);
|
|
|
|
static vtk3DSColour Black = {0.0, 0.0, 0.0};
|
|
static char obj_name[80] = "";
|
|
static vtk3DSColour fog_colour = {0.0, 0.0, 0.0};
|
|
static vtk3DSColour col = {0.0, 0.0, 0.0};
|
|
static vtk3DSColour global_amb = {0.1, 0.1, 0.1};
|
|
static vtk3DSVector pos = {0.0, 0.0, 0.0};
|
|
static vtk3DSVector target = {0.0, 0.0, 0.0};
|
|
static float hotspot = -1;
|
|
static float falloff = -1;
|
|
/* Default material property */
|
|
static vtk3DSMatProp DefaultMaterial =
|
|
{ "Default", NULL,
|
|
{1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0},
|
|
70.0, // shininess
|
|
0.0, // transparency
|
|
0.0, // reflection
|
|
0,// self illumination
|
|
"", // tex_map
|
|
0.0, // tex_strength
|
|
"", // bump_map
|
|
0.0, // bump_strength
|
|
NULL};// vtkProperty
|
|
|
|
static void cleanup_name (char *);
|
|
static void list_insert (vtk3DSList **root, vtk3DSList *new_node);
|
|
static void *list_find (vtk3DSList **root, const char *name);
|
|
static void list_kill (vtk3DSList **root);
|
|
static vtk3DSMatProp *create_mprop (void);
|
|
static vtk3DSMesh *create_mesh (char *name, int vertices, int faces);
|
|
static int parse_3ds_file (vtk3DSImporter *importer);
|
|
static void parse_3ds (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
|
|
static void parse_mdata (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
|
|
static void parse_fog (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
|
|
static void parse_fog_bgnd (vtk3DSImporter *importer);
|
|
static void parse_mat_entry (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
|
|
static char *parse_mapname (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
|
|
static void parse_named_object (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
|
|
static void parse_n_tri_object (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
|
|
static void parse_point_array (vtk3DSImporter *importer, vtk3DSMesh *mesh);
|
|
static void parse_face_array (vtk3DSImporter *importer, vtk3DSMesh *mesh, vtk3DSChunk *mainchunk);
|
|
static void parse_msh_mat_group (vtk3DSImporter *importer, vtk3DSMesh *mesh);
|
|
static void parse_smooth_group (vtk3DSImporter *importer);
|
|
static void parse_mesh_matrix (vtk3DSImporter *importer, vtk3DSMesh *mesh);
|
|
static void parse_n_direct_light (vtk3DSImporter *importer, vtk3DSChunk *mainchunk);
|
|
static void parse_dl_spotlight (vtk3DSImporter *importer);
|
|
static void parse_n_camera (vtk3DSImporter *importer);
|
|
static void parse_colour (vtk3DSImporter *importer, vtk3DSColour *colour);
|
|
static void parse_colour_f (vtk3DSImporter *importer, vtk3DSColour *colour);
|
|
static void parse_colour_24 (vtk3DSImporter *importer, vtk3DSColour_24 *colour);
|
|
static float parse_percentage (vtk3DSImporter *importer);
|
|
static short parse_int_percentage (vtk3DSImporter *importer);
|
|
static float parse_float_percentage (vtk3DSImporter *importer);
|
|
static vtk3DSMaterial *update_materials (vtk3DSImporter *importer, const char *new_material, int ext);
|
|
static void start_chunk (vtk3DSImporter *importer, vtk3DSChunk *chunk);
|
|
static void end_chunk (vtk3DSImporter *importer, vtk3DSChunk *chunk);
|
|
static byte read_byte (vtk3DSImporter *importer);
|
|
static word read_word (vtk3DSImporter *importer);
|
|
static dword read_dword (vtk3DSImporter *importer);
|
|
static float read_float (vtk3DSImporter *importer);
|
|
static void read_point (vtk3DSImporter *importer, vtk3DSVector v);
|
|
static char *read_string (vtk3DSImporter *importer);
|
|
|
|
vtk3DSImporter::vtk3DSImporter ()
|
|
{
|
|
this->OmniList = NULL;
|
|
this->SpotLightList = NULL;
|
|
this->CameraList = NULL;
|
|
this->MeshList = NULL;
|
|
this->MaterialList = NULL;
|
|
this->MatPropList = NULL;
|
|
this->FileName = NULL;
|
|
this->FileFD = NULL;
|
|
this->ComputeNormals = 0;
|
|
}
|
|
|
|
int vtk3DSImporter::ImportBegin ()
|
|
{
|
|
vtkDebugMacro(<< "Opening import file as binary");
|
|
this->FileFD = fopen (this->FileName, "rb");
|
|
if (this->FileFD == NULL)
|
|
{
|
|
vtkErrorMacro(<< "Unable to open file: "<< this->FileName);
|
|
return 0;
|
|
}
|
|
return this->Read3DS ();
|
|
}
|
|
|
|
void vtk3DSImporter::ImportEnd ()
|
|
{
|
|
vtkDebugMacro(<<"Closing import file");
|
|
if ( this->FileFD != NULL )
|
|
{
|
|
fclose (this->FileFD);
|
|
}
|
|
this->FileFD = NULL;
|
|
}
|
|
|
|
int vtk3DSImporter::Read3DS ()
|
|
{
|
|
vtk3DSMatProp *aMaterial;
|
|
|
|
if (parse_3ds_file (this) == 0)
|
|
{
|
|
vtkErrorMacro (<< "Error readings .3ds file: " << this->FileName << "\n");
|
|
return 0;
|
|
}
|
|
|
|
|
|
// create a vtk3DSMatProp and fill if in with default
|
|
aMaterial = (vtk3DSMatProp *) malloc (sizeof (vtk3DSMatProp));
|
|
*aMaterial = DefaultMaterial;
|
|
aMaterial->aProperty = vtkProperty::New ();
|
|
VTK_LIST_INSERT (this->MatPropList, aMaterial);
|
|
return 1;
|
|
}
|
|
|
|
void vtk3DSImporter::ImportActors (vtkRenderer *renderer)
|
|
{
|
|
vtk3DSMatProp *material;
|
|
vtk3DSMesh *mesh;
|
|
vtkStripper *polyStripper;
|
|
vtkPolyDataNormals *polyNormals;
|
|
vtkPolyDataMapper *polyMapper;
|
|
vtkPolyData *polyData;
|
|
vtkActor *actor;
|
|
|
|
// walk the list of meshes, creating actors
|
|
for (mesh = this->MeshList; mesh != (vtk3DSMesh *) NULL;
|
|
mesh = (vtk3DSMesh *) mesh->next)
|
|
{
|
|
if (mesh->faces == 0)
|
|
{
|
|
vtkWarningMacro (<< "part " << mesh->name << " has zero faces... skipping\n");
|
|
continue;
|
|
}
|
|
|
|
polyData = this->GeneratePolyData (mesh);
|
|
mesh->aMapper = polyMapper = vtkPolyDataMapper::New ();
|
|
mesh->aStripper = polyStripper = vtkStripper::New ();
|
|
|
|
// if ComputeNormals is on, insert a vtkPolyDataNormals filter
|
|
if (this->ComputeNormals)
|
|
{
|
|
mesh->aNormals = polyNormals = vtkPolyDataNormals::New ();
|
|
polyNormals->SetInput (polyData);
|
|
polyStripper->SetInput (polyNormals->GetOutput ());
|
|
}
|
|
else
|
|
{
|
|
polyStripper->SetInput (polyData);
|
|
}
|
|
|
|
polyMapper->SetInput (polyStripper->GetOutput ());
|
|
vtkDebugMacro (<< "Importing Actor: " << mesh->name);
|
|
mesh->anActor = actor = vtkActor::New ();
|
|
actor->SetMapper (polyMapper);
|
|
material = (vtk3DSMatProp *)VTK_LIST_FIND(this->MatPropList, mesh->mtl[0]->name);
|
|
actor->SetProperty (material->aProperty);
|
|
renderer->AddActor (actor);
|
|
}
|
|
}
|
|
|
|
vtkPolyData *vtk3DSImporter::GeneratePolyData (vtk3DSMesh *mesh)
|
|
{
|
|
int i;
|
|
vtk3DSFace *face;
|
|
vtkCellArray *triangles;
|
|
vtkPoints *vertices;
|
|
vtkPolyData *polyData;
|
|
|
|
face = mesh->face;
|
|
mesh->aCellArray = triangles = vtkCellArray::New ();
|
|
triangles->Allocate(mesh->faces * 3);
|
|
for (i = 0; i < mesh->faces; i++, face++)
|
|
{
|
|
triangles->InsertNextCell (3);
|
|
triangles->InsertCellPoint (face->a);
|
|
triangles->InsertCellPoint (face->b);
|
|
triangles->InsertCellPoint (face->c);
|
|
}
|
|
|
|
mesh->aPoints = vertices = vtkPoints::New ();
|
|
vertices->Allocate(mesh->vertices);
|
|
for (i = 0; i < mesh->vertices; i++)
|
|
{
|
|
vertices->InsertPoint (i, (float *) mesh->vertex[i]);
|
|
}
|
|
mesh->aPolyData = polyData = vtkPolyData::New ();
|
|
polyData->SetPolys (triangles);
|
|
polyData->SetPoints (vertices);
|
|
|
|
return polyData;
|
|
}
|
|
|
|
void vtk3DSImporter::ImportCameras (vtkRenderer *renderer)
|
|
{
|
|
vtkCamera *aCamera;
|
|
vtk3DSCamera *camera;
|
|
|
|
// walk the list of cameras and create vtk cameras
|
|
for (camera = this->CameraList; camera != (vtk3DSCamera *) NULL; camera = (vtk3DSCamera *) camera->next)
|
|
{
|
|
camera->aCamera = aCamera = vtkCamera::New ();
|
|
aCamera->SetPosition (camera->pos[0], camera->pos[1], camera->pos[2]);
|
|
aCamera->SetFocalPoint (camera->target[0], camera->target[1], camera->target[2]);
|
|
aCamera->SetViewUp (0, 0, 1);
|
|
aCamera->SetClippingRange (.1,10000);
|
|
aCamera->Roll (camera->bank);
|
|
renderer->SetActiveCamera (aCamera);
|
|
vtkDebugMacro (<< "Importing Camera: " << camera->name);
|
|
}
|
|
}
|
|
|
|
void vtk3DSImporter::ImportLights (vtkRenderer *renderer)
|
|
{
|
|
vtk3DSOmniLight *omniLight;
|
|
vtk3DSSpotLight *spotLight;
|
|
vtkLight *aLight;
|
|
|
|
// just walk the list of omni lights, creating vtk lights
|
|
for (omniLight = this->OmniList; omniLight != (vtk3DSOmniLight *) NULL;
|
|
omniLight = (vtk3DSOmniLight *) omniLight->next)
|
|
{
|
|
omniLight->aLight = aLight = vtkLight::New ();
|
|
aLight->SetPosition (omniLight->pos[0],
|
|
omniLight->pos[1],
|
|
omniLight->pos[2]);
|
|
aLight->SetFocalPoint (0, 0, 0);
|
|
aLight->SetColor (omniLight->col.red,
|
|
omniLight->col.green,
|
|
omniLight->col.blue);
|
|
renderer->AddLight (aLight);
|
|
vtkDebugMacro (<< "Importing Omni Light: " << omniLight->name);
|
|
}
|
|
|
|
// now walk the list of spot lights, creating vtk lights
|
|
for (spotLight = this->SpotLightList; spotLight != (vtk3DSSpotLight *) NULL;
|
|
spotLight = (vtk3DSSpotLight *) spotLight->next)
|
|
{
|
|
spotLight->aLight = aLight = vtkLight::New ();
|
|
aLight->PositionalOn ();
|
|
aLight->SetPosition (spotLight->pos[0],
|
|
spotLight->pos[1],
|
|
spotLight->pos[2]);
|
|
aLight->SetFocalPoint (spotLight->target[0],
|
|
spotLight->target[1],
|
|
spotLight->target[2]);
|
|
aLight->SetColor (spotLight->col.red,
|
|
spotLight->col.green,
|
|
spotLight->col.blue);
|
|
aLight->SetConeAngle (spotLight->falloff);
|
|
renderer->AddLight (aLight);
|
|
vtkDebugMacro (<< "Importing Spot Light: " << spotLight->name);
|
|
}
|
|
}
|
|
|
|
void vtk3DSImporter::ImportProperties (vtkRenderer *vtkNotUsed(renderer))
|
|
{
|
|
float amb = 0.1, dif = 0.9;
|
|
float dist_white, dist_diff, phong, phong_size;
|
|
vtkProperty *property;
|
|
vtk3DSMatProp *m;
|
|
|
|
// just walk the list of material properties, creating vtk properties
|
|
for (m = this->MatPropList; m != (vtk3DSMatProp *) NULL; m = (vtk3DSMatProp *) m->next)
|
|
{
|
|
if (m->self_illum)
|
|
{
|
|
amb = 0.9;
|
|
dif = 0.1;
|
|
}
|
|
|
|
dist_white = fabs(1.0 - m->specular.red) +
|
|
fabs(1.0 - m->specular.green) +
|
|
fabs(1.0 - m->specular.blue);
|
|
|
|
dist_diff = fabs(m->diffuse.red - m->specular.red) +
|
|
fabs(m->diffuse.green - m->specular.green) +
|
|
fabs(m->diffuse.blue - m->specular.blue);
|
|
|
|
if (dist_diff < dist_white)
|
|
{
|
|
dif = .1; amb = .8;
|
|
}
|
|
|
|
phong_size = 0.7*m->shininess;
|
|
if (phong_size < 1.0)
|
|
{
|
|
phong_size = 1.0;
|
|
}
|
|
if (phong_size > 30.0)
|
|
{
|
|
phong = 1.0;
|
|
}
|
|
else
|
|
{
|
|
phong = phong_size/30.0;
|
|
}
|
|
property = m->aProperty;
|
|
property->SetAmbientColor(m->ambient.red, m->ambient.green, m->ambient.blue);
|
|
property->SetAmbient (amb);
|
|
property->SetDiffuseColor(m->diffuse.red, m->diffuse.green, m->diffuse.blue);
|
|
property->SetDiffuse (dif);
|
|
property->SetSpecularColor(m->specular.red, m->specular.green, m->specular.blue);
|
|
property->SetSpecular (phong);
|
|
property->SetSpecularPower(phong_size);
|
|
property->SetOpacity(1.0 - m->transparency);
|
|
vtkDebugMacro(<< "Importing Property: " << m->name);
|
|
|
|
m->aProperty = property;
|
|
}
|
|
}
|
|
|
|
/* Insert a new node into the list */
|
|
static void list_insert (vtk3DSList **root, vtk3DSList *new_node)
|
|
{
|
|
new_node->next = *root;
|
|
*root = new_node;
|
|
}
|
|
|
|
|
|
/* Find the node with the specified name */
|
|
static void *list_find (vtk3DSList **root, const char *name)
|
|
{
|
|
vtk3DSList *p;
|
|
for (p = *root; p != (vtk3DSList *) NULL; p = (vtk3DSList *) p->next)
|
|
{
|
|
if (strcmp (p->name, name) == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return (void *)p;
|
|
}
|
|
|
|
/* Delete the entire list */
|
|
static void list_kill (vtk3DSList **root)
|
|
{
|
|
vtk3DSList *temp;
|
|
|
|
while (*root != (vtk3DSList *) NULL)
|
|
{
|
|
temp = *root;
|
|
*root = (vtk3DSList *) (*root)->next;
|
|
free (temp);
|
|
}
|
|
}
|
|
|
|
/* Add a new material to the material list */
|
|
static vtk3DSMaterial *update_materials (vtk3DSImporter *importer, const char *new_material, int ext)
|
|
{
|
|
vtk3DSMaterial *p;
|
|
|
|
p = (vtk3DSMaterial *) VTK_LIST_FIND (importer->MaterialList, new_material);
|
|
|
|
if (p == NULL)
|
|
{
|
|
p = (vtk3DSMaterial *) malloc (sizeof (*p));
|
|
strcpy (p->name, new_material);
|
|
p->external = ext;
|
|
VTK_LIST_INSERT (importer->MaterialList, p);
|
|
}
|
|
return p;
|
|
}
|
|
|
|
|
|
static vtk3DSMatProp *create_mprop()
|
|
{
|
|
vtk3DSMatProp *new_mprop;
|
|
|
|
new_mprop = (vtk3DSMatProp *) malloc (sizeof(*new_mprop));
|
|
strcpy (new_mprop->name, "");
|
|
new_mprop->ambient = Black;
|
|
new_mprop->diffuse = Black;
|
|
new_mprop->specular = Black;
|
|
new_mprop->shininess = 0.0;
|
|
new_mprop->transparency = 0.0;
|
|
new_mprop->reflection = 0.0;
|
|
new_mprop->self_illum = 0;
|
|
|
|
strcpy (new_mprop->tex_map, "");
|
|
new_mprop->tex_strength = 0.0;
|
|
|
|
strcpy (new_mprop->bump_map, "");
|
|
new_mprop->bump_strength = 0.0;
|
|
|
|
new_mprop->aProperty = vtkProperty::New ();
|
|
return new_mprop;
|
|
}
|
|
|
|
|
|
/* Create a new mesh */
|
|
static vtk3DSMesh *create_mesh (char *name, int vertices, int faces)
|
|
{
|
|
vtk3DSMesh *new_mesh;
|
|
|
|
new_mesh = (vtk3DSMesh *) malloc (sizeof(*new_mesh));
|
|
strcpy (new_mesh->name, name);
|
|
|
|
new_mesh->vertices = vertices;
|
|
|
|
if (vertices <= 0)
|
|
{
|
|
new_mesh->vertex = NULL;
|
|
}
|
|
else
|
|
{
|
|
new_mesh->vertex = (vtk3DSVector *) malloc(vertices * sizeof(*new_mesh->vertex));
|
|
}
|
|
|
|
new_mesh->faces = faces;
|
|
|
|
if (faces <= 0)
|
|
{
|
|
new_mesh->face = NULL;
|
|
new_mesh->mtl = NULL;
|
|
}
|
|
else
|
|
{
|
|
new_mesh->face = (vtk3DSFace *) malloc (faces * sizeof(*new_mesh->face));
|
|
new_mesh->mtl = (vtk3DSMaterial **) malloc (faces * sizeof(*new_mesh->mtl));
|
|
}
|
|
|
|
new_mesh->hidden = 0;
|
|
new_mesh->shadow = 1;
|
|
|
|
new_mesh->anActor = NULL;
|
|
new_mesh->aMapper = NULL;
|
|
new_mesh->aNormals = NULL;
|
|
new_mesh->aStripper = NULL;
|
|
new_mesh->aPoints = NULL;
|
|
new_mesh->aCellArray = NULL;
|
|
new_mesh->aPolyData = NULL;
|
|
return new_mesh;
|
|
}
|
|
|
|
|
|
static int parse_3ds_file(vtk3DSImporter *importer)
|
|
{
|
|
vtk3DSChunk chunk;
|
|
|
|
start_chunk(importer, &chunk);
|
|
|
|
if (chunk.tag == 0x4D4D)
|
|
{
|
|
parse_3ds (importer, &chunk);
|
|
}
|
|
else
|
|
{
|
|
vtkGenericWarningMacro(<< "Error: Input file is not .3DS format\n");
|
|
return 0;
|
|
}
|
|
|
|
end_chunk (importer, &chunk);
|
|
return 1;
|
|
}
|
|
|
|
static void parse_3ds (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
|
|
{
|
|
vtk3DSChunk chunk;
|
|
|
|
do
|
|
{
|
|
start_chunk (importer, &chunk);
|
|
|
|
if (chunk.end <= mainchunk->end)
|
|
{
|
|
switch (chunk.tag)
|
|
{
|
|
case 0x3D3D: parse_mdata (importer, &chunk);
|
|
break;
|
|
}
|
|
}
|
|
end_chunk (importer, &chunk);
|
|
} while (chunk.end <= mainchunk->end);
|
|
}
|
|
|
|
|
|
static void parse_mdata (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
|
|
{
|
|
vtk3DSChunk chunk;
|
|
vtk3DSColour bgnd_colour;
|
|
|
|
do
|
|
{
|
|
start_chunk (importer, &chunk);
|
|
|
|
if (chunk.end <= mainchunk->end)
|
|
{
|
|
switch (chunk.tag)
|
|
{
|
|
case 0x2100: parse_colour (importer, &global_amb);
|
|
break;
|
|
case 0x1200: parse_colour (importer, &bgnd_colour);
|
|
break;
|
|
case 0x2200: parse_fog (importer, &chunk);
|
|
break;
|
|
case 0x2210: parse_fog_bgnd(importer);
|
|
break;
|
|
case 0xAFFF: parse_mat_entry (importer, &chunk);
|
|
break;
|
|
case 0x4000: parse_named_object (importer, &chunk);
|
|
break;
|
|
}
|
|
}
|
|
|
|
end_chunk (importer, &chunk);
|
|
} while (chunk.end <= mainchunk->end);
|
|
}
|
|
|
|
|
|
static void parse_fog (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
|
|
{
|
|
vtk3DSChunk chunk;
|
|
|
|
(void)read_float(importer);
|
|
(void)read_float(importer);
|
|
(void) read_float(importer);
|
|
(void)read_float(importer);
|
|
|
|
parse_colour (importer, &fog_colour);
|
|
|
|
do
|
|
{
|
|
start_chunk (importer, &chunk);
|
|
|
|
if (chunk.end <= mainchunk->end)
|
|
{
|
|
switch (chunk.tag)
|
|
{
|
|
case 0x2210: parse_fog_bgnd(importer);
|
|
break;
|
|
}
|
|
}
|
|
|
|
end_chunk (importer, &chunk);
|
|
} while (chunk.end <= mainchunk->end);
|
|
}
|
|
|
|
|
|
static void parse_fog_bgnd(vtk3DSImporter *vtkNotUsed(importer))
|
|
{
|
|
}
|
|
|
|
|
|
static void parse_mat_entry (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
|
|
{
|
|
vtk3DSChunk chunk;
|
|
vtk3DSMatProp *mprop;
|
|
|
|
mprop = create_mprop();
|
|
|
|
do
|
|
{
|
|
start_chunk (importer, &chunk);
|
|
if (chunk.end <= mainchunk->end)
|
|
{
|
|
switch (chunk.tag)
|
|
{
|
|
case 0xA000: strcpy (mprop->name, read_string(importer));
|
|
cleanup_name (mprop->name);
|
|
break;
|
|
|
|
case 0xA010: parse_colour (importer, &mprop->ambient);
|
|
break;
|
|
|
|
case 0xA020: parse_colour (importer, &mprop->diffuse);
|
|
break;
|
|
|
|
case 0xA030: parse_colour (importer, &mprop->specular);
|
|
break;
|
|
|
|
case 0xA040: mprop->shininess = 100.0*parse_percentage(importer);
|
|
break;
|
|
|
|
case 0xA050: mprop->transparency = parse_percentage(importer);
|
|
break;
|
|
|
|
case 0xA080: mprop->self_illum = 1;
|
|
break;
|
|
|
|
case 0xA220: mprop->reflection = parse_percentage(importer);
|
|
(void)parse_mapname (importer, &chunk);
|
|
break;
|
|
|
|
case 0xA310: if (mprop->reflection == 0.0)
|
|
{
|
|
mprop->reflection = 1.0;
|
|
}
|
|
break;
|
|
|
|
case 0xA200: mprop->tex_strength = parse_percentage(importer);
|
|
strcpy (mprop->tex_map, parse_mapname (importer, &chunk));
|
|
break;
|
|
|
|
case 0xA230: mprop->bump_strength = parse_percentage(importer);
|
|
strcpy (mprop->bump_map, parse_mapname (importer, &chunk));
|
|
break;
|
|
}
|
|
}
|
|
|
|
end_chunk (importer, &chunk);
|
|
} while (chunk.end <= mainchunk->end);
|
|
|
|
VTK_LIST_INSERT (importer->MatPropList, mprop);
|
|
}
|
|
|
|
|
|
static char *parse_mapname (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
|
|
{
|
|
static char name[80] = "";
|
|
vtk3DSChunk chunk;
|
|
|
|
do
|
|
{
|
|
start_chunk (importer, &chunk);
|
|
|
|
if (chunk.end <= mainchunk->end)
|
|
{
|
|
switch (chunk.tag)
|
|
{
|
|
case 0xA300: strcpy (name, read_string(importer));
|
|
break;
|
|
}
|
|
}
|
|
|
|
end_chunk (importer, &chunk);
|
|
} while (chunk.end <= mainchunk->end);
|
|
|
|
return name;
|
|
}
|
|
|
|
|
|
static void parse_named_object (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
|
|
{
|
|
vtk3DSMesh *mesh;
|
|
vtk3DSChunk chunk;
|
|
|
|
strcpy (obj_name, read_string(importer));
|
|
cleanup_name (obj_name);
|
|
|
|
mesh = NULL;
|
|
|
|
do
|
|
{
|
|
start_chunk (importer, &chunk);
|
|
if (chunk.end <= mainchunk->end)
|
|
{
|
|
switch (chunk.tag)
|
|
{
|
|
case 0x4100: parse_n_tri_object (importer, &chunk);
|
|
break;
|
|
case 0x4600: parse_n_direct_light (importer, &chunk);
|
|
break;
|
|
case 0x4700: parse_n_camera(importer);
|
|
break;
|
|
case 0x4010: if (mesh != NULL)
|
|
{
|
|
mesh->hidden = 1;
|
|
}
|
|
break;
|
|
case 0x4012: if (mesh != NULL)
|
|
{
|
|
mesh->shadow = 0;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
end_chunk (importer, &chunk);
|
|
} while (chunk.end <= mainchunk->end);
|
|
|
|
}
|
|
|
|
static void parse_n_tri_object (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
|
|
{
|
|
vtk3DSMesh *mesh;
|
|
vtk3DSChunk chunk;
|
|
|
|
mesh = create_mesh (obj_name, 0, 0);
|
|
|
|
do
|
|
{
|
|
start_chunk (importer, &chunk);
|
|
|
|
if (chunk.end <= mainchunk->end)
|
|
{
|
|
switch (chunk.tag)
|
|
{
|
|
case 0x4110: parse_point_array(importer, mesh);
|
|
break;
|
|
case 0x4120: parse_face_array (importer, mesh, &chunk);
|
|
break;
|
|
case 0x4160: parse_mesh_matrix(importer, mesh);
|
|
break;
|
|
}
|
|
}
|
|
|
|
end_chunk (importer, &chunk);
|
|
} while (chunk.end <= mainchunk->end);
|
|
|
|
VTK_LIST_INSERT (importer->MeshList, mesh);
|
|
}
|
|
|
|
|
|
static void parse_point_array(vtk3DSImporter *importer, vtk3DSMesh *mesh)
|
|
{
|
|
int i;
|
|
|
|
mesh->vertices = read_word(importer);
|
|
mesh->vertex = (vtk3DSVector *) malloc (mesh->vertices * sizeof(*(mesh->vertex)));
|
|
for (i = 0; i < mesh->vertices; i++)
|
|
{
|
|
read_point (importer, mesh->vertex[i]);
|
|
}
|
|
}
|
|
|
|
static void parse_face_array (vtk3DSImporter *importer, vtk3DSMesh *mesh, vtk3DSChunk *mainchunk)
|
|
{
|
|
vtk3DSChunk chunk;
|
|
int i;
|
|
|
|
mesh->faces = read_word(importer);
|
|
mesh->face = (vtk3DSFace *) malloc (mesh->faces * sizeof(*(mesh->face)));
|
|
mesh->mtl = (vtk3DSMaterial **) malloc (mesh->faces * sizeof(*(mesh->mtl)));
|
|
|
|
for (i = 0; i < mesh->faces; i++)
|
|
{
|
|
mesh->face[i].a = read_word(importer);
|
|
mesh->face[i].b = read_word(importer);
|
|
mesh->face[i].c = read_word(importer);
|
|
(void)read_word(importer);
|
|
|
|
mesh->mtl[i] = NULL;
|
|
}
|
|
|
|
do
|
|
{
|
|
start_chunk (importer, &chunk);
|
|
if (chunk.end <= mainchunk->end)
|
|
{
|
|
switch (chunk.tag)
|
|
{
|
|
case 0x4130: parse_msh_mat_group(importer, mesh);
|
|
break;
|
|
case 0x4150: parse_smooth_group(importer);
|
|
break;
|
|
}
|
|
}
|
|
|
|
end_chunk (importer, &chunk);
|
|
} while (chunk.end <= mainchunk->end);
|
|
|
|
for (i = 0; i < mesh->faces; i++)
|
|
{
|
|
if (mesh->mtl[i] == (vtk3DSMaterial *) NULL)
|
|
{
|
|
mesh->mtl[i] = update_materials (importer, "Default", 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void parse_msh_mat_group(vtk3DSImporter *importer, vtk3DSMesh *mesh)
|
|
{
|
|
vtk3DSMaterial *new_mtl;
|
|
char mtlname[80];
|
|
int mtlcnt;
|
|
int i, face;
|
|
|
|
strcpy (mtlname, read_string(importer));
|
|
cleanup_name (mtlname);
|
|
|
|
new_mtl = update_materials (importer, mtlname, 0);
|
|
|
|
mtlcnt = read_word(importer);
|
|
|
|
for (i = 0; i < mtlcnt; i++)
|
|
{
|
|
face = read_word(importer);
|
|
mesh->mtl[face] = new_mtl;
|
|
}
|
|
}
|
|
|
|
static void parse_smooth_group(vtk3DSImporter *vtkNotUsed(importer))
|
|
{
|
|
}
|
|
|
|
static void parse_mesh_matrix(vtk3DSImporter *vtkNotUsed(importer), vtk3DSMesh *vtkNotUsed(mesh))
|
|
{
|
|
// vtkGenericWarningMacro(<< "mesh matrix detected but not used\n");
|
|
}
|
|
|
|
|
|
static void parse_n_direct_light (vtk3DSImporter *importer, vtk3DSChunk *mainchunk)
|
|
{
|
|
vtk3DSChunk chunk;
|
|
vtk3DSSpotLight *s;
|
|
vtk3DSOmniLight *o;
|
|
int spot_flag = 0;
|
|
|
|
read_point (importer, pos);
|
|
parse_colour (importer, &col);
|
|
|
|
do
|
|
{
|
|
start_chunk (importer, &chunk);
|
|
|
|
if (chunk.end <= mainchunk->end)
|
|
{
|
|
switch (chunk.tag)
|
|
{
|
|
case 0x4620: break;
|
|
case 0x4610: parse_dl_spotlight(importer);
|
|
spot_flag = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
end_chunk (importer, &chunk);
|
|
} while (chunk.end <= mainchunk->end);
|
|
|
|
if (!spot_flag)
|
|
{
|
|
o = (vtk3DSOmniLight *) VTK_LIST_FIND (importer->OmniList, obj_name);
|
|
|
|
if (o != NULL)
|
|
{
|
|
pos[0] = o->pos[0];
|
|
pos[1] = o->pos[1];
|
|
pos[2] = o->pos[2];
|
|
col = o->col;
|
|
}
|
|
else
|
|
{
|
|
o = (vtk3DSOmniLight *) malloc (sizeof (*o));
|
|
o->pos[0] = pos[0];
|
|
o->pos[1] = pos[1];
|
|
o->pos[2] = pos[2];
|
|
o->col = col ;
|
|
strcpy (o->name, obj_name);
|
|
VTK_LIST_INSERT (importer->OmniList, o);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s = (vtk3DSSpotLight *) VTK_LIST_FIND (importer->SpotLightList, obj_name);
|
|
|
|
if (s != NULL)
|
|
{
|
|
pos[0] = s->pos[0];
|
|
pos[1] = s->pos[1];
|
|
pos[2] = s->pos[2];
|
|
target[0] = s->target[0];
|
|
target[1] = s->target[1];
|
|
target[2] = s->target[2];
|
|
col = s->col;
|
|
hotspot = s->hotspot;
|
|
falloff = s->falloff;
|
|
}
|
|
else
|
|
{
|
|
if (falloff <= 0.0)
|
|
{
|
|
falloff = 180.0;
|
|
}
|
|
if (hotspot <= 0.0)
|
|
{
|
|
hotspot = 0.7*falloff;
|
|
}
|
|
s = (vtk3DSSpotLight *) malloc (sizeof (*s));
|
|
s->pos[0] = pos[0];
|
|
s->pos[1] = pos[1];
|
|
s->pos[2] = pos[2];
|
|
s->target[0] = target[0];
|
|
s->target[1] = target[1];
|
|
s->target[2] = target[2];
|
|
s->col = col ;
|
|
s->hotspot = hotspot;
|
|
s->falloff = falloff;
|
|
strcpy (s->name, obj_name);
|
|
VTK_LIST_INSERT (importer->SpotLightList, s);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void parse_dl_spotlight(vtk3DSImporter *importer)
|
|
{
|
|
read_point (importer, target);
|
|
|
|
hotspot = read_float(importer);
|
|
falloff = read_float(importer);
|
|
}
|
|
|
|
|
|
static void parse_n_camera(vtk3DSImporter *importer)
|
|
{
|
|
float bank;
|
|
float lens;
|
|
vtk3DSCamera *c = (vtk3DSCamera *) malloc (sizeof (vtk3DSCamera));
|
|
|
|
read_point (importer, pos);
|
|
read_point (importer, target);
|
|
bank = read_float(importer);
|
|
lens = read_float(importer);
|
|
|
|
strcpy (c->name, obj_name);
|
|
c->pos[0] = pos[0];
|
|
c->pos[1] = pos[1];
|
|
c->pos[2] = pos[2];
|
|
c->target[0] = target[0];
|
|
c->target[1] = target[1];
|
|
c->target[2] = target[2];
|
|
c->lens = lens;
|
|
c->bank = bank;
|
|
|
|
VTK_LIST_INSERT (importer->CameraList, c);
|
|
}
|
|
|
|
static void parse_colour (vtk3DSImporter *importer, vtk3DSColour *colour)
|
|
{
|
|
vtk3DSChunk chunk;
|
|
vtk3DSColour_24 colour_24;
|
|
|
|
start_chunk (importer, &chunk);
|
|
|
|
switch (chunk.tag)
|
|
{
|
|
case 0x0010: parse_colour_f (importer, colour);
|
|
break;
|
|
|
|
case 0x0011: parse_colour_24 (importer, &colour_24);
|
|
colour->red = colour_24.red/255.0;
|
|
colour->green = colour_24.green/255.0;
|
|
colour->blue = colour_24.blue/255.0;
|
|
break;
|
|
|
|
default: vtkGenericWarningMacro(<< "Error parsing colour");
|
|
}
|
|
|
|
end_chunk (importer, &chunk);
|
|
}
|
|
|
|
|
|
static void parse_colour_f (vtk3DSImporter *importer, vtk3DSColour *colour)
|
|
{
|
|
colour->red = read_float(importer);
|
|
colour->green = read_float(importer);
|
|
colour->blue = read_float(importer);
|
|
}
|
|
|
|
|
|
static void parse_colour_24 (vtk3DSImporter *importer, vtk3DSColour_24 *colour)
|
|
{
|
|
colour->red = read_byte(importer);
|
|
colour->green = read_byte(importer);
|
|
colour->blue = read_byte(importer);
|
|
}
|
|
|
|
|
|
static float parse_percentage(vtk3DSImporter *importer)
|
|
{
|
|
vtk3DSChunk chunk;
|
|
float percent = 0.0;
|
|
|
|
start_chunk (importer, &chunk);
|
|
|
|
switch (chunk.tag)
|
|
{
|
|
case 0x0030: percent = parse_int_percentage(importer)/100.0;
|
|
break;
|
|
|
|
case 0x0031: percent = parse_float_percentage(importer);
|
|
break;
|
|
|
|
default: vtkGenericWarningMacro( << "Error parsing percentage\n");
|
|
}
|
|
|
|
end_chunk (importer, &chunk);
|
|
|
|
return percent;
|
|
}
|
|
|
|
|
|
static short parse_int_percentage(vtk3DSImporter *importer)
|
|
{
|
|
word percent = read_word(importer);
|
|
|
|
return percent;
|
|
}
|
|
|
|
|
|
static float parse_float_percentage(vtk3DSImporter *importer)
|
|
{
|
|
float percent = read_float(importer);
|
|
|
|
return percent;
|
|
}
|
|
|
|
|
|
static void start_chunk (vtk3DSImporter *importer, vtk3DSChunk *chunk)
|
|
{
|
|
chunk->start = ftell(importer->GetFileFD());
|
|
chunk->tag = read_word(importer);
|
|
chunk->length = read_dword(importer);
|
|
if (chunk->length == 0)
|
|
{
|
|
chunk->length = 1;
|
|
}
|
|
chunk->end = chunk->start + chunk->length;
|
|
}
|
|
|
|
|
|
static void end_chunk (vtk3DSImporter *importer, vtk3DSChunk *chunk)
|
|
{
|
|
fseek (importer->GetFileFD(), chunk->end, 0);
|
|
}
|
|
|
|
|
|
static byte read_byte(vtk3DSImporter *importer)
|
|
{
|
|
byte data;
|
|
|
|
data = fgetc (importer->GetFileFD());
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
static word read_word(vtk3DSImporter *importer)
|
|
{
|
|
word data;
|
|
|
|
fread (&data, 2, 1, importer->GetFileFD());
|
|
vtkByteSwap::Swap2LE ((short *) &data);
|
|
/* swab ((char *) &data, (char *) &sdata, 2);*/
|
|
|
|
return data;
|
|
}
|
|
|
|
static dword read_dword(vtk3DSImporter *importer)
|
|
{
|
|
dword data;
|
|
|
|
if (fread (&data, 4, 1, importer->GetFileFD()) != 1)
|
|
{
|
|
// vtkGenericWarningMacro(<<"Pre-mature end of file in read_dword\n");
|
|
data = 0;
|
|
}
|
|
|
|
vtkByteSwap::Swap4LE ((char *) &data);
|
|
return data;
|
|
}
|
|
|
|
|
|
static float read_float(vtk3DSImporter *importer)
|
|
{
|
|
float data;
|
|
|
|
fread (&data, 4, 1, importer->GetFileFD());
|
|
vtkByteSwap::Swap4LE ((char *) &data);
|
|
/* TIFFSwabLong (&data);*/
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
static void read_point (vtk3DSImporter *importer, vtk3DSVector v)
|
|
{
|
|
v[0] = read_float(importer);
|
|
v[1] = read_float(importer);
|
|
v[2] = read_float(importer);
|
|
}
|
|
|
|
|
|
static char *read_string(vtk3DSImporter *importer)
|
|
{
|
|
static char string[80];
|
|
int i;
|
|
|
|
for (i = 0; i < 80; i++)
|
|
{
|
|
string[i] = read_byte(importer);
|
|
|
|
if (string[i] == '\0')
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return string;
|
|
}
|
|
|
|
|
|
|
|
static void cleanup_name (char *name)
|
|
{
|
|
char *tmp = (char *) malloc (strlen(name)+2);
|
|
int i;
|
|
|
|
/* Remove any leading blanks or quotes */
|
|
i = 0;
|
|
while ((name[i] == ' ' || name[i] == '"') && name[i] != '\0')
|
|
{
|
|
i++;
|
|
}
|
|
strcpy (tmp, &name[i]);
|
|
|
|
/* Remove any trailing blanks or quotes */
|
|
for (i = static_cast<int>(strlen(tmp))-1; i >= 0; i--)
|
|
{
|
|
if (isprint(tmp[i]) && !isspace(tmp[i]) && tmp[i] != '"')
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
tmp[i] = '\0';
|
|
}
|
|
}
|
|
|
|
strcpy (name, tmp);
|
|
|
|
/* Prefix the letter 'N' to materials that begin with a digit */
|
|
if (!isdigit (name[0]))
|
|
{
|
|
strcpy (tmp, name);
|
|
}
|
|
else
|
|
{
|
|
tmp[0] = 'N';
|
|
strcpy (&tmp[1], name);
|
|
}
|
|
|
|
/* Replace all illegal charaters in name with underscores */
|
|
for (i = 0; tmp[i] != '\0'; i++)
|
|
{
|
|
if (!isalnum(tmp[i]))
|
|
{
|
|
tmp[i] = '_';
|
|
}
|
|
}
|
|
|
|
strcpy (name, tmp);
|
|
|
|
free (tmp);
|
|
}
|
|
|
|
vtk3DSImporter::~vtk3DSImporter()
|
|
{
|
|
vtk3DSOmniLight *omniLight;
|
|
vtk3DSSpotLight *spotLight;
|
|
|
|
// walk the light list and delete vtk objects
|
|
for (omniLight = this->OmniList; omniLight != (vtk3DSOmniLight *) NULL; omniLight = (vtk3DSOmniLight *) omniLight->next)
|
|
{
|
|
omniLight->aLight->Delete();
|
|
}
|
|
VTK_LIST_KILL (this->OmniList);
|
|
|
|
// walk the spot light list and delete vtk objects
|
|
for (spotLight = this->SpotLightList; spotLight != (vtk3DSSpotLight *) NULL;
|
|
spotLight = (vtk3DSSpotLight *) spotLight->next)
|
|
{
|
|
spotLight->aLight->Delete();
|
|
}
|
|
VTK_LIST_KILL (this->SpotLightList);
|
|
|
|
vtk3DSCamera *camera;
|
|
// walk the camera list and delete vtk objects
|
|
for (camera = this->CameraList; camera != (vtk3DSCamera *) NULL;
|
|
camera = (vtk3DSCamera *) camera->next)
|
|
{
|
|
camera->aCamera->Delete ();
|
|
}
|
|
VTK_LIST_KILL (this->CameraList);
|
|
|
|
// walk the mesh list and delete malloced datra and vtk objects
|
|
vtk3DSMesh *mesh;
|
|
for (mesh = this->MeshList; mesh != (vtk3DSMesh *) NULL;
|
|
mesh = (vtk3DSMesh *) mesh->next)
|
|
{
|
|
if (mesh->anActor != NULL)
|
|
{
|
|
mesh->anActor->Delete ();
|
|
}
|
|
if (mesh->aMapper != NULL)
|
|
{
|
|
mesh->aMapper->Delete ();
|
|
}
|
|
if (mesh->aNormals != NULL)
|
|
{
|
|
mesh->aNormals->Delete ();
|
|
}
|
|
if (mesh->aStripper != NULL)
|
|
{
|
|
mesh->aStripper->Delete ();
|
|
}
|
|
if (mesh->aPoints != NULL)
|
|
{
|
|
mesh->aPoints->Delete ();
|
|
}
|
|
if (mesh->aCellArray != NULL)
|
|
{
|
|
mesh->aCellArray->Delete ();
|
|
}
|
|
if (mesh->aPolyData != NULL)
|
|
{
|
|
mesh->aPolyData->Delete ();
|
|
}
|
|
if (mesh->vertex)
|
|
{
|
|
free (mesh->vertex);
|
|
}
|
|
if (mesh->face)
|
|
{
|
|
free (mesh->face);
|
|
}
|
|
if (mesh->mtl)
|
|
{
|
|
free (mesh->mtl);
|
|
}
|
|
}
|
|
|
|
// then delete the list structure
|
|
|
|
VTK_LIST_KILL (this->MeshList);
|
|
VTK_LIST_KILL (this->MaterialList);
|
|
|
|
// objects allocated in Material Property List
|
|
vtk3DSMatProp *m;
|
|
// just walk the list of material properties, deleting vtk properties
|
|
for (m = this->MatPropList; m != (vtk3DSMatProp *) NULL; m = (vtk3DSMatProp *) m->next)
|
|
{
|
|
m->aProperty->Delete();
|
|
}
|
|
|
|
// then delete the list structure
|
|
VTK_LIST_KILL (this->MatPropList);
|
|
|
|
if (this->FileName)
|
|
{
|
|
delete [] this->FileName;
|
|
}
|
|
}
|
|
|
|
void vtk3DSImporter::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
os << indent << "File Name: "
|
|
<< (this->FileName ? this->FileName : "(none)") << "\n";
|
|
|
|
os << indent << "Compute Normals: "
|
|
<< (this->ComputeNormals ? "On\n" : "Off\n");
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|