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.
399 lines
10 KiB
399 lines
10 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkOBJExporter.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 "vtkOBJExporter.h"
|
|
|
|
#include "vtkActorCollection.h"
|
|
#include "vtkAssemblyNode.h"
|
|
#include "vtkAssemblyPath.h"
|
|
#include "vtkCellArray.h"
|
|
#include "vtkDataSet.h"
|
|
#include "vtkFloatArray.h"
|
|
#include "vtkGeometryFilter.h"
|
|
#include "vtkMapper.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkPolyData.h"
|
|
#include "vtkProperty.h"
|
|
#include "vtkRenderWindow.h"
|
|
#include "vtkRendererCollection.h"
|
|
#include "vtkTransform.h"
|
|
|
|
vtkCxxRevisionMacro(vtkOBJExporter, "$Revision: 1.57 $");
|
|
vtkStandardNewMacro(vtkOBJExporter);
|
|
|
|
vtkOBJExporter::vtkOBJExporter()
|
|
{
|
|
this->FilePrefix = NULL;
|
|
}
|
|
|
|
vtkOBJExporter::~vtkOBJExporter()
|
|
{
|
|
if ( this->FilePrefix )
|
|
{
|
|
delete [] this->FilePrefix;
|
|
}
|
|
}
|
|
|
|
void vtkOBJExporter::WriteData()
|
|
{
|
|
vtkRenderer *ren;
|
|
FILE *fpObj, *fpMtl;
|
|
vtkActorCollection *ac;
|
|
vtkActor *anActor, *aPart;
|
|
char nameObj[80];
|
|
char nameMtl[80];
|
|
int idStart = 1;
|
|
|
|
// make sure the user specified a filename
|
|
if ( this->FilePrefix == NULL)
|
|
{
|
|
vtkErrorMacro(<< "Please specify file prefix to use");
|
|
return;
|
|
}
|
|
|
|
// first make sure there is only one renderer in this rendering window
|
|
if (this->RenderWindow->GetRenderers()->GetNumberOfItems() > 1)
|
|
{
|
|
vtkErrorMacro(<< "obj files only support on renderer per window.");
|
|
return;
|
|
}
|
|
|
|
// get the renderer
|
|
ren = this->RenderWindow->GetRenderers()->GetFirstRenderer();
|
|
|
|
// make sure it has at least one actor
|
|
if (ren->GetActors()->GetNumberOfItems() < 1)
|
|
{
|
|
vtkErrorMacro(<< "no actors found for writing .obj file.");
|
|
return;
|
|
}
|
|
|
|
// try opening the files
|
|
sprintf(nameObj,"%s.obj",this->FilePrefix);
|
|
sprintf(nameMtl,"%s.mtl",this->FilePrefix);
|
|
fpObj = fopen(nameObj,"w");
|
|
fpMtl = fopen(nameMtl,"w");
|
|
if (!fpObj || !fpMtl)
|
|
{
|
|
vtkErrorMacro(<< "unable to open .obj and .mtl files ");
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Write header
|
|
//
|
|
vtkDebugMacro("Writing wavefront files");
|
|
fprintf(fpObj,
|
|
"# wavefront obj file written by the visualization toolkit\n\n");
|
|
fprintf(fpObj, "mtllib %s\n\n", nameMtl);
|
|
fprintf(fpMtl,
|
|
"# wavefront mtl file written by the visualization toolkit\n\n");
|
|
|
|
ac = ren->GetActors();
|
|
vtkAssemblyPath *apath;
|
|
vtkCollectionSimpleIterator ait;
|
|
for (ac->InitTraversal(ait); (anActor = ac->GetNextActor(ait)); )
|
|
{
|
|
for (anActor->InitPathTraversal(); (apath=anActor->GetNextPath()); )
|
|
{
|
|
aPart=(vtkActor *)apath->GetLastNode()->GetViewProp();
|
|
this->WriteAnActor(aPart, fpObj, fpMtl, idStart);
|
|
}
|
|
}
|
|
|
|
fclose(fpObj);
|
|
fclose(fpMtl);
|
|
}
|
|
|
|
void vtkOBJExporter::WriteAnActor(vtkActor *anActor, FILE *fpObj, FILE *fpMtl,
|
|
int &idStart)
|
|
{
|
|
vtkDataSet *ds;
|
|
vtkPolyData *pd;
|
|
vtkGeometryFilter *gf = NULL;
|
|
vtkPointData *pntData;
|
|
vtkPoints *points;
|
|
vtkDataArray *normals = NULL;
|
|
vtkDataArray *tcoords;
|
|
int i, i1, i2, idNext;
|
|
vtkProperty *prop;
|
|
double *tempd;
|
|
double *p;
|
|
vtkCellArray *cells;
|
|
vtkTransform *trans = vtkTransform::New();
|
|
vtkIdType npts = 0;
|
|
vtkIdType *indx = 0;
|
|
|
|
// see if the actor has a mapper. it could be an assembly
|
|
if (anActor->GetMapper() == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// write out the material properties to the mat file
|
|
prop = anActor->GetProperty();
|
|
fprintf(fpMtl,"newmtl mtl%i\n",idStart);
|
|
tempd = prop->GetAmbientColor();
|
|
fprintf(fpMtl,"Ka %g %g %g\n",tempd[0], tempd[1], tempd[2]);
|
|
tempd = prop->GetDiffuseColor();
|
|
fprintf(fpMtl,"Kd %g %g %g\n",tempd[0], tempd[1], tempd[2]);
|
|
tempd = prop->GetSpecularColor();
|
|
fprintf(fpMtl,"Ks %g %g %g\n",tempd[0], tempd[1], tempd[2]);
|
|
fprintf(fpMtl,"Ns %g\n",prop->GetSpecularPower());
|
|
fprintf(fpMtl,"Tf %g %g %g\n",1.0 - prop->GetOpacity(),
|
|
1.0 - prop->GetOpacity(),1.0 - prop->GetOpacity());
|
|
fprintf(fpMtl,"illum 3\n\n");
|
|
|
|
// get the mappers input and matrix
|
|
ds = anActor->GetMapper()->GetInput();
|
|
// see if the mapper has an input.
|
|
if (ds == NULL)
|
|
{
|
|
return;
|
|
}
|
|
ds->Update();
|
|
trans->SetMatrix(anActor->vtkProp3D::GetMatrix());
|
|
|
|
// we really want polydata
|
|
if ( ds->GetDataObjectType() != VTK_POLY_DATA )
|
|
{
|
|
gf = vtkGeometryFilter::New();
|
|
gf->SetInput(ds);
|
|
gf->Update();
|
|
pd = gf->GetOutput();
|
|
}
|
|
else
|
|
{
|
|
pd = (vtkPolyData *)ds;
|
|
}
|
|
|
|
// write out the points
|
|
points = vtkPoints::New();
|
|
trans->TransformPoints(pd->GetPoints(),points);
|
|
for (i = 0; i < points->GetNumberOfPoints(); i++)
|
|
{
|
|
p = points->GetPoint(i);
|
|
fprintf (fpObj, "v %g %g %g\n", p[0], p[1], p[2]);
|
|
}
|
|
idNext = idStart + (int)(points->GetNumberOfPoints());
|
|
points->Delete();
|
|
|
|
// write out the point data
|
|
pntData = pd->GetPointData();
|
|
if (pntData->GetNormals())
|
|
{
|
|
normals = vtkFloatArray::New();
|
|
normals->SetNumberOfComponents(3);
|
|
trans->TransformNormals(pntData->GetNormals(),normals);
|
|
for (i = 0; i < normals->GetNumberOfTuples(); i++)
|
|
{
|
|
p = normals->GetTuple(i);
|
|
fprintf (fpObj, "vn %g %g %g\n", p[0], p[1], p[2]);
|
|
}
|
|
}
|
|
|
|
tcoords = pntData->GetTCoords();
|
|
if (tcoords)
|
|
{
|
|
for (i = 0; i < tcoords->GetNumberOfTuples(); i++)
|
|
{
|
|
p = tcoords->GetTuple(i);
|
|
fprintf (fpObj, "vt %g %g\n", p[0], p[1]);
|
|
}
|
|
}
|
|
|
|
// write out a group name and material
|
|
fprintf (fpObj, "\ng grp%i\n", idStart);
|
|
fprintf (fpObj, "usemtl mtl%i\n", idStart);
|
|
|
|
// write out verts if any
|
|
if (pd->GetNumberOfVerts() > 0)
|
|
{
|
|
cells = pd->GetVerts();
|
|
for (cells->InitTraversal(); cells->GetNextCell(npts,indx); )
|
|
{
|
|
fprintf(fpObj,"p ");
|
|
for (i = 0; i < npts; i++)
|
|
{
|
|
// treating vtkIdType as int
|
|
fprintf(fpObj,"%i ", ((int)indx[i])+idStart);
|
|
}
|
|
fprintf(fpObj,"\n");
|
|
}
|
|
}
|
|
|
|
// write out lines if any
|
|
if (pd->GetNumberOfLines() > 0)
|
|
{
|
|
cells = pd->GetLines();
|
|
for (cells->InitTraversal(); cells->GetNextCell(npts,indx); )
|
|
{
|
|
fprintf(fpObj,"l ");
|
|
if (tcoords)
|
|
{
|
|
for (i = 0; i < npts; i++)
|
|
{
|
|
// treating vtkIdType as int
|
|
fprintf(fpObj,"%i/%i ",((int)indx[i])+idStart,
|
|
((int)indx[i]) + idStart);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < npts; i++)
|
|
{
|
|
// treating vtkIdType as int
|
|
fprintf(fpObj,"%i ", ((int)indx[i])+idStart);
|
|
}
|
|
}
|
|
fprintf(fpObj,"\n");
|
|
}
|
|
}
|
|
|
|
// write out polys if any
|
|
if (pd->GetNumberOfPolys() > 0)
|
|
{
|
|
cells = pd->GetPolys();
|
|
for (cells->InitTraversal(); cells->GetNextCell(npts,indx); )
|
|
{
|
|
fprintf(fpObj,"f ");
|
|
for (i = 0; i < npts; i++)
|
|
{
|
|
if (normals)
|
|
{
|
|
if (tcoords)
|
|
{
|
|
// treating vtkIdType as int
|
|
fprintf(fpObj,"%i/%i/%i ", ((int)indx[i])+idStart,
|
|
((int)indx[i]) + idStart, ((int)indx[i]) + idStart);
|
|
}
|
|
else
|
|
{
|
|
// treating vtkIdType as int
|
|
fprintf(fpObj,"%i//%i ",((int)indx[i])+idStart,
|
|
((int)indx[i]) + idStart);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (tcoords)
|
|
{
|
|
// treating vtkIdType as int
|
|
fprintf(fpObj,"%i/%i ", ((int)indx[i])+idStart,
|
|
((int)indx[i]) + idStart);
|
|
}
|
|
else
|
|
{
|
|
// treating vtkIdType as int
|
|
fprintf(fpObj,"%i ", ((int)indx[i])+idStart);
|
|
}
|
|
}
|
|
}
|
|
fprintf(fpObj,"\n");
|
|
}
|
|
}
|
|
|
|
// write out tstrips if any
|
|
if (pd->GetNumberOfStrips() > 0)
|
|
{
|
|
cells = pd->GetStrips();
|
|
for (cells->InitTraversal(); cells->GetNextCell(npts,indx); )
|
|
{
|
|
for (i = 2; i < npts; i++)
|
|
{
|
|
if (i%2)
|
|
{
|
|
i1 = i - 1;
|
|
i2 = i - 2;
|
|
}
|
|
else
|
|
{
|
|
i1 = i - 1;
|
|
i2 = i - 2;
|
|
}
|
|
if (normals)
|
|
{
|
|
if (tcoords)
|
|
{
|
|
// treating vtkIdType as int
|
|
fprintf(fpObj,"f %i/%i/%i ", ((int)indx[i1]) + idStart,
|
|
((int)indx[i1]) + idStart, ((int)indx[i1]) + idStart);
|
|
fprintf(fpObj,"%i/%i/%i ", ((int)indx[i2])+ idStart,
|
|
((int)indx[i2]) + idStart, ((int)indx[i2]) + idStart);
|
|
fprintf(fpObj,"%i/%i/%i\n", ((int)indx[i]) + idStart,
|
|
((int)indx[i]) + idStart, ((int)indx[i]) + idStart);
|
|
}
|
|
else
|
|
{
|
|
// treating vtkIdType as int
|
|
fprintf(fpObj,"f %i//%i ", ((int)indx[i1]) + idStart,
|
|
((int)indx[i1]) + idStart);
|
|
fprintf(fpObj,"%i//%i ", ((int)indx[i2]) + idStart,
|
|
((int)indx[i2]) + idStart);
|
|
fprintf(fpObj,"%i//%i\n",((int)indx[i]) + idStart,
|
|
((int)indx[i]) + idStart);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (tcoords)
|
|
{
|
|
// treating vtkIdType as int
|
|
fprintf(fpObj,"f %i/%i ", ((int)indx[i1]) + idStart,
|
|
((int)indx[i1]) + idStart);
|
|
fprintf(fpObj,"%i/%i ", ((int)indx[i2]) + idStart,
|
|
((int)indx[i2]) + idStart);
|
|
fprintf(fpObj,"%i/%i\n", ((int)indx[i]) + idStart,
|
|
((int)indx[i]) + idStart);
|
|
}
|
|
else
|
|
{
|
|
// treating vtkIdType as int
|
|
fprintf(fpObj,"f %i %i %i\n", ((int)indx[i1]) + idStart,
|
|
((int)indx[i2]) + idStart, ((int)indx[i]) + idStart);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
idStart = idNext;
|
|
trans->Delete();
|
|
if (normals)
|
|
{
|
|
normals->Delete();
|
|
}
|
|
if (gf)
|
|
{
|
|
gf->Delete();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void vtkOBJExporter::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
if (this->FilePrefix)
|
|
{
|
|
os << indent << "FilePrefix: " << this->FilePrefix << "\n";
|
|
}
|
|
else
|
|
{
|
|
os << indent << "FilePrefix: (null)\n";
|
|
}
|
|
}
|
|
|
|
|