Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
1417 lines (1277 sloc) 40.1 KB
/*=========================================================================
Program: Visualization Toolkit
Module: vtkRIBExporter.cxx
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 "vtkRIBExporter.h"
#include "vtkAssemblyNode.h"
#include "vtkAssemblyPath.h"
#include "vtkCamera.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkFieldData.h"
#include "vtkGeometryFilter.h"
#include "vtkImageAppendComponents.h"
#include "vtkImageConstantPad.h"
#include "vtkImageExtractComponents.h"
#include "vtkLightCollection.h"
#include "vtkMapper.h"
#include "vtkMath.h"
#include "vtkMatrix4x4.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkPolygon.h"
#include "vtkRIBLight.h"
#include "vtkRIBProperty.h"
#include "vtkRenderWindow.h"
#include "vtkRendererCollection.h"
#include "vtkStructuredPoints.h"
#include "vtkTIFFWriter.h"
#include "vtkTexture.h"
#include <vtksys/ios/sstream>
vtkStandardNewMacro(vtkRIBExporter);
typedef double RtColor[3];
typedef double RtPoint[3];
typedef char *RtPointer;
typedef float RtFloat;
vtkRIBExporter::vtkRIBExporter()
{
this->FilePrefix = NULL;
this->FilePtr = NULL;
this->TexturePrefix = NULL;
this->Size[0] = this->Size[1] = -1;
this->PixelSamples[0] = this->PixelSamples[1] = 2;
this->Background = 0;
this->ExportArrays = 0;
}
vtkRIBExporter::~vtkRIBExporter()
{
if ( this->FilePrefix )
{
delete [] this->FilePrefix;
}
if ( this->TexturePrefix )
{
delete [] this->TexturePrefix;
}
}
void vtkRIBExporter::WriteData()
{
vtkRenderer *ren;
vtkActorCollection *ac;
vtkLightCollection *lc;
vtkActor *anActor;
vtkCollection *textures = vtkCollection::New();
vtkLight *aLight;
vtkTexture *aTexture;
// make sure the user specified a FilePrefix
if ( this->FilePrefix == NULL)
{
vtkErrorMacro(<< "Please specify file name for the rib file");
return;
}
// first make sure there is only one renderer in this rendering window
if (this->RenderWindow->GetRenderers()->GetNumberOfItems() > 1)
{
vtkErrorMacro(<< "RIB files only support one renderer per window.");
return;
}
// get the renderer
vtkCollectionSimpleIterator sit;
this->RenderWindow->GetRenderers()->InitTraversal(sit);
ren = this->RenderWindow->GetRenderers()->GetNextRenderer(sit);
// make sure it has at least one actor
if (ren->GetActors()->GetNumberOfItems() < 1)
{
vtkErrorMacro(<< "no actors found for writing .RIB file.");
return;
}
char *ribFileName = new char [strlen (this->FilePrefix) + strlen (".rib") + 1];
sprintf (ribFileName, "%s%s", this->FilePrefix, ".rib");
this->FilePtr = fopen (ribFileName, "w");
if (this->FilePtr == NULL)
{
vtkErrorMacro (<< "Cannot open " << ribFileName);
delete [] ribFileName;
return;
}
delete [] ribFileName;
//
// Write Header
//
this->WriteHeader (ren);
//
// All textures must be made first
//
ac = ren->GetActors();
vtkCollectionSimpleIterator ait;
for ( ac->InitTraversal (ait); (anActor = ac->GetNextActor(ait)); )
{
// see if the actor has a mapper. it could be an assembly
if (anActor->GetMapper() == NULL)
{
continue;
}
// if it's invisible, don't make the texture
if ( anActor->GetVisibility () )
{
aTexture = anActor->GetTexture ();
if (aTexture &&
textures->IsItemPresent (aTexture) == 0) {
this->WriteTexture (aTexture);
textures->AddItem (aTexture);
}
}
}
//
// Write viewport
//
this->WriteViewport (ren, this->Size);
//
// Write camera
//
this->WriteCamera (ren->GetActiveCamera ());
fprintf (this->FilePtr, "WorldBegin\n");
//
// Write all lights
//
lc = ren->GetLights();
//
// If there is no light defined, create one
//
lc->InitTraversal(sit);
if (lc->GetNextLight(sit) == NULL)
{
vtkWarningMacro(<< "No light defined, creating one at camera position");
ren->CreateLight();
}
// Create an ambient light
this->WriteAmbientLight (1);
int lightCount = 2;
for (lc->InitTraversal(sit); (aLight = lc->GetNextLight(sit)); )
{
if (aLight->GetSwitch ())
{
this->WriteLight(aLight, lightCount++);
}
}
//
// Write all actors
//
vtkAssemblyNode *node;
ac = ren->GetActors();
vtkAssemblyPath *apath;
for (ac->InitTraversal(ait); (anActor = ac->GetNextActor(ait)); )
{
for (anActor->InitPathTraversal(); (apath=anActor->GetNextPath()); )
{
node = apath->GetLastNode();
if ( node->GetViewProp()->GetVisibility () )
{
if ( node->GetViewProp()->IsA("vtkActor") )
{
this->WriteActor((vtkActor *)(node->GetViewProp()));
}
}
}
}
// RiWorldEnd ();
fprintf (this->FilePtr, "WorldEnd\n");
//
// Write trailer
//
this->WriteTrailer ();
// RiEnd ();
fclose (this->FilePtr);
textures->Delete();
}
void vtkRIBExporter::WriteHeader (vtkRenderer *aRen)
{
// create a FileName to hold the renderered image
char *imageFileName = new char [strlen (this->FilePrefix) + strlen (".tif") + 1];
sprintf (imageFileName, "%s%s", this->FilePrefix, ".tif");
fprintf (this->FilePtr, "FrameBegin %d\n", 1);
fprintf (this->FilePtr, "Display \"%s\" \"file\" \"rgba\"\n", imageFileName);
fprintf (this->FilePtr, "Declare \"bgcolor\" \"uniform color\"\n");
if (this->Background)
{
double *color = aRen->GetBackground ();
fprintf (this->FilePtr, "Imager \"background\" \"bgcolor\" [%f %f %f]\n",
color[0], color[1], color[2]);
}
fprintf (this->FilePtr, "PixelSamples %d %d\n",
this->PixelSamples[0],
this->PixelSamples[1]);
delete [] imageFileName;
}
void vtkRIBExporter::WriteTrailer ()
{
fprintf (this->FilePtr, "FrameEnd\n");
}
void vtkRIBExporter::WriteProperty (vtkProperty *aProperty,
vtkTexture *aTexture)
{
char *mapName;
double Ambient, Diffuse, Specular;
double Opacity;
double *DiffuseColor, *SpecularColor;
double Roughness;
RtColor opacity;
Opacity = aProperty->GetOpacity();
// set the opacity
opacity[0] = Opacity;
opacity[1] = Opacity;
opacity[2] = Opacity;
fprintf (this->FilePtr, "Opacity [%f %f %f]\n",
opacity[0], opacity[1], opacity[2]);
// set the color of the surface
DiffuseColor = aProperty->GetDiffuseColor();
fprintf (this->FilePtr, "Color [%f %f %f]\n",
DiffuseColor[0], DiffuseColor[1], DiffuseColor[2]);
// set the shader parameters
Ambient = aProperty->GetAmbient();
Diffuse = aProperty->GetDiffuse();
Specular = aProperty->GetSpecular();
SpecularColor = aProperty->GetSpecularColor();
Roughness = (RtFloat) (1.0 / aProperty->GetSpecularPower ());
//
// if there is a texture map we need to declare it
//
mapName = (char *) NULL;
if (aTexture)
{
mapName = this->GetTextureName(aTexture);
if (mapName)
{
fprintf (this->FilePtr, "Declare \"mapname\" \"uniform string\"\n");
}
}
//
// Now we need to check to see if an RIBProperty has been specified
//
if (strcmp ("vtkRIBProperty", aProperty->GetClassName ()) == 0)
{
vtkRIBProperty *aRIBProperty = (vtkRIBProperty *) aProperty;
if (aRIBProperty->GetDeclarations ())
{
fprintf (this->FilePtr, "%s", aRIBProperty->GetDeclarations ());
}
if (aRIBProperty->GetSurfaceShader ())
{
fprintf (this->FilePtr, "%s \"%s\" ", "Surface", aRIBProperty->GetSurfaceShader ());
fprintf (this->FilePtr, "\"Ka\" [%f] ", Ambient);
fprintf (this->FilePtr, "\"Kd\" [%f] ", Diffuse);
fprintf (this->FilePtr, "\"Ks\" [%f] ", Specular);
fprintf (this->FilePtr, "\"roughness\" [%f] ", Roughness);
fprintf (this->FilePtr, "\"specularcolor\" [%f %f %f]",
SpecularColor[0], SpecularColor[1], SpecularColor[2]);
if (mapName)
{
fprintf (this->FilePtr, " \"mapname\" [\"%s\"]", mapName);
}
}
if (aRIBProperty->GetParameters ())
{
fprintf (this->FilePtr, "%s", aRIBProperty->GetParameters ());
}
fprintf (this->FilePtr, "\n");
if (aRIBProperty->GetDisplacementShader ())
{
fprintf (this->FilePtr, "%s \"%s\" ", "Displacement", aRIBProperty->GetDisplacementShader ());
fprintf (this->FilePtr, "\"Ka\" [%f] ", Ambient);
fprintf (this->FilePtr, "\"Kd\" [%f] ", Diffuse);
fprintf (this->FilePtr, "\"Ks\" [%f] ", Specular);
fprintf (this->FilePtr, "\"roughness\" [%f] ", Roughness);
fprintf (this->FilePtr, "\"specularcolor\" [%f %f %f]",
SpecularColor[0], SpecularColor[1], SpecularColor[2]);
if (mapName)
{
fprintf (this->FilePtr, " \"mapname\" [\"%s\"]", mapName);
}
if (aRIBProperty->GetParameters ())
{
fprintf (this->FilePtr, "%s", aRIBProperty->GetParameters ());
}
fprintf (this->FilePtr, "\n");
}
}
// Normal Property
else
{
fprintf (this->FilePtr, "Surface \"%s\" ", mapName ? "txtplastic" : "plastic");
fprintf (this->FilePtr, "\"Ka\" [%f] ", Ambient);
fprintf (this->FilePtr, "\"Kd\" [%f] ", Diffuse);
fprintf (this->FilePtr, "\"Ks\" [%f] ", Specular);
fprintf (this->FilePtr, "\"roughness\" [%f] ", Roughness);
fprintf (this->FilePtr, "\"specularcolor\" [%f %f %f] ",
SpecularColor[0], SpecularColor[1], SpecularColor[2]);
if (mapName)
{
fprintf (this->FilePtr, " \"mapname\" [\"%s\"]", mapName);
}
fprintf (this->FilePtr, "\n");
}
}
void vtkRIBExporter::WriteLight (vtkLight *aLight, int count)
{
double color[4];
double *Color;
double *Position, *FocalPoint;
double Intensity;
// get required info from light
Intensity = aLight->GetIntensity();
Color = aLight->GetDiffuseColor();
color[0] = Intensity * Color[0];
color[1] = Intensity * Color[1];
color[2] = Intensity * Color[2];
color[3] = 1.0;
FocalPoint = aLight->GetFocalPoint();
Position = aLight->GetPosition();
//
// Now we need to check to see if an RIBLight has been specified
//
if (strcmp ("vtkRIBLight", aLight->GetClassName ()) == 0)
{
if (((vtkRIBLight *) aLight)->GetShadows())
{
fprintf (this->FilePtr, "Attribute \"light\" \"shadows\" \"on\"\n");
}
}
// define the light source
if (!aLight->GetPositional())
{
fprintf (this->FilePtr, "LightSource \"distantlight\" %d ", count);
fprintf (this->FilePtr, "\"intensity\" [%f] ", Intensity);
fprintf (this->FilePtr, "\"lightcolor\" [%f %f %f] ",
color[0], color[1], color[2]);
fprintf (this->FilePtr, "\"from\" [%f %f %f] ",
Position[0], Position[1], Position[2]);
fprintf (this->FilePtr, "\"to\" [%f %f %f]\n",
FocalPoint[0], FocalPoint[1], FocalPoint[2]);
}
else
{
double coneAngle = aLight->GetConeAngle ();
double exponent = aLight->GetExponent ();
fprintf (this->FilePtr, "LightSource \"spotlight\" %d ", count);
fprintf (this->FilePtr, "\"intensity\" [%f] ", Intensity);
fprintf (this->FilePtr, "\"lightcolor\" [%f %f %f] ",
color[0], color[1], color[2]);
fprintf (this->FilePtr, "\"from\" [%f %f %f] ",
Position[0], Position[1], Position[2]);
fprintf (this->FilePtr, "\"to\" [%f %f %f]\n",
FocalPoint[0], FocalPoint[1], FocalPoint[2]);
fprintf (this->FilePtr, "\"coneangle\" [%f]\n", coneAngle);
fprintf (this->FilePtr, "\"beamdistribution\" [%f]\n", exponent);
fprintf (this->FilePtr, "\"conedeltaangle\" [%f]\n", 0.0);
}
if (strcmp ("vtkRIBLight", aLight->GetClassName ()) == 0)
{
if (((vtkRIBLight *) aLight)->GetShadows())
{
fprintf (this->FilePtr, "Attribute \"light\" \"shadows\" \"off\"\n");
}
}
}
void vtkRIBExporter::WriteAmbientLight (int count)
{
fprintf (this->FilePtr, "LightSource \"ambientlight\" %d\n", count);
}
void vtkRIBExporter::WriteViewport (vtkRenderer *ren, int size[2])
{
double aspect[2];
double *vport;
int left,right,bottom,top;
if (size[0] != -1 || size[1] != -1)
{
vport = ren->GetViewport();
left = (int)(vport[0]*(size[0] -1));
right = (int)(vport[2]*(size[0] - 1));
bottom = (int)(vport[1]*(size[1] -1));
top = (int)(vport[3]*(size[1] - 1));
fprintf (this->FilePtr, "Format %d %d 1\n", size[0], size[1]);
fprintf (this->FilePtr, "CropWindow %f %f %f %f\n",
vport[0], vport[2], vport[1], vport[3]);
aspect[0] = (double)(right-left+1)/(double)(top-bottom+1);
aspect[1] = 1.0;
fprintf (this->FilePtr, "ScreenWindow %f %f %f %f\n",
-aspect[0], aspect[0], -1.0, 1.0);
}
}
static void PlaceCamera (FILE *filePtr, RtPoint, RtPoint, double);
static void AimZ (FILE *filePtr, RtPoint);
void vtkRIBExporter::WriteCamera (vtkCamera *aCamera)
{
RtPoint direction;
double position[3], focalPoint[3];
aCamera->GetPosition (position);
aCamera->GetFocalPoint (focalPoint);
direction[0] = focalPoint[0] - position[0];
direction[1] = focalPoint[1] - position[1];
direction[2] = focalPoint[2] - position[2];
vtkMath::Normalize (direction);
RtFloat angle = aCamera->GetViewAngle ();
fprintf (this->FilePtr, "Projection \"perspective\" \"fov\" [%f]\n", angle);
PlaceCamera (this->FilePtr, position, direction, aCamera->GetRoll ());
fprintf (this->FilePtr, "Orientation \"rh\"\n");
}
/*
* PlaceCamera(): establish a viewpoint, viewing direction and orientation
* for a scene. This routine must be called before RiWorldBegin().
* position: a point giving the camera position
* direction: a point giving the camera direction relative to position
* roll: an optional rotation of the camera about its direction axis
*/
static double cameraMatrix[4][4] = {
{-1, 0, 0, 0},
{ 0, 1, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1}
};
void PlaceCamera(FILE *filePtr, RtPoint position, RtPoint direction, double roll)
{
fprintf (filePtr, "Identity\n");
fprintf (filePtr, "Transform [%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f ]\n",
cameraMatrix[0][0], cameraMatrix[0][1], cameraMatrix[0][2], cameraMatrix[0][3],
cameraMatrix[1][0], cameraMatrix[1][1], cameraMatrix[1][2], cameraMatrix[1][3],
cameraMatrix[2][0], cameraMatrix[2][1], cameraMatrix[2][2], cameraMatrix[2][3],
cameraMatrix[3][0], cameraMatrix[3][1], cameraMatrix[3][2], cameraMatrix[3][3]);
fprintf (filePtr, "Rotate %f %f %f %f\n", -roll, 0.0, 0.0, 1.0);
AimZ(filePtr, direction);
fprintf (filePtr, "Translate %f %f %f\n",
-position[0], -position[1], -position[2]);
}
/*
* AimZ(): rotate the world so the directionvector points in
* positive z by rotating about the y axis, then x. The cosine
* of each rotation is given by components of the normalized
* direction vector. Before the y rotation the direction vector
* might be in negative z, but not afterward.
*/
static void
AimZ(FILE *filePtr, RtPoint direction)
{
double xzlen, yzlen, yrot, xrot;
if (direction[0]==0 && direction[1]==0 && direction[2]==0)
{
return;
}
/*
* The initial rotation about the y axis is given by the projection of
* the direction vector onto the x,z plane: the x and z components
* of the direction.
*/
xzlen = sqrt(direction[0]*direction[0]+direction[2]*direction[2]);
if (xzlen == 0)
{
yrot = (direction[1] < 0) ? 180 : 0;
}
else
{
yrot = 180*acos(direction[2]/xzlen)/vtkMath::Pi();
}
/*
* The second rotation, about the x axis, is given by the projection on
* the y,z plane of the y-rotated direction vector: the original y
* component, and the rotated x,z vector from above.
*/
yzlen = sqrt(direction[1]*direction[1]+xzlen*xzlen);
xrot = 180*acos(xzlen/yzlen)/vtkMath::Pi(); /* yzlen should never be 0 */
if (direction[1] > 0)
{
fprintf (filePtr, "Rotate %f %f %f %f\n", xrot, 1.0, 0.0, 0.0);
}
else
{
fprintf (filePtr, "Rotate %f %f %f %f\n", -xrot, 1.0, 0.0, 0.0);
}
/* The last rotation declared gets performed first */
if (direction[0] > 0)
{
fprintf (filePtr, "Rotate %f %f %f %f\n", -yrot, 0.0, 1.0, 0.0);
}
else
{
fprintf (filePtr, "Rotate %f %f %f %f\n", yrot, 0.0, 1.0, 0.0);
}
}
void vtkRIBExporter::WriteActor(vtkActor *anActor)
{
vtkDataSet *aDataSet;
vtkPolyData *polyData;
vtkGeometryFilter *geometryFilter = NULL;
vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
// see if the actor has a mapper. it could be an assembly
if (anActor->GetMapper() == NULL)
{
return;
}
fprintf (this->FilePtr, "AttributeBegin\n");
fprintf (this->FilePtr, "TransformBegin\n");
// write out the property
this->WriteProperty (anActor->GetProperty (), anActor->GetTexture ());
// get the mappers input and matrix
aDataSet = anActor->GetMapper()->GetInput();
anActor->GetMatrix (matrix);
matrix->Transpose();
// insert model transformation
fprintf (this->FilePtr, "ConcatTransform [%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f ]\n",
matrix->Element[0][0], matrix->Element[0][1],
matrix->Element[0][2], matrix->Element[0][3],
matrix->Element[1][0], matrix->Element[1][1],
matrix->Element[1][2], matrix->Element[1][3],
matrix->Element[2][0], matrix->Element[2][1],
matrix->Element[2][2], matrix->Element[2][3],
matrix->Element[3][0], matrix->Element[3][1],
matrix->Element[3][2], matrix->Element[3][3]);
// we really want polydata
if ( aDataSet->GetDataObjectType() != VTK_POLY_DATA )
{
geometryFilter = vtkGeometryFilter::New();
geometryFilter->SetInput(aDataSet);
geometryFilter->Update();
polyData = geometryFilter->GetOutput();
}
else
{
polyData = (vtkPolyData *)aDataSet;
}
// Let us start with point data and then we can copy to other
if ( this->ExportArrays )
{
vtkPointData *pointData = polyData->GetPointData();
if ( pointData && pointData->GetNumberOfArrays() )
{
int cc;
for ( cc = 0; cc< pointData->GetNumberOfArrays(); cc ++ )
{
vtkDataArray *array = pointData->GetArray(cc);
char buffer[1024];
this->ModifyArrayName(buffer, array->GetName());
fprintf(this->FilePtr, "Declare \"%s\" \"varying double\"\n",
buffer);
}
}
vtkCellData *cellData = polyData->GetCellData();
if ( cellData && cellData->GetNumberOfArrays() )
{
int cc;
for ( cc = 0; cc< cellData->GetNumberOfArrays(); cc ++ )
{
vtkDataArray *array = cellData->GetArray(cc);
char buffer[1024];
this->ModifyArrayName(buffer, array->GetName());
fprintf(this->FilePtr, "Declare \"%s\" \"varying double\"\n",
buffer);
}
}
vtkFieldData *fieldData = polyData->GetFieldData();
if ( fieldData && fieldData->GetNumberOfArrays() )
{
int cc;
for ( cc = 0; cc< fieldData->GetNumberOfArrays(); cc ++ )
{
vtkDataArray *array = fieldData->GetArray(cc);
char buffer[1024];
this->ModifyArrayName(buffer, array->GetName());
fprintf(this->FilePtr, "Declare \"%s\" \"varying double\"\n",
buffer);
}
}
}
if (polyData->GetNumberOfPolys ())
{
this->WritePolygons (polyData, anActor->GetMapper()->MapScalars(1.0),
anActor->GetProperty ());
}
if (polyData->GetNumberOfStrips ())
{
this->WriteStrips (polyData, anActor->GetMapper()->MapScalars(1.0),
anActor->GetProperty ());
}
fprintf (this->FilePtr, "TransformEnd\n");
fprintf (this->FilePtr, "AttributeEnd\n");
if (geometryFilter)
{
geometryFilter->Delete();
}
matrix->Delete();
}
void vtkRIBExporter::WritePolygons (vtkPolyData *polyData,
vtkUnsignedCharArray *c,
vtkProperty *aProperty)
{
double vertexColors[512][3];
double *TCoords;
double *normals;
double points[3];
RtPoint vertexNormals[512];
RtPoint vertexPoints[512];
double poly_norm[3];
double vertexTCoords[512][2];
vtkIdType *pts = 0;
vtkIdType npts = 0;
int k, kk;
int rep, j, interpolation;
int tDim;
unsigned char *colors;
vtkCellArray *polys;
vtkDataArray *n = NULL;
vtkPoints *p;
vtkPolygon *polygon;
vtkDataArray *t;
// get the representation
rep = aProperty->GetRepresentation();
switch (rep)
{
case VTK_SURFACE:
break;
default:
vtkErrorMacro(<< "Bad representation sent\n");
break;
}
// get the shading interpolation
interpolation = aProperty->GetInterpolation();
// and draw the display list
polygon = vtkPolygon::New();
p = polyData->GetPoints();
polys = polyData->GetPolys();
t = polyData->GetPointData()->GetTCoords();
if ( t )
{
tDim = t->GetNumberOfComponents();
if (tDim != 2)
{
vtkDebugMacro(<< "Currently only 2d textures are supported.\n");
t = NULL;
}
}
// Get point data
vtkPointData *pointData = polyData->GetPointData();
vtkCellData *cellData = polyData->GetCellData();
vtkFieldData *fieldData = polyData->GetFieldData();
if ( interpolation == VTK_FLAT || !(polyData->GetPointData()) ||
!(n=polyData->GetPointData()->GetNormals()) )
{
n = 0;
}
for (polys->InitTraversal(); polys->GetNextCell(npts,pts); )
{
if (!n)
{
polygon->ComputeNormal(p,npts,pts,poly_norm);
}
for (j = 0; j < npts; j++)
{
k = j;
if (c)
{
colors = c->GetPointer(4*pts[k]);
vertexColors[k][0] = colors[0] / 255.0;
vertexColors[k][1] = colors[1] / 255.0;
vertexColors[k][2] = colors[2] / 255.0;
}
if (t)
{
TCoords = t->GetTuple (pts[k]);
vertexTCoords[k][0] = TCoords[0];
// Renderman Textures have origin at upper left
vertexTCoords[k][1] = 1.0 - TCoords[1];
}
if (n)
{
normals = n->GetTuple (pts[k]);
vertexNormals[k][0] = normals[0];
vertexNormals[k][1] = normals[1];
vertexNormals[k][2] = normals[2];
}
else
{
vertexNormals[k][0] = poly_norm[0];
vertexNormals[k][1] = poly_norm[1];
vertexNormals[k][2] = poly_norm[2];
}
p->GetPoint(pts[k], points);
vertexPoints[k][0] = points[0];
vertexPoints[k][1] = points[1];
vertexPoints[k][2] = points[2];
}
fprintf (this->FilePtr, "Polygon ");
fprintf (this->FilePtr, "\"P\" [");
for (kk = 0; kk < npts; kk++)
{
fprintf (this->FilePtr, "%f %f %f ",
vertexPoints[kk][0], vertexPoints[kk][1], vertexPoints[kk][2]);
}
fprintf (this->FilePtr, "] ");
fprintf (this->FilePtr, "\"N\" [");
for (kk = 0; kk < npts; kk++)
{
fprintf (this->FilePtr, "%f %f %f ",
vertexNormals[kk][0], vertexNormals[kk][1], vertexNormals[kk][2]);
}
fprintf (this->FilePtr, "] ");
if (c)
{
fprintf (this->FilePtr, "\"Cs\" [");
for (kk = 0; kk < npts; kk++)
{
fprintf (this->FilePtr, "%f %f %f ",
vertexColors[kk][0], vertexColors[kk][1], vertexColors[kk][2]);
}
fprintf (this->FilePtr, "] ");
}
if (t)
{
fprintf (this->FilePtr, "\"st\" [");
for (kk = 0; kk < npts; kk++)
{
fprintf (this->FilePtr, "%f %f ",
vertexTCoords[kk][0], vertexTCoords[kk][1]);
}
fprintf (this->FilePtr, "] ");
}
if ( this->ExportArrays )
{
if ( pointData )
{
int cc, aa;
vtksys_ios::ostringstream str_with_warning_C4701;
for ( cc = 0; cc < pointData->GetNumberOfArrays(); cc ++ )
{
vtkDataArray *array = pointData->GetArray(cc);
char buffer[1024];
this->ModifyArrayName(buffer, array->GetName());
str_with_warning_C4701 << "\"" << buffer << "\" [";
for (kk = 0; kk < npts; kk++)
{
double tuple[3];
array->GetTuple(pts[kk], tuple);
for ( aa = 0; aa < array->GetNumberOfComponents(); aa++ )
{
str_with_warning_C4701 << ((!kk &&!aa) ? "" : " ") << tuple[aa];
}
}
str_with_warning_C4701 << "] ";
}
fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str().c_str() );
}
if ( cellData )
{
int cc, aa;
vtksys_ios::ostringstream str_with_warning_C4701;
for ( cc = 0; cc < cellData->GetNumberOfArrays(); cc ++ )
{
vtkDataArray *array = cellData->GetArray(cc);
char buffer[1024];
this->ModifyArrayName(buffer, array->GetName());
str_with_warning_C4701 << "\"" << buffer << "\" [";
for (kk = 0; kk < npts; kk++)
{
double tuple[3];
array->GetTuple(pts[kk], tuple);
for ( aa = 0; aa < array->GetNumberOfComponents(); aa++ )
{
str_with_warning_C4701 << ((!kk &&!aa) ? "" : " ") << tuple[aa];
}
}
str_with_warning_C4701 << "] ";
}
fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str().c_str() );
}
if ( fieldData )
{
int cc, aa;
vtksys_ios::ostringstream str_with_warning_C4701;
for ( cc = 0; cc < fieldData->GetNumberOfArrays(); cc ++ )
{
vtkDataArray *array = fieldData->GetArray(cc);
char buffer[1024];
this->ModifyArrayName(buffer, array->GetName());
str_with_warning_C4701 << "\"" << buffer << "\" [";
for (kk = 0; kk < npts; kk++)
{
double tuple[3];
array->GetTuple(pts[kk], tuple);
for ( aa = 0; aa < array->GetNumberOfComponents(); aa++ )
{
str_with_warning_C4701 << ((!kk &&!aa) ? "" : " ") << tuple[aa];
}
}
str_with_warning_C4701 << "] ";
}
fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str().c_str() );
}
}
fprintf (this->FilePtr, "\n");
}
polygon->Delete();
}
void vtkRIBExporter::WriteStrips (vtkPolyData *polyData,
vtkUnsignedCharArray *c,
vtkProperty *aProperty)
{
double vertexColors[512][3];
double *TCoords;
double *normals;
double points[3];
RtPoint vertexNormals[512];
RtPoint vertexPoints[512];
double poly_norm[3];
double vertexTCoords[512][2];
vtkIdType *pts = 0;
vtkIdType npts = 0;
int p1, p2, p3;
int k, kk;
int rep, j, interpolation;
int tDim;
unsigned char *colors;
vtkCellArray *strips;
vtkDataArray *n = NULL;
vtkPoints *p;
vtkDataArray *t;
vtkPolygon *polygon;
vtkIdType idx[3];
// get the representation
rep = aProperty->GetRepresentation();
switch (rep)
{
case VTK_SURFACE:
break;
default:
vtkErrorMacro(<< "Bad representation sent\n");
break;
}
// get the shading interpolation
interpolation = aProperty->GetInterpolation();
// and draw the display list
p = polyData->GetPoints();
strips = polyData->GetStrips();
polygon = vtkPolygon::New();
t = polyData->GetPointData()->GetTCoords();
if ( t )
{
tDim = t->GetNumberOfComponents();
if (tDim != 2)
{
vtkDebugMacro(<< "Currently only 2d textures are supported.\n");
t = NULL;
}
}
if ( interpolation == VTK_FLAT || !(polyData->GetPointData()) ||
!(n=polyData->GetPointData()->GetNormals()) )
{
n = 0;
}
// Get point data
vtkPointData *pointData = polyData->GetPointData();
vtkCellData *cellData = polyData->GetCellData();
vtkFieldData *fieldData = polyData->GetFieldData();
// each iteration returns a triangle strip
for (strips->InitTraversal(); strips->GetNextCell(npts,pts); )
{
// each triangle strip is converted into a bunch of triangles
p1 = pts[0];
p2 = pts[1];
p3 = pts[2];
for (j = 0; j < (npts-2); j++)
{
if (j%2)
{
idx[0] = p2;
idx[1] = p1;
idx[2] = p3;
}
else
{
idx[0] = p1;
idx[1] = p2;
idx[2] = p3;
}
if (!n)
{
polygon->ComputeNormal (p, 3, idx, poly_norm);
}
// build colors, texture coordinates and normals for the triangle
for (k = 0; k < 3; k++)
{
if (c)
{
colors = c->GetPointer(4*idx[k]);
vertexColors[k][0] = colors[0] / 255.0;
vertexColors[k][1] = colors[1] / 255.0;
vertexColors[k][2] = colors[2] / 255.0;
}
if (t)
{
TCoords = t->GetTuple (idx[k]);
vertexTCoords[k][0] = TCoords[0];
// Renderman Textures have origin at upper left
vertexTCoords[k][1] = 1.0 - TCoords[1];
}
if (n)
{
normals = n->GetTuple (idx[k]);
vertexNormals[k][0] = normals[0];
vertexNormals[k][1] = normals[1];
vertexNormals[k][2] = normals[2];
}
else
{
vertexNormals[k][0] = poly_norm[0];
vertexNormals[k][1] = poly_norm[1];
vertexNormals[k][2] = poly_norm[2];
}
p->GetPoint(idx[k], points);
vertexPoints[k][0] = points[0];
vertexPoints[k][1] = points[1];
vertexPoints[k][2] = points[2];
}
fprintf (this->FilePtr, "Polygon ");
fprintf (this->FilePtr, "\"P\" [");
for (kk = 0; kk < 3; kk++)
{
fprintf (this->FilePtr, "%f %f %f ",
vertexPoints[kk][0], vertexPoints[kk][1], vertexPoints[kk][2]);
}
fprintf (this->FilePtr, "] ");
fprintf (this->FilePtr, "\"N\" [");
for (kk = 0; kk < 3; kk++)
{
fprintf (this->FilePtr, "%f %f %f ",
vertexNormals[kk][0], vertexNormals[kk][1], vertexNormals[kk][2]);
}
fprintf (this->FilePtr, "] ");
if (c)
{
fprintf (this->FilePtr, "\"Cs\" [");
for (kk = 0; kk < 3; kk++)
{
fprintf (this->FilePtr, "%f %f %f ",
vertexColors[kk][0], vertexColors[kk][1], vertexColors[kk][2]);
}
fprintf (this->FilePtr, "] ");
}
if (t)
{
fprintf (this->FilePtr, "\"st\" [");
for (kk = 0; kk < 3; kk++)
{
fprintf (this->FilePtr, "%f %f ",
vertexTCoords[kk][0], vertexTCoords[kk][1]);
}
fprintf (this->FilePtr, "] ");
}
if ( this->ExportArrays )
{
if ( pointData )
{
int cc, aa;
vtksys_ios::ostringstream str_with_warning_C4701;
for ( cc = 0; cc < pointData->GetNumberOfArrays(); cc ++ )
{
vtkDataArray *array = pointData->GetArray(cc);
char buffer[1024];
this->ModifyArrayName(buffer, array->GetName());
str_with_warning_C4701 << "\"" << buffer << "\" [";
for (kk = 0; kk < npts; kk++)
{
double tuple[3];
array->GetTuple(pts[kk], tuple);
for ( aa = 0; aa < array->GetNumberOfComponents(); aa++ )
{
str_with_warning_C4701 << ((!kk &&!aa) ? "" : " ") << tuple[aa];
}
}
str_with_warning_C4701 << "] ";
}
fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str().c_str() );
}
if ( cellData )
{
int cc, aa;
vtksys_ios::ostringstream str_with_warning_C4701;
for ( cc = 0; cc < cellData->GetNumberOfArrays(); cc ++ )
{
vtkDataArray *array = cellData->GetArray(cc);
char buffer[1024];
this->ModifyArrayName(buffer, array->GetName());
str_with_warning_C4701 << "\"" << buffer << "\" [";
for (kk = 0; kk < npts; kk++)
{
double tuple[3];
array->GetTuple(pts[kk], tuple);
for ( aa = 0; aa < array->GetNumberOfComponents(); aa++ )
{
str_with_warning_C4701 << ((!kk &&!aa) ? "" : " ") << tuple[aa];
}
}
str_with_warning_C4701 << "] ";
}
fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str().c_str() );
}
if ( fieldData )
{
int cc, aa;
vtksys_ios::ostringstream str_with_warning_C4701;
for ( cc = 0; cc < fieldData->GetNumberOfArrays(); cc ++ )
{
vtkDataArray *array = fieldData->GetArray(cc);
char buffer[1024];
this->ModifyArrayName(buffer, array->GetName());
str_with_warning_C4701 << "\"" << buffer << "\" [";
for (kk = 0; kk < npts; kk++)
{
double tuple[3];
array->GetTuple(pts[kk], tuple);
for ( aa = 0; aa < array->GetNumberOfComponents(); aa++ )
{
str_with_warning_C4701 << ((!kk &&!aa) ? "" : " ") << tuple[aa];
}
}
str_with_warning_C4701 << "] ";
}
fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str().c_str() );
}
}
fprintf (this->FilePtr, "\n");
// Get ready for next triangle
p1 = p2;
p2 = p3;
if (j+3 < npts)
{
p3 = pts[j+3];
}
}
}
polygon->Delete();
}
void vtkRIBExporter::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
if (this->FilePrefix)
{
os << indent << "FilePrefix: " << this->FilePrefix << "\n";
}
else
{
os << indent << "FilePrefix: (none)\n";
}
if (this->TexturePrefix)
{
os << indent << "TexturePrefix: " << this->TexturePrefix << "\n";
}
else
{
os << indent << "TexturePrefix: (none)\n";
}
os << indent << "Background: " << (this->Background ? "On\n" : "Off\n");
os << indent << "Size: " << this->Size[0] << " " << this->Size[1] << "\n";
os << indent << "PixelSamples: " << this->PixelSamples[0] << " "
<< this->PixelSamples[1] << "\n";
os << indent << "Export Arrays: " << (this->ExportArrays ? "On" : "Off")
<< "\n";
}
void vtkRIBExporter::WriteTexture (vtkTexture *aTexture)
{
vtkDataArray *scalars;
vtkDataArray *mappedScalars;
int *size;
int xsize, ysize;
unsigned short xs,ys;
// RtToken wrap = aTexture->GetRepeat () ? RI_PERIODIC : RI_CLAMP;
// RiMakeTexture (this->GetTIFFName (aTexture),
// this->GetTextureName (aTexture),
// wrap, wrap,
// RiBoxFilter,
// 1, 1,
// RI_NULL);
const char *wrap = aTexture->GetRepeat () ? "periodic" : "clamp";
fprintf (this->FilePtr, "MakeTexture \"%s\" ", this->GetTIFFName (aTexture));
fprintf (this->FilePtr, "\"%s\" ", this->GetTextureName (aTexture));
fprintf (this->FilePtr, "\"%s\" \"%s\" ", wrap, wrap);
fprintf (this->FilePtr, "\"%s\" 1 1\n", "box");
// do an Update and 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 = 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;
}
}
}
// xsize and ysize must be a power of 2 in OpenGL
xs = (unsigned short)xsize;
ys = (unsigned short)ysize;
while (!(xs & 0x01))
{
xs = xs >> 1;
}
while (!(ys & 0x01))
{
ys = ys >> 1;
}
if ((xs > 1)||(ys > 1))
{
vtkWarningMacro(<< "Texture map's width and height must be a power of two in RenderMan\n");
}
vtkTIFFWriter *aWriter = vtkTIFFWriter::New();
vtkImageConstantPad *icp = NULL;
vtkImageExtractComponents *iec = NULL;
vtkImageAppendComponents *iac1 = NULL;
vtkImageAppendComponents *iac2 = NULL;
vtkStructuredPoints *anImage = vtkStructuredPoints::New();
anImage->SetDimensions (xsize, ysize, 1);
anImage->SetUpdateExtent(0,xsize-1,0,ysize-1, 0, 0);
anImage->SetScalarType(mappedScalars->GetDataType());
anImage->GetPointData()->SetScalars (mappedScalars);
int bpp = mappedScalars->GetNumberOfComponents();
anImage->SetNumberOfScalarComponents (bpp);
// renderman and bmrt seem to require r,g,b and alpha in all their
// texture maps. So if our tmap doesn't have the right components
// we add them
if (bpp == 1) // needs intensity intensity and alpha
{
iac1 = vtkImageAppendComponents::New();
iac2 = vtkImageAppendComponents::New();
icp = vtkImageConstantPad::New();
iac1->SetInput(0, anImage);
iac1->SetInput(1, anImage);
iac2->SetInput(0, iac1->GetOutput ());
iac2->SetInput(1, anImage);
icp->SetInput( iac2->GetOutput ());
icp->SetConstant(255);
icp->SetOutputNumberOfScalarComponents(4);
aWriter->SetInput (icp->GetOutput());
}
else if (bpp == 2) // needs intensity intensity
{
iec = vtkImageExtractComponents::New();
iac1 = vtkImageAppendComponents::New();
iac2 = vtkImageAppendComponents::New();
iec->SetInput( anImage);
iec->SetComponents (0);
iac1->SetInput(0, iec->GetOutput ());
iac1->SetInput(1, anImage);
iac2->SetInput(0, iec->GetOutput ());
iac2->SetInput(1, iac1->GetOutput ());
aWriter->SetInput (iac2->GetOutput());
}
else if (bpp == 3) // needs alpha
{
icp = vtkImageConstantPad::New();
icp->SetInput( anImage);
icp->SetConstant(255);
icp->SetOutputNumberOfScalarComponents(4);
aWriter->SetInput (icp->GetOutput());
}
else // needs nothing
{
aWriter->SetInput (anImage);
}
aWriter->SetFileName (this->GetTIFFName (aTexture));
aWriter->Write ();
if (bpp == 1)
{
iac1->Delete ();
iac2->Delete ();
icp->Delete ();
}
else if (bpp == 2)
{
iec->Delete ();
iac1->Delete ();
iac2->Delete ();
}
else if (bpp == 3)
{
icp->Delete ();
}
aWriter->Delete();
anImage->Delete();
}
static char tiffName[4096];
static char textureName[4096];
char *vtkRIBExporter::GetTIFFName (vtkTexture *aTexture)
{
sprintf (tiffName, "%s_%p_%d.tif", this->TexturePrefix, (void *) aTexture, (int) aTexture->GetMTime ());
return tiffName;
}
char *vtkRIBExporter::GetTextureName (vtkTexture *aTexture)
{
sprintf (textureName, "%s_%p_%d.txt", this->TexturePrefix, (void *) aTexture, (int) aTexture->GetMTime ());
return textureName;
}
void vtkRIBExporter::ModifyArrayName(char *newname, const char* name)
{
if ( !newname )
{
return;
}
if ( !name )
{
*newname = 0;
return;
}
int cc = 0;
for ( cc =0; name[cc]; cc++ )
{
if ( (name[cc] >= 'A' && name[cc] <= 'Z') ||
(name[cc] >= '0' && name[cc] <= '9') ||
(name[cc] >= 'a' && name[cc] <= 'z') )
{
newname[cc] = name[cc];
}
else
{
newname[cc] = '_';
}
}
newname[cc] = 0;
}