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.
1428 lines
40 KiB
1428 lines
40 KiB
2 years ago
|
/*=========================================================================
|
||
|
|
||
|
Program: Visualization Toolkit
|
||
|
Module: $RCSfile: vtkRIBExporter.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 "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"
|
||
|
|
||
|
vtkCxxRevisionMacro(vtkRIBExporter, "$Revision: 1.63 $");
|
||
|
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->GetColor();
|
||
|
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;
|
||
|
ostrstream 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 << "] ";
|
||
|
}
|
||
|
str_with_warning_C4701 << ends;
|
||
|
fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str() );
|
||
|
str_with_warning_C4701.rdbuf()->freeze(0);
|
||
|
}
|
||
|
|
||
|
if ( cellData )
|
||
|
{
|
||
|
int cc, aa;
|
||
|
ostrstream 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 << "] ";
|
||
|
}
|
||
|
str_with_warning_C4701 << ends;
|
||
|
fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str() );
|
||
|
str_with_warning_C4701.rdbuf()->freeze(0);
|
||
|
}
|
||
|
|
||
|
if ( fieldData )
|
||
|
{
|
||
|
int cc, aa;
|
||
|
ostrstream 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 << "] ";
|
||
|
}
|
||
|
str_with_warning_C4701 << ends;
|
||
|
fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str() );
|
||
|
str_with_warning_C4701.rdbuf()->freeze(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
ostrstream 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 << "] ";
|
||
|
}
|
||
|
str_with_warning_C4701 << ends;
|
||
|
fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str() );
|
||
|
str_with_warning_C4701.rdbuf()->freeze(0);
|
||
|
}
|
||
|
|
||
|
if ( cellData )
|
||
|
{
|
||
|
int cc, aa;
|
||
|
ostrstream 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 << "] ";
|
||
|
}
|
||
|
str_with_warning_C4701 << ends;
|
||
|
fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str() );
|
||
|
str_with_warning_C4701.rdbuf()->freeze(0);
|
||
|
}
|
||
|
|
||
|
if ( fieldData )
|
||
|
{
|
||
|
int cc, aa;
|
||
|
ostrstream 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 << "] ";
|
||
|
}
|
||
|
str_with_warning_C4701 << ends;
|
||
|
fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str() );
|
||
|
str_with_warning_C4701.rdbuf()->freeze(0);
|
||
|
}
|
||
|
}
|
||
|
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;
|
||
|
}
|