/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkIVExporter.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 "vtkIVExporter.h" #include "vtkAssemblyNode.h" #include "vtkAssemblyPath.h" #include "vtkCamera.h" #include "vtkCellArray.h" #include "vtkGeometryFilter.h" #include "vtkImageData.h" #include "vtkLight.h" #include "vtkLightCollection.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkProperty.h" #include "vtkRenderWindow.h" #include "vtkRendererCollection.h" #include "vtkTexture.h" #include "vtkTransform.h" #include "vtkUnsignedCharArray.h" vtkCxxRevisionMacro(vtkIVExporter, "$Revision: 1.62 $"); vtkStandardNewMacro(vtkIVExporter); vtkIVExporter::vtkIVExporter() { this->FileName = NULL; } vtkIVExporter::~vtkIVExporter() { if ( this->FileName ) { delete [] this->FileName; } } static char indent[256]; int indent_now = 0; #define VTK_INDENT_MORE { indent[indent_now] = ' '; \ indent_now += 4; \ indent[indent_now] = 0; } #define VTK_INDENT_LESS { indent[indent_now] = ' '; \ indent_now -= 4; \ indent[indent_now] = 0; } void vtkIVExporter::WriteData() { vtkRenderer *ren; FILE *fp; vtkActorCollection *ac; vtkActor *anActor, *aPart; vtkLightCollection *lc; vtkLight *aLight; vtkCamera *cam; double *tempd; for (int i=0;i<256;i++) { indent[i] = ' '; } indent[indent_now] = 0; // make sure the user specified a filename if ( this->FileName == NULL) { vtkErrorMacro(<< "Please specify FileName to use"); return; } // first make sure there is only one renderer in this rendering window if (this->RenderWindow->GetRenderers()->GetNumberOfItems() > 1) { vtkErrorMacro(<< "OpenInventor files only support one 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 OpenInventor file."); return; } // try opening the files fp = fopen(this->FileName,"w"); if (!fp) { vtkErrorMacro(<< "unable to open OpenInventor file " << this->FileName); return; } // // Write header // vtkDebugMacro("Writing OpenInventor file"); fprintf(fp,"#Inventor V2.0 ascii\n"); fprintf(fp,"# OpenInventor file written by the visualization toolkit\n\n"); fprintf(fp, "Separator {\n"); VTK_INDENT_MORE; // do the camera cam = ren->GetActiveCamera(); if (cam->GetParallelProjection()) { fprintf(fp,"%sOrthographicCamera\n%s{\n", indent, indent); } else { // this assumes the aspect ratio is 1 fprintf(fp,"%sPerspectiveCamera\n%s{\n%s heightAngle %f\n", indent, indent, indent, cam->GetViewAngle()*3.1415926/180.0); } VTK_INDENT_MORE; fprintf(fp,"%snearDistance %f\n",indent, cam->GetClippingRange()[0]); fprintf(fp,"%sfarDistance %f\n",indent, cam->GetClippingRange()[1]); fprintf(fp,"%sfocalDistance %f\n",indent, cam->GetDistance()); fprintf(fp,"%sposition %f %f %f\n", indent, cam->GetPosition()[0], cam->GetPosition()[1], cam->GetPosition()[2]); tempd = cam->GetOrientationWXYZ(); fprintf(fp,"%sorientation %g %g %g %g\n%s}\n", indent, tempd[1], tempd[2], tempd[3], tempd[0]*3.1415926/180.0, indent); VTK_INDENT_LESS; // do the lights first the ambient then the others fprintf(fp,"# The following environment information is disabled\n"); fprintf(fp,"# because a popular viewer (Template Graphics Software SceneViewer) has\n"); fprintf(fp,"# trouble (access violations under Windows NT) with it.\n"); fprintf(fp,"#%sEnvironment {\n", indent); // couldn't figure out a way to do headlight -- seems to be a property of the // viewer not the model VTK_INDENT_MORE; fprintf(fp,"#%sambientIntensity 1.0 # ambient light\n", indent); fprintf(fp,"#%sambientColor %f %f %f }\n\n", indent, ren->GetAmbient()[0], ren->GetAmbient()[1], ren->GetAmbient()[2]); VTK_INDENT_LESS; // make sure we have a default light // if we dont then use a headlight lc = ren->GetLights(); vtkCollectionSimpleIterator lsit; for (lc->InitTraversal(lsit); (aLight = lc->GetNextLight(lsit)); ) { this->WriteALight(aLight, fp); } // do the actors now 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, fp); } } VTK_INDENT_LESS; fprintf(fp, "}\n"); // close Separator fclose(fp); } void vtkIVExporter::WriteALight(vtkLight *aLight, FILE *fp) { double *pos, *focus, *color; float dir[3]; pos = aLight->GetPosition(); focus = aLight->GetFocalPoint(); color = aLight->GetColor(); dir[0] = focus[0] - pos[0]; dir[1] = focus[1] - pos[1]; dir[2] = focus[2] - pos[2]; vtkMath::Normalize(dir); if (aLight->GetPositional()) { double *attn; if (aLight->GetConeAngle() >= 180.0) { fprintf(fp,"%sPointLight {\n", indent); VTK_INDENT_MORE; } else { fprintf(fp,"%sSpotLight {\n", indent); VTK_INDENT_MORE; fprintf(fp,"%sdirection %f %f %f\n", indent, dir[0], dir[1], dir[2]); fprintf(fp,"%scutOffAngle %f\n", indent, aLight->GetConeAngle()); // the following ignores linear and quadratic attenuation values attn = aLight->GetAttenuationValues(); fprintf(fp,"%sdropOffRate %f\n", indent, attn[0]); } fprintf(fp,"%slocation %f %f %f\n", indent, pos[0], pos[1], pos[2]); } else { fprintf(fp,"%sDirectionalLight {\n", indent); VTK_INDENT_MORE; fprintf(fp,"%sdirection %f %f %f\n", indent, dir[0], dir[1], dir[2]); } fprintf(fp,"%scolor %f %f %f\n", indent, color[0], color[1], color[2]); fprintf(fp,"%sintensity %f\n", indent, aLight->GetIntensity()); if (aLight->GetSwitch()) { fprintf(fp,"%son TRUE\n%s}\n", indent, indent); } else { fprintf(fp,"%son FALSE\n%s}\n", indent, indent); } VTK_INDENT_LESS; } void vtkIVExporter::WriteAnActor(vtkActor *anActor, FILE *fp) { vtkDataSet *ds; vtkPolyData *pd; vtkGeometryFilter *gf = NULL; vtkPointData *pntData; vtkPoints *points; vtkDataArray *normals = NULL; vtkDataArray *tcoords = NULL; int i; vtkProperty *prop; double *tempd; vtkCellArray *cells; vtkIdType npts = 0; vtkIdType *indx = 0; float tempf2; vtkPolyDataMapper *pm; vtkUnsignedCharArray *colors; double *p; unsigned char *c; vtkTransform *trans; // see if the actor has a mapper. it could be an assembly if (anActor->GetMapper() == NULL) { return; } fprintf(fp,"%sSeparator {\n", indent); VTK_INDENT_MORE; // first stuff out the transform trans = vtkTransform::New(); trans->SetMatrix(anActor->vtkProp3D::GetMatrix()); fprintf(fp,"%sTransform {\n", indent); VTK_INDENT_MORE; tempd = trans->GetPosition(); fprintf(fp,"%stranslation %g %g %g\n", indent, tempd[0], tempd[1], tempd[2]); tempd = trans->GetOrientationWXYZ(); fprintf(fp,"%srotation %g %g %g %g\n", indent, tempd[1], tempd[2], tempd[3], tempd[0]*3.1415926/180.0); tempd = trans->GetScale(); fprintf(fp,"%sscaleFactor %g %g %g\n", indent, tempd[0], tempd[1], tempd[2]); fprintf(fp,"%s}\n", indent); VTK_INDENT_LESS; trans->Delete(); // get the mappers input and matrix ds = anActor->GetMapper()->GetInput(); // we really want polydata if ( ds->GetDataObjectType() != VTK_POLY_DATA ) { gf = vtkGeometryFilter::New(); gf->SetInput(ds); gf->Update(); pd = gf->GetOutput(); } else { ds->Update(); pd = (vtkPolyData *)ds; } pm = vtkPolyDataMapper::New(); pm->SetInput(pd); pm->SetScalarRange(anActor->GetMapper()->GetScalarRange()); pm->SetScalarVisibility(anActor->GetMapper()->GetScalarVisibility()); pm->SetLookupTable(anActor->GetMapper()->GetLookupTable()); points = pd->GetPoints(); pntData = pd->GetPointData(); normals = pntData->GetNormals(); tcoords = pntData->GetTCoords(); colors = pm->MapScalars(1.0); fprintf(fp,"%sMaterial {\n", indent); VTK_INDENT_MORE; // write out the material properties to the mat file prop = anActor->GetProperty(); // the following is based on a guess about how VTK's GetAmbient // property corresponds to SoMaterial's ambientColor tempf2 = prop->GetAmbient(); tempd = prop->GetAmbientColor(); fprintf(fp,"%sambientColor %g %g %g\n", indent, tempd[0]*tempf2, tempd[1]*tempf2, tempd[2]*tempf2); tempf2 = prop->GetDiffuse(); tempd = prop->GetDiffuseColor(); fprintf(fp,"%sdiffuseColor %g %g %g\n", indent, tempd[0]*tempf2, tempd[1]*tempf2, tempd[2]*tempf2); tempf2 = prop->GetSpecular(); tempd = prop->GetSpecularColor(); fprintf(fp,"%sspecularColor %g %g %g\n", indent, tempd[0]*tempf2, tempd[1]*tempf2, tempd[2]*tempf2); fprintf(fp,"%sshininess %g\n", indent,prop->GetSpecularPower()/128.0); fprintf(fp,"%stransparency %g\n", indent,1.0 - prop->GetOpacity()); fprintf(fp,"%s}\n", indent); // close matrial VTK_INDENT_LESS; // is there a texture map if (anActor->GetTexture()) { vtkTexture *aTexture = anActor->GetTexture(); int *size, xsize, ysize, bpp; vtkDataArray *scalars; vtkUnsignedCharArray *mappedScalars; unsigned char *txtrData; int totalValues; // make sure it is updated and then get some info if (aTexture->GetInput() == NULL) { vtkErrorMacro(<< "texture has no input!\n"); return; } aTexture->GetInput()->Update(); size = aTexture->GetInput()->GetDimensions(); scalars = aTexture->GetInput()->GetPointData()->GetScalars(); // make sure scalars are non null if (!scalars) { vtkErrorMacro(<< "No scalar values found for texture input!\n"); return; } // make sure using unsigned char data of color scalars type if (aTexture->GetMapColorScalarsThroughLookupTable () || (scalars->GetDataType() != VTK_UNSIGNED_CHAR) ) { mappedScalars = aTexture->GetMappedScalars (); } else { mappedScalars = static_cast(scalars); } // we only support 2d texture maps right now // so one of the three sizes must be 1, but it // could be any of them, so lets find it if (size[0] == 1) { xsize = size[1]; ysize = size[2]; } else { xsize = size[0]; if (size[1] == 1) { ysize = size[2]; } else { ysize = size[1]; if (size[2] != 1) { vtkErrorMacro(<< "3D texture maps currently are not supported!\n"); return; } } } fprintf(fp, "%sTexture2 {\n", indent); VTK_INDENT_MORE; bpp = mappedScalars->GetNumberOfComponents(); fprintf(fp, "%simage %d %d %d\n", indent, xsize, ysize, bpp); VTK_INDENT_MORE; txtrData = static_cast(mappedScalars)->GetPointer(0); totalValues = xsize*ysize; fprintf(fp,"%s",indent); for (i = 0; i < totalValues; i++) { fprintf(fp,"%.2x",*txtrData); txtrData++; if (bpp > 1) { fprintf(fp,"%.2x",*txtrData); txtrData++; } if (bpp > 2) { fprintf(fp,"%.2x",*txtrData); txtrData++; } if (bpp > 3) { fprintf(fp,"%.2x",*txtrData); txtrData++; } if (i%8 == 0) { fprintf(fp,"\n%s ", indent); } else { fprintf(fp," "); } } VTK_INDENT_LESS; fprintf(fp, "%s}\n", indent); VTK_INDENT_LESS; } // write out point data if any this->WritePointData(points, normals, tcoords, colors, fp); // write out polys if any if (pd->GetNumberOfPolys() > 0) { fprintf(fp,"%sIndexedFaceSet {\n", indent); VTK_INDENT_MORE; fprintf(fp,"%scoordIndex [\n", indent); VTK_INDENT_MORE; cells = pd->GetPolys(); for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) { fprintf(fp,"%s", indent); for (i = 0; i < npts; i++) { // treating vtkIdType as int fprintf(fp,"%i, ",(int)indx[i]); if (((i+1)%10) == 0) { fprintf(fp, "\n%s ", indent); } } fprintf(fp,"-1,\n"); } fprintf(fp,"%s]\n", indent); VTK_INDENT_LESS; fprintf(fp,"%s}\n", indent); VTK_INDENT_LESS; } // write out tstrips if any if (pd->GetNumberOfStrips() > 0) { fprintf(fp,"%sIndexedTriangleStripSet {\n", indent); VTK_INDENT_MORE; fprintf(fp,"%scoordIndex [\n", indent); VTK_INDENT_MORE; cells = pd->GetStrips(); for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) { fprintf(fp,"%s", indent); for (i = 0; i < npts; i++) { // treating vtkIdType as int fprintf(fp,"%i, ", (int)indx[i]); if (((i+1)%10) == 0) { fprintf(fp, "\n%s ", indent); } } fprintf(fp,"-1,\n"); } fprintf(fp,"%s]\n", indent); VTK_INDENT_LESS; fprintf(fp,"%s}\n", indent); VTK_INDENT_LESS; } // write out lines if any if (pd->GetNumberOfLines() > 0) { fprintf(fp,"%sIndexedLineSet {\n", indent); VTK_INDENT_MORE; fprintf(fp,"%scoordIndex [\n", indent); VTK_INDENT_MORE; cells = pd->GetLines(); for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) { fprintf(fp,"%s", indent); for (i = 0; i < npts; i++) { // treating vtkIdType as int fprintf(fp,"%i, ", (int)indx[i]); if (((i+1)%10) == 0) { fprintf(fp, "\n%s ", indent); } } fprintf(fp,"-1,\n"); } fprintf(fp,"%s]\n", indent); VTK_INDENT_LESS; fprintf(fp,"%s}\n", indent); VTK_INDENT_LESS; } // write out verts if any // (more complex because there is no IndexedPointSet) if (pd->GetNumberOfVerts() > 0) { fprintf(fp, "%sSeparator {\n", indent); VTK_INDENT_MORE; fprintf(fp, "%sCoordinate3 {\n", indent); VTK_INDENT_MORE; fprintf(fp,"%spoint [", indent); VTK_INDENT_MORE; cells = pd->GetVerts(); for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) { for (i = 0; i < npts; i++) { p = points->GetPoint(indx[i]); fprintf (fp,"%s%g %g %g,\n", indent, p[0], p[1], p[2]); } } fprintf(fp,"%s]\n", indent); VTK_INDENT_LESS; fprintf(fp,"%s}\n", indent); VTK_INDENT_LESS; if (colors) { fprintf(fp,"%sPackedColor {", indent); VTK_INDENT_MORE; fprintf(fp,"%srgba [\n", indent); VTK_INDENT_MORE; for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) { fprintf(fp,"%s", indent); for (i = 0; i < npts; i++) { c = colors->GetPointer(4*indx[i]); fprintf (fp,"%#lx, ", ((unsigned long)c[3] << 24) | (((unsigned long)c[2])<<16) | (((unsigned long)c[1])<<8) | ((unsigned long)c[0])); if (((i+1)%5) == 0) { fprintf(fp, "\n%s", indent); } } } fprintf(fp,"\n%s]\n", indent); VTK_INDENT_LESS; fprintf(fp,"%s}\n", indent); VTK_INDENT_LESS; fprintf(fp,"%sMaterialBinding { value PER_VERTEX_INDEXED }\n", indent); } fprintf(fp, "%sPointSet {\n", indent); VTK_INDENT_MORE; // treating vtkIdType as int fprintf(fp, "%snumPoints %d\n", indent, (int)npts); VTK_INDENT_MORE; fprintf(fp, "%s}\n", indent); VTK_INDENT_LESS; fprintf(fp,"%s}\n", indent); // close the Separator VTK_INDENT_LESS; } fprintf(fp, "%s}\n", indent); VTK_INDENT_LESS; if (gf) { gf->Delete(); } pm->Delete(); } void vtkIVExporter::WritePointData(vtkPoints *points, vtkDataArray *normals, vtkDataArray *tcoords, vtkUnsignedCharArray *colors, FILE *fp) { double *p; int i; unsigned char *c; // write out the points fprintf(fp,"%sCoordinate3 {\n", indent); VTK_INDENT_MORE; fprintf(fp,"%spoint [\n", indent); VTK_INDENT_MORE; for (i = 0; i < points->GetNumberOfPoints(); i++) { p = points->GetPoint(i); fprintf (fp,"%s%g %g %g,\n", indent, p[0], p[1], p[2]); } fprintf(fp,"%s]\n", indent); VTK_INDENT_LESS; fprintf(fp,"%s}\n", indent); VTK_INDENT_LESS; // write out the point data if (normals) { fprintf(fp,"%sNormal {\n", indent); VTK_INDENT_MORE; fprintf(fp,"%svector [\n", indent); VTK_INDENT_MORE; for (i = 0; i < normals->GetNumberOfTuples(); i++) { p = normals->GetTuple(i); fprintf (fp,"%s%g %g %g,\n", indent, p[0], p[1], p[2]); } fprintf(fp,"%s]\n", indent); VTK_INDENT_LESS; fprintf(fp,"%s}\n", indent); VTK_INDENT_LESS; } // write out the point data if (tcoords) { fprintf(fp,"%sTextureCoordinateBinding {\n",indent); VTK_INDENT_MORE; fprintf(fp,"%svalue PER_VERTEX_INDEXED\n",indent); VTK_INDENT_LESS; fprintf(fp,"%s}\n",indent); fprintf(fp,"%sTextureCoordinate2 {\n", indent); VTK_INDENT_MORE; fprintf(fp,"%spoint [\n", indent); VTK_INDENT_MORE; for (i = 0; i < tcoords->GetNumberOfTuples(); i++) { p = tcoords->GetTuple(i); fprintf (fp,"%s%g %g,\n", indent, p[0], p[1]); } fprintf(fp,"%s]\n", indent); VTK_INDENT_LESS; fprintf(fp,"%s}\n", indent); VTK_INDENT_LESS; } // write out the point data if (colors) { fprintf(fp,"%sPackedColor {\n", indent); VTK_INDENT_MORE; fprintf(fp,"%srgba [\n", indent); VTK_INDENT_MORE; fprintf(fp,"%s", indent); for (i = 0; i < colors->GetNumberOfTuples(); i++) { c = colors->GetPointer(4*i); fprintf (fp,"%#lx, ", ((unsigned long)c[3] << 24) | (((unsigned long)c[2])<<16) | (((unsigned long)c[1])<<8) | ((unsigned long)c[0])); if (((i+1)%5)==0) { fprintf(fp, "\n%s", indent); } } fprintf(fp,"\n%s]\n", indent); VTK_INDENT_LESS; fprintf(fp,"%s}\n", indent); VTK_INDENT_LESS; fprintf(fp,"%sMaterialBinding { value PER_VERTEX_INDEXED }\n", indent); } } void vtkIVExporter::PrintSelf(ostream& os, vtkIndent ind) { this->Superclass::PrintSelf(os,ind); if (this->FileName) { os << ind << "FileName: " << this->FileName << "\n"; } else { os << ind << "FileName: (null)\n"; } }