mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
1071 lines
33 KiB
C++
1071 lines
33 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkGL2PSExporter.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 "vtkGL2PSExporter.h"
|
|
|
|
#include "vtkActor.h"
|
|
#include "vtkActor2D.h"
|
|
#include "vtkActorCollection.h"
|
|
#include "vtkActor2DCollection.h"
|
|
#include "vtkCamera.h"
|
|
#include "vtkContext2D.h"
|
|
#include "vtkContextActor.h"
|
|
#include "vtkContextScene.h"
|
|
#include "vtkCoordinate.h"
|
|
#include "vtkFloatArray.h"
|
|
#include "vtkGL2PSContextDevice2D.h"
|
|
#include "vtkGL2PSUtilities.h"
|
|
#include "vtkImageData.h"
|
|
#include "vtkImageShiftScale.h"
|
|
#include "vtkIntArray.h"
|
|
#include "vtkLabeledDataMapper.h"
|
|
#include "vtkLabeledContourMapper.h"
|
|
#include "vtkMapper2D.h"
|
|
#include "vtkMath.h"
|
|
#include "vtkMathTextUtilities.h"
|
|
#include "vtkMatrix4x4.h"
|
|
#include "vtkNew.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPath.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkProp.h"
|
|
#include "vtkProp3DCollection.h"
|
|
#include "vtkOpenGLRenderWindow.h"
|
|
#include "vtkRenderWindow.h"
|
|
#include "vtkRenderer.h"
|
|
#include "vtkRendererCollection.h"
|
|
#include "vtkScalarBarActor.h"
|
|
#include "vtkStdString.h"
|
|
#include "vtkTextActor.h"
|
|
#include "vtkTextActor3D.h"
|
|
#include "vtkTextMapper.h"
|
|
#include "vtkTextProperty.h"
|
|
#include "vtkTextRenderer.h"
|
|
#include "vtkTransform.h"
|
|
#include "vtkTransformFilter.h"
|
|
#include "vtkVolume.h"
|
|
#include "vtkVolumeCollection.h"
|
|
#include "vtkWindowToImageFilter.h"
|
|
#include "vtk_gl2ps.h"
|
|
#include "vtkOpenGLError.h"
|
|
|
|
#include <vector>
|
|
|
|
vtkStandardNewMacro(vtkGL2PSExporter)
|
|
vtkCxxSetObjectMacro(vtkGL2PSExporter, RasterExclusions, vtkPropCollection)
|
|
|
|
vtkGL2PSExporter::vtkGL2PSExporter()
|
|
{
|
|
this->RasterExclusions = NULL;
|
|
this->FilePrefix = NULL;
|
|
this->BufferSize = 4194304; // 4MB
|
|
this->Title = NULL;
|
|
this->FileFormat = EPS_FILE;
|
|
this->Sort = SIMPLE_SORT;
|
|
this->Compress = 1;
|
|
this->DrawBackground = 1;
|
|
this->SimpleLineOffset = 1;
|
|
this->Silent = 0;
|
|
this->BestRoot = 1;
|
|
this->Text = 1;
|
|
this->Landscape = 0;
|
|
this->PS3Shading = 1;
|
|
this->OcclusionCull = 1;
|
|
this->Write3DPropsAsRasterImage = 0;
|
|
this->TextAsPath = false;
|
|
this->PointSizeFactor = 5.f / 7.f;
|
|
this->LineWidthFactor = 5.f / 7.f;
|
|
}
|
|
|
|
vtkGL2PSExporter::~vtkGL2PSExporter()
|
|
{
|
|
this->SetRasterExclusions(NULL);
|
|
delete [] this->FilePrefix;
|
|
delete [] this->Title;
|
|
}
|
|
|
|
void vtkGL2PSExporter::WriteData()
|
|
{
|
|
// make sure the user specified a file prefix
|
|
if (this->FilePrefix == NULL)
|
|
{
|
|
vtkErrorMacro(<< "Please specify a file prefix to use");
|
|
return;
|
|
}
|
|
|
|
vtkOpenGLRenderWindow *renWinGL =
|
|
vtkOpenGLRenderWindow::SafeDownCast(this->RenderWindow);
|
|
if (!renWinGL)
|
|
{
|
|
vtkErrorMacro(<< "Cannot export scene -- GL2PS export only works on OpenGL"
|
|
" render windows.");
|
|
return;
|
|
}
|
|
|
|
// Get the renderers. We'll be walking through them a lot later.
|
|
vtkRendererCollection *renCol = this->RenderWindow->GetRenderers();
|
|
|
|
// Grab props that need special handling for vector output
|
|
vtkNew<vtkPropCollection> contextActorCol;
|
|
this->GetVisibleContextActors(contextActorCol.GetPointer(), renCol);
|
|
vtkNew<vtkCollection> specialPropCol;
|
|
this->RenderWindow->CaptureGL2PSSpecialProps(specialPropCol.GetPointer());
|
|
|
|
// Setup information that GL2PS will need to export the scene:
|
|
GLint options = static_cast<GLint>(this->GetGL2PSOptions());
|
|
GLint sort = static_cast<GLint>(this->GetGL2PSSort());
|
|
GLint format = static_cast<GLint>(this->GetGL2PSFormat());
|
|
int *winsize = this->RenderWindow->GetSize();
|
|
GLint viewport[4] = {0, 0, static_cast<GLint>(winsize[0]),
|
|
static_cast<GLint>(winsize[1])};
|
|
|
|
// Create the file.
|
|
char *fName = new char [strlen(this->FilePrefix) + 8];
|
|
sprintf(fName, "%s.%s%s", this->FilePrefix, this->GetFileExtension(),
|
|
this->Compress ? ".gz" : "");
|
|
FILE *fpObj = fopen(fName, "wb");
|
|
if (!fpObj)
|
|
{
|
|
vtkErrorMacro(<< "unable to open file: " << fName);
|
|
delete [] fName;
|
|
return;
|
|
}
|
|
|
|
// Setup the helper class.
|
|
vtkGL2PSUtilities::SetRenderWindow(this->RenderWindow);
|
|
vtkGL2PSUtilities::SetTextAsPath(this->TextAsPath != 0);
|
|
vtkGL2PSUtilities::SetPointSizeFactor(this->PointSizeFactor);
|
|
vtkGL2PSUtilities::SetLineWidthFactor(this->LineWidthFactor);
|
|
vtkGL2PSUtilities::StartExport();
|
|
|
|
// Store the "properly" rendered image's pixel data for special actors that
|
|
// need to copy bitmaps into the output (e.g. paraview's scalar bar actor)
|
|
vtkNew<vtkWindowToImageFilter> windowToImage;
|
|
windowToImage->SetInput(this->RenderWindow);
|
|
windowToImage->SetInputBufferTypeToRGB();
|
|
windowToImage->ReadFrontBufferOff();
|
|
|
|
// RGB buffers are captured as unsigned char, but gl2ps requires floats
|
|
vtkNew<vtkImageShiftScale> imageConverter;
|
|
imageConverter->SetOutputScalarTypeToFloat();
|
|
imageConverter->SetScale(1.0/255.0);
|
|
imageConverter->SetInputConnection(0, windowToImage->GetOutputPort(0));
|
|
|
|
// Render twice to populate back buffer with correct data
|
|
this->RenderWindow->Render();
|
|
this->RenderWindow->Render();
|
|
windowToImage->Modified();
|
|
imageConverter->Update();
|
|
this->PixelData->DeepCopy(imageConverter->GetOutput());
|
|
|
|
// Turn off special props -- these will be handled separately later.
|
|
vtkPropCollection *propCol;
|
|
for (specialPropCol->InitTraversal();
|
|
(propCol = vtkPropCollection::SafeDownCast(
|
|
specialPropCol->GetNextItemAsObject()));)
|
|
{
|
|
this->SetPropVisibilities(propCol, 0);
|
|
}
|
|
this->SetPropVisibilities(contextActorCol.GetPointer(), 0);
|
|
|
|
// Write out a raster image without the 2d actors before switching to feedback
|
|
// mode
|
|
vtkNew<vtkImageData> rasterImage;
|
|
// Store visibility of actors/volumes if rasterizing.
|
|
vtkNew<vtkIntArray> volVis;
|
|
vtkNew<vtkIntArray> actVis;
|
|
vtkNew<vtkIntArray> act2dVis;
|
|
if (this->Write3DPropsAsRasterImage)
|
|
{
|
|
vtkDebugMacro(<<"Rasterizing 3D geometry.")
|
|
this->SavePropVisibility(renCol, volVis.GetPointer(), actVis.GetPointer(),
|
|
act2dVis.GetPointer());
|
|
this->Turn2DPropsOff(renCol);
|
|
// Render twice to populate back buffer with correct data
|
|
this->RenderWindow->Render();
|
|
this->RenderWindow->Render();
|
|
windowToImage->Modified();
|
|
imageConverter->Update();
|
|
rasterImage->DeepCopy(imageConverter->GetOutput());
|
|
}
|
|
|
|
// Disable depth peeling. It uses textures that turn into large opaque quads
|
|
// in the output, and gl2ps sorts primitives itself anyway.
|
|
vtkRenderer *ren;
|
|
std::vector<bool> origDepthPeeling;
|
|
origDepthPeeling.reserve(renCol->GetNumberOfItems());
|
|
for (renCol->InitTraversal(); (ren = renCol->GetNextItem());)
|
|
{
|
|
origDepthPeeling.push_back(ren->GetUseDepthPeeling() != 0);
|
|
ren->UseDepthPeelingOff();
|
|
}
|
|
|
|
vtkDebugMacro(<<"Writing file using GL2PS");
|
|
|
|
// Check that the buffer size is sane:
|
|
if (this->BufferSize < 1024)
|
|
{
|
|
vtkDebugMacro("Initial buffer size is too small (" << this->BufferSize
|
|
<< " bytes). Increasing to 1kb.");
|
|
this->SetBufferSize(1024);
|
|
}
|
|
|
|
// Call gl2ps to generate the file.
|
|
int buffsize = this->BufferSize;
|
|
int state = GL2PS_OVERFLOW;
|
|
while(state == GL2PS_OVERFLOW)
|
|
{
|
|
gl2psBeginPage(this->Title ? this->Title : "VTK GL2PS Export", "VTK",
|
|
viewport, format, sort, options, GL_RGBA, 0,
|
|
NULL, 0, 0, 0, buffsize, fpObj, fName);
|
|
|
|
// Render non-specialized geometry by either passing in the raster image or
|
|
// rendering into the feedback buffer.
|
|
if (this->Write3DPropsAsRasterImage)
|
|
{
|
|
if (rasterImage->GetScalarType() != VTK_FLOAT)
|
|
{
|
|
vtkErrorMacro(<<"Raster image is not correctly formatted.")
|
|
}
|
|
else
|
|
{
|
|
// Dump the rendered image without 2d actors as a raster image.
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glRasterPos3f(-1.0, -1.0, 1.0);
|
|
gl2psDrawPixels(winsize[0], winsize[1], 0, 0, GL_RGB, GL_FLOAT,
|
|
static_cast<float*>(rasterImage->GetScalarPointer()));
|
|
glPopMatrix();
|
|
|
|
// Render the 2d actors alone in a vector graphic format.
|
|
this->RestorePropVisibility(renCol, volVis.GetPointer(),
|
|
actVis.GetPointer(), act2dVis.GetPointer());
|
|
this->Turn3DPropsOff(renCol);
|
|
this->RenderWindow->Render();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->RenderWindow->Render();
|
|
}
|
|
|
|
// Render props that require special handling (text, etc)
|
|
this->DrawSpecialProps(specialPropCol.GetPointer(), renCol);
|
|
|
|
// Render context 2D stuff
|
|
this->DrawContextActors(contextActorCol.GetPointer(), renCol);
|
|
|
|
state = gl2psEndPage();
|
|
if (state == GL2PS_OVERFLOW)
|
|
{
|
|
buffsize += this->BufferSize;
|
|
}
|
|
}
|
|
fclose(fpObj);
|
|
|
|
// Clean up:
|
|
vtkGL2PSUtilities::SetRenderWindow(NULL);
|
|
vtkGL2PSUtilities::SetTextAsPath(false);
|
|
// Re-enable depth peeling if needed
|
|
for (int i = 0; i < static_cast<int>(origDepthPeeling.size()); ++i)
|
|
{
|
|
vtkRenderer::SafeDownCast(renCol->GetItemAsObject(i))->SetUseDepthPeeling(
|
|
origDepthPeeling[i] ? 1 : 0);
|
|
}
|
|
if (this->Write3DPropsAsRasterImage)
|
|
{
|
|
// Reset the visibility.
|
|
this->RestorePropVisibility(renCol, volVis.GetPointer(),
|
|
actVis.GetPointer(), act2dVis.GetPointer());
|
|
}
|
|
// Turn the special props back on
|
|
for (specialPropCol->InitTraversal();
|
|
(propCol = vtkPropCollection::SafeDownCast(
|
|
specialPropCol->GetNextItemAsObject()));)
|
|
{
|
|
this->SetPropVisibilities(propCol, 1);
|
|
}
|
|
// Turn context actors back on
|
|
this->SetPropVisibilities(contextActorCol.GetPointer(), 1);
|
|
// Re-render the scene to show all actors.
|
|
this->RenderWindow->Render();
|
|
|
|
// Cleanup memory
|
|
delete[] fName;
|
|
|
|
vtkDebugMacro(<<"Finished writing file using GL2PS");
|
|
vtkGL2PSUtilities::FinishExport();
|
|
}
|
|
|
|
int vtkGL2PSExporter::GetGL2PSOptions()
|
|
{
|
|
GLint options = GL2PS_NONE;
|
|
if (this->Compress == 1)
|
|
{
|
|
options = options | GL2PS_COMPRESS;
|
|
}
|
|
if (this->DrawBackground == 1)
|
|
{
|
|
options = options | GL2PS_DRAW_BACKGROUND;
|
|
}
|
|
if (this->SimpleLineOffset == 1)
|
|
{
|
|
options = options | GL2PS_SIMPLE_LINE_OFFSET;
|
|
}
|
|
if (this->Silent == 1)
|
|
{
|
|
options = options | GL2PS_SILENT;
|
|
}
|
|
if (this->BestRoot == 1)
|
|
{
|
|
options = options | GL2PS_BEST_ROOT;
|
|
}
|
|
if (this->Text == 0)
|
|
{
|
|
options = options | GL2PS_NO_TEXT;
|
|
}
|
|
if (this->Landscape == 1)
|
|
{
|
|
options = options | GL2PS_LANDSCAPE;
|
|
}
|
|
if (this->PS3Shading == 0)
|
|
{
|
|
options = options | GL2PS_NO_PS3_SHADING;
|
|
}
|
|
if (this->OcclusionCull == 1)
|
|
{
|
|
options = options | GL2PS_OCCLUSION_CULL;
|
|
}
|
|
return static_cast<int>(options);
|
|
}
|
|
|
|
int vtkGL2PSExporter::GetGL2PSSort()
|
|
{
|
|
switch (this->Sort)
|
|
{
|
|
default:
|
|
vtkDebugMacro(<<"Invalid sort settings, using NO_SORT.");
|
|
VTK_FALLTHROUGH;
|
|
case NO_SORT:
|
|
return GL2PS_NO_SORT;
|
|
case SIMPLE_SORT:
|
|
return GL2PS_SIMPLE_SORT;
|
|
case BSP_SORT:
|
|
return GL2PS_BSP_SORT;
|
|
}
|
|
}
|
|
|
|
int vtkGL2PSExporter::GetGL2PSFormat()
|
|
{
|
|
switch (this->FileFormat)
|
|
{
|
|
default:
|
|
vtkDebugMacro(<<"Invalid output format. Using postscript.");
|
|
VTK_FALLTHROUGH;
|
|
case PS_FILE:
|
|
return GL2PS_PS;
|
|
case EPS_FILE:
|
|
return GL2PS_EPS;
|
|
case PDF_FILE:
|
|
return GL2PS_PDF;
|
|
case TEX_FILE:
|
|
return GL2PS_TEX;
|
|
case SVG_FILE:
|
|
return GL2PS_SVG;
|
|
}
|
|
}
|
|
|
|
const char *vtkGL2PSExporter::GetFileExtension()
|
|
{
|
|
switch (this->FileFormat)
|
|
{
|
|
default:
|
|
vtkDebugMacro(<<"Invalid output format. Using postscript.");
|
|
VTK_FALLTHROUGH;
|
|
case PS_FILE:
|
|
return "ps";
|
|
case EPS_FILE:
|
|
return "eps";
|
|
case PDF_FILE:
|
|
return "pdf";
|
|
case TEX_FILE:
|
|
return "tex";
|
|
case SVG_FILE:
|
|
return "svg";
|
|
}
|
|
}
|
|
|
|
void vtkGL2PSExporter::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
if (this->FilePrefix)
|
|
{
|
|
os << indent << "FilePrefix: " << this->FilePrefix << "\n";
|
|
}
|
|
else
|
|
{
|
|
os << indent << "FilePrefix: (null)\n";
|
|
}
|
|
|
|
os << indent << "FileFormat: "
|
|
<< this->GetFileFormatAsString() << "\n";
|
|
os << indent << "Sort: "
|
|
<< this->GetSortAsString() << "\n";
|
|
os << indent << "Compress: "
|
|
<< (this->Compress ? "On\n" : "Off\n");
|
|
os << indent << "DrawBackground: "
|
|
<< (this->DrawBackground ? "On\n" : "Off\n");
|
|
os << indent << "SimpleLineOffset: "
|
|
<< (this->SimpleLineOffset ? "On\n" : "Off\n");
|
|
os << indent << "Silent: "
|
|
<< (this->Silent ? "On\n" : "Off\n");
|
|
os << indent << "BestRoot: "
|
|
<< (this->BestRoot ? "On\n" : "Off\n");
|
|
os << indent << "Text: "
|
|
<< (this->Text ? "On\n" : "Off\n");
|
|
os << indent << "Landscape: "
|
|
<< (this->Landscape ? "On\n" : "Off\n");
|
|
os << indent << "PS3Shading: "
|
|
<< (this->PS3Shading ? "On\n" : "Off\n");
|
|
os << indent << "OcclusionCull: "
|
|
<< (this->OcclusionCull ? "On\n" : "Off\n");
|
|
os << indent << "Write3DPropsAsRasterImage: "
|
|
<< (this->Write3DPropsAsRasterImage ? "On\n" : "Off\n");
|
|
if (this->RasterExclusions)
|
|
{
|
|
os << indent << "RasterExclusions:\n";
|
|
this->RasterExclusions->PrintSelf(os, indent.GetNextIndent());
|
|
}
|
|
else
|
|
{
|
|
os << indent << "RasterExclusions: (null)\n";
|
|
}
|
|
}
|
|
|
|
void vtkGL2PSExporter::SavePropVisibility(vtkRendererCollection *renCol,
|
|
vtkIntArray *volVis,
|
|
vtkIntArray *actVis,
|
|
vtkIntArray *act2dVis)
|
|
{
|
|
int nRen = renCol->GetNumberOfItems();
|
|
vtkRenderer *ren;
|
|
vtkVolumeCollection *vCol;
|
|
vtkActorCollection *aCol;
|
|
vtkActor2DCollection *a2Col;
|
|
vtkVolume *vol;
|
|
vtkActor *act;
|
|
vtkActor2D *act2d;
|
|
int tuple;
|
|
|
|
volVis->SetNumberOfComponents(nRen);
|
|
actVis->SetNumberOfComponents(nRen);
|
|
act2dVis->SetNumberOfComponents(nRen);
|
|
|
|
renCol->InitTraversal();
|
|
for (int component = 0; component < nRen; ++component)
|
|
{
|
|
ren = renCol->GetNextItem();
|
|
vCol = ren->GetVolumes();
|
|
aCol = ren->GetActors();
|
|
a2Col = ren->GetActors2D();
|
|
|
|
for (vCol->InitTraversal(), tuple=0; (vol = vCol->GetNextVolume()); ++tuple)
|
|
{
|
|
volVis->InsertComponent(tuple, component, vol->GetVisibility());
|
|
}
|
|
|
|
for (aCol->InitTraversal(), tuple=0; (act = aCol->GetNextActor()); ++tuple)
|
|
{
|
|
actVis->InsertComponent(tuple, component, act->GetVisibility());
|
|
}
|
|
|
|
for (a2Col->InitTraversal(), tuple=0; (act2d = a2Col->GetNextActor2D());
|
|
++tuple)
|
|
{
|
|
act2dVis->InsertComponent(tuple, component, act2d->GetVisibility());
|
|
}
|
|
}
|
|
}
|
|
|
|
void vtkGL2PSExporter::RestorePropVisibility(vtkRendererCollection *renCol,
|
|
vtkIntArray *volVis,
|
|
vtkIntArray *actVis,
|
|
vtkIntArray *act2dVis)
|
|
{
|
|
vtkRenderer *ren;
|
|
vtkVolumeCollection *vCol;
|
|
vtkActorCollection *aCol;
|
|
vtkActor2DCollection *a2Col;
|
|
vtkVolume *vol;
|
|
vtkActor *act;
|
|
vtkActor2D *act2d;
|
|
int tuple;
|
|
int nRen = renCol->GetNumberOfItems();
|
|
|
|
renCol->InitTraversal();
|
|
for (int component = 0; component < nRen; ++component)
|
|
{
|
|
ren = renCol->GetNextItem();
|
|
vCol = ren->GetVolumes();
|
|
aCol = ren->GetActors();
|
|
a2Col = ren->GetActors2D();
|
|
|
|
for (vCol->InitTraversal(), tuple=0; (vol = vCol->GetNextVolume()); ++tuple)
|
|
{
|
|
vol->SetVisibility(static_cast<int>(volVis->GetComponent(tuple, component)));
|
|
}
|
|
|
|
for (aCol->InitTraversal(), tuple=0; (act = aCol->GetNextActor()); ++tuple)
|
|
{
|
|
act->SetVisibility(static_cast<int>(actVis->GetComponent(tuple, component)));
|
|
}
|
|
|
|
for (a2Col->InitTraversal(), tuple=0; (act2d = a2Col->GetNextActor2D());
|
|
++tuple)
|
|
{
|
|
act2d->SetVisibility(static_cast<int>(act2dVis->GetComponent(tuple, component)));
|
|
}
|
|
}
|
|
}
|
|
|
|
void vtkGL2PSExporter::Turn3DPropsOff(vtkRendererCollection *renCol)
|
|
{
|
|
vtkRenderer *ren;
|
|
vtkVolumeCollection *vCol;
|
|
vtkActorCollection *aCol;
|
|
vtkVolume *vol;
|
|
vtkActor *act;
|
|
|
|
for (renCol->InitTraversal(); (ren = renCol->GetNextItem());)
|
|
{
|
|
vCol = ren->GetVolumes();
|
|
aCol = ren->GetActors();
|
|
for (vCol->InitTraversal(); (vol = vCol->GetNextVolume());)
|
|
{
|
|
if (!this->Write3DPropsAsRasterImage ||
|
|
!this->RasterExclusions ||
|
|
!this->RasterExclusions->IsItemPresent(vol))
|
|
{
|
|
vol->SetVisibility(0);
|
|
}
|
|
}
|
|
|
|
for (aCol->InitTraversal(); (act = aCol->GetNextActor());)
|
|
{
|
|
if (!this->Write3DPropsAsRasterImage ||
|
|
!this->RasterExclusions ||
|
|
!this->RasterExclusions->IsItemPresent(act))
|
|
{
|
|
act->SetVisibility(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void vtkGL2PSExporter::Turn2DPropsOff(vtkRendererCollection *renCol)
|
|
{
|
|
vtkRenderer *ren;
|
|
vtkActor2DCollection *a2Col;
|
|
vtkActor2D *act2d;
|
|
|
|
for (renCol->InitTraversal(); (ren = renCol->GetNextItem());)
|
|
{
|
|
a2Col = ren->GetActors2D();
|
|
for (a2Col->InitTraversal(); (act2d = a2Col->GetNextActor2D());)
|
|
{
|
|
act2d->SetVisibility(0);
|
|
}
|
|
}
|
|
if (this->Write3DPropsAsRasterImage && this->RasterExclusions)
|
|
{
|
|
vtkProp *prop;
|
|
for (this->RasterExclusions->InitTraversal();
|
|
(prop = this->RasterExclusions->GetNextProp());)
|
|
{
|
|
prop->SetVisibility(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void vtkGL2PSExporter::GetVisibleContextActors(vtkPropCollection *result,
|
|
vtkRendererCollection *renCol)
|
|
{
|
|
assert("valid pointers" && result && renCol);
|
|
result->RemoveAllItems();
|
|
vtkRenderer *ren;
|
|
for (renCol->InitTraversal(); (ren = renCol->GetNextItem());)
|
|
{
|
|
vtkCollection *pCol = ren->GetViewProps();
|
|
vtkObject *object;
|
|
for (pCol->InitTraversal(); (object = pCol->GetNextItemAsObject());)
|
|
{
|
|
vtkContextActor *act = vtkContextActor::SafeDownCast(object);
|
|
if (!act || !act->GetVisibility())
|
|
{
|
|
continue;
|
|
}
|
|
if (!result->IsItemPresent(act))
|
|
{
|
|
result->AddItem(act);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void vtkGL2PSExporter::SetPropVisibilities(vtkPropCollection *col, int vis)
|
|
{
|
|
vtkProp *prop;
|
|
for (col->InitTraversal();
|
|
(prop = vtkProp::SafeDownCast(col->GetNextItemAsObject()));)
|
|
{
|
|
prop->SetVisibility(vis);
|
|
}
|
|
}
|
|
|
|
void vtkGL2PSExporter::DrawSpecialProps(vtkCollection *specialPropCol,
|
|
vtkRendererCollection *renCol)
|
|
{
|
|
vtkOpenGLClearErrorMacro();
|
|
|
|
// Iterate through the renderers and the prop collections together:
|
|
assert("renderers and special prop collections match" &&
|
|
renCol->GetNumberOfItems() == specialPropCol->GetNumberOfItems());
|
|
for (int i = 0; i < renCol->GetNumberOfItems(); ++i)
|
|
{
|
|
vtkPropCollection *propCol = vtkPropCollection::SafeDownCast(
|
|
specialPropCol->GetItemAsObject(i));
|
|
vtkRenderer *ren = vtkRenderer::SafeDownCast(renCol->GetItemAsObject(i));
|
|
|
|
// Setup the GL matrices for this renderer. This pushes the MV matrix,
|
|
// (and resets w/o pushing proj?) so we'll need to pop it later. We push the
|
|
// projection matrix ourselves.
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
ren->GetActiveCamera()->Render(ren);
|
|
|
|
// Draw special props
|
|
vtkProp *prop = 0;
|
|
for (propCol->InitTraversal(); (prop = propCol->GetNextProp());)
|
|
{
|
|
this->HandleSpecialProp(prop, ren);
|
|
}
|
|
// Pop MV matrices (This was pushed by vtkOpenGLCamera::Render earlier).
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPopMatrix();
|
|
}
|
|
|
|
vtkOpenGLCheckErrorMacro("failed after DrawSpecialProps");
|
|
}
|
|
|
|
void vtkGL2PSExporter::HandleSpecialProp(vtkProp *prop, vtkRenderer *ren)
|
|
{
|
|
// What sort of special prop is it?
|
|
if (vtkActor2D *act2d = vtkActor2D::SafeDownCast(prop))
|
|
{
|
|
if (vtkTextActor *textAct = vtkTextActor::SafeDownCast(act2d))
|
|
{
|
|
this->DrawTextActor(textAct, ren);
|
|
}
|
|
else if (vtkMapper2D *map2d = act2d->GetMapper())
|
|
{
|
|
if (vtkTextMapper *textMap = vtkTextMapper::SafeDownCast(map2d))
|
|
{
|
|
this->DrawTextMapper(textMap, act2d, ren);
|
|
}
|
|
else if (vtkLabeledDataMapper *ldm =
|
|
vtkLabeledDataMapper::SafeDownCast(map2d))
|
|
{
|
|
this->DrawLabeledDataMapper(ldm, ren);
|
|
}
|
|
else // Some other mapper2D
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else if (vtkScalarBarActor *bar = vtkScalarBarActor::SafeDownCast(act2d))
|
|
{
|
|
this->DrawScalarBarActor(bar, ren);
|
|
}
|
|
else // Some other actor2D
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else if (vtkActor *act = vtkActor::SafeDownCast(prop))
|
|
{
|
|
if (vtkLabeledContourMapper *lcm =
|
|
vtkLabeledContourMapper::SafeDownCast(act->GetMapper()))
|
|
{
|
|
this->DrawLabeledContourMapper(act, lcm, ren);
|
|
}
|
|
}
|
|
else if (vtkTextActor3D *textAct3D =
|
|
vtkTextActor3D::SafeDownCast(prop))
|
|
{
|
|
this->DrawTextActor3D(textAct3D, ren);
|
|
}
|
|
else // Some other prop
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
void vtkGL2PSExporter::DrawTextActor(vtkTextActor *textAct, vtkRenderer *ren)
|
|
{
|
|
const char *string = textAct->GetInput();
|
|
vtkCoordinate *coord = textAct->GetActualPositionCoordinate();
|
|
vtkTextProperty *tprop = textAct->GetScaledTextProperty();
|
|
|
|
this->DrawViewportTextOverlay(string, tprop, coord, ren);
|
|
}
|
|
|
|
void vtkGL2PSExporter::DrawTextActor3D(vtkTextActor3D *textAct,
|
|
vtkRenderer *ren)
|
|
{
|
|
// Get path
|
|
const char *string = textAct->GetInput();
|
|
vtkTextProperty *tprop = textAct->GetTextProperty();
|
|
vtkNew<vtkPath> textPath;
|
|
vtkTextRenderer *tren = vtkTextRenderer::GetInstance();
|
|
|
|
if (!tren)
|
|
{
|
|
vtkWarningMacro(<<"Cannot generate path data from 3D text string '"
|
|
<< string << "': Text renderer unavailable.");
|
|
return;
|
|
}
|
|
|
|
if (!tren->StringToPath(tprop, vtkStdString(string), textPath.GetPointer(),
|
|
vtkTextActor3D::GetRenderedDPI()))
|
|
{
|
|
vtkWarningMacro(<<"Failed to generate path data from 3D text string '"
|
|
<< string << "': StringToPath failed.");
|
|
return;
|
|
}
|
|
|
|
// Get actor info
|
|
vtkMatrix4x4 *actorMatrix = textAct->GetMatrix();
|
|
double *actorBounds = textAct->GetBounds();
|
|
double textPos[3] = {(actorBounds[1] + actorBounds[0]) * 0.5,
|
|
(actorBounds[3] + actorBounds[2]) * 0.5,
|
|
(actorBounds[5] + actorBounds[4]) * 0.5};
|
|
|
|
double *fgColord = tprop->GetColor();
|
|
unsigned char fgColor[4] = {
|
|
static_cast<unsigned char>(fgColord[0] * 255),
|
|
static_cast<unsigned char>(fgColord[1] * 255),
|
|
static_cast<unsigned char>(fgColord[2] * 255),
|
|
static_cast<unsigned char>(tprop->GetOpacity() * 255)};
|
|
|
|
// Draw the background quad as a path:
|
|
if (tprop->GetBackgroundOpacity() > 0.f)
|
|
{
|
|
double *bgColord = tprop->GetBackgroundColor();
|
|
unsigned char bgColor[4] = {
|
|
static_cast<unsigned char>(bgColord[0] * 255),
|
|
static_cast<unsigned char>(bgColord[1] * 255),
|
|
static_cast<unsigned char>(bgColord[2] * 255),
|
|
static_cast<unsigned char>(tprop->GetBackgroundOpacity() * 255)};
|
|
|
|
// Get the camera so we can calculate an offset to place the background
|
|
// behind the text.
|
|
vtkCamera *cam = ren->GetActiveCamera();
|
|
vtkMatrix4x4 *mat = cam->GetCompositeProjectionTransformMatrix(
|
|
ren->GetTiledAspectRatio(), 0., 1.);
|
|
double forward[3] = {mat->GetElement(2, 0),
|
|
mat->GetElement(2, 1),
|
|
mat->GetElement(2, 2)};
|
|
vtkMath::Normalize(forward);
|
|
double bgPos[3] = {textPos[0] + (forward[0] * 0.0001),
|
|
textPos[1] + (forward[1] * 0.0001),
|
|
textPos[2] + (forward[2] * 0.0001)};
|
|
|
|
vtkTextRenderer::Metrics metrics;
|
|
if (tren->GetMetrics(tprop, string, metrics,
|
|
vtkTextActor3D::GetRenderedDPI()))
|
|
{
|
|
vtkNew<vtkPath> bgPath;
|
|
bgPath->InsertNextPoint(static_cast<double>(metrics.TopLeft.GetX()),
|
|
static_cast<double>(metrics.TopLeft.GetY()),
|
|
0., vtkPath::MOVE_TO);
|
|
bgPath->InsertNextPoint(static_cast<double>(metrics.TopRight.GetX()),
|
|
static_cast<double>(metrics.TopRight.GetY()),
|
|
0., vtkPath::LINE_TO);
|
|
bgPath->InsertNextPoint(static_cast<double>(metrics.BottomRight.GetX()),
|
|
static_cast<double>(metrics.BottomRight.GetY()),
|
|
0., vtkPath::LINE_TO);
|
|
bgPath->InsertNextPoint(static_cast<double>(metrics.BottomLeft.GetX()),
|
|
static_cast<double>(metrics.BottomLeft.GetY()),
|
|
0., vtkPath::LINE_TO);
|
|
bgPath->InsertNextPoint(static_cast<double>(metrics.TopLeft.GetX()),
|
|
static_cast<double>(metrics.TopLeft.GetY()),
|
|
0., vtkPath::LINE_TO);
|
|
|
|
vtkGL2PSUtilities::Draw3DPath(bgPath.GetPointer(), actorMatrix, bgPos,
|
|
bgColor);
|
|
}
|
|
}
|
|
|
|
// Draw the text path:
|
|
vtkGL2PSUtilities::Draw3DPath(textPath.GetPointer(), actorMatrix, textPos,
|
|
fgColor);
|
|
}
|
|
|
|
void vtkGL2PSExporter::DrawTextMapper(vtkTextMapper *textMap,
|
|
vtkActor2D *textAct,
|
|
vtkRenderer *ren)
|
|
{
|
|
const char *string = textMap->GetInput();
|
|
vtkCoordinate *coord = textAct->GetActualPositionCoordinate();
|
|
vtkTextProperty *tprop = textMap->GetTextProperty();
|
|
|
|
this->DrawViewportTextOverlay(string, tprop, coord, ren);
|
|
}
|
|
|
|
void vtkGL2PSExporter::DrawLabeledDataMapper(vtkLabeledDataMapper *mapper,
|
|
vtkRenderer *ren)
|
|
{
|
|
vtkNew<vtkCoordinate> coord;
|
|
coord->SetViewport(ren);
|
|
switch (mapper->GetCoordinateSystem())
|
|
{
|
|
case vtkLabeledDataMapper::WORLD:
|
|
coord->SetCoordinateSystem(VTK_WORLD);
|
|
break;
|
|
case vtkLabeledDataMapper::DISPLAY:
|
|
coord->SetCoordinateSystem(VTK_DISPLAY);
|
|
break;
|
|
default:
|
|
vtkWarningMacro("Unsupported coordinate system for exporting vtkLabeled"
|
|
"DataMapper. Some text may not be exported properly.");
|
|
return;
|
|
}
|
|
|
|
int numberOfLabels = mapper->GetNumberOfLabels();
|
|
const char *text;
|
|
double position[3];
|
|
|
|
for (int i = 0; i < numberOfLabels; ++i)
|
|
{
|
|
text = mapper->GetLabelText(i);
|
|
mapper->GetLabelPosition(i, position);
|
|
coord->SetValue(position);
|
|
this->DrawViewportTextOverlay(text, mapper->GetLabelTextProperty(),
|
|
coord.GetPointer(), ren);
|
|
}
|
|
}
|
|
|
|
void vtkGL2PSExporter::DrawLabeledContourMapper(vtkActor *act,
|
|
vtkLabeledContourMapper *mapper,
|
|
vtkRenderer *ren)
|
|
{
|
|
bool oldLabelVisibility = mapper->GetLabelVisibility();
|
|
mapper->LabelVisibilityOff();
|
|
act->RenderOpaqueGeometry(ren);
|
|
act->RenderTranslucentPolygonalGeometry(ren);
|
|
act->RenderOverlay(ren);
|
|
mapper->SetLabelVisibility(oldLabelVisibility);
|
|
}
|
|
|
|
void vtkGL2PSExporter::DrawScalarBarActor(vtkScalarBarActor *bar,
|
|
vtkRenderer *ren)
|
|
{
|
|
// Disable colorbar -- the texture doesn't render properly, we'll copy the
|
|
// rasterized pixel data for it.
|
|
int drawColorBarOrig(bar->GetDrawColorBar());
|
|
bar->SetDrawColorBar(0);
|
|
|
|
// Disable text -- it is handled separately
|
|
int drawTickLabelsOrig(bar->GetDrawTickLabels());
|
|
bar->SetDrawTickLabels(0);
|
|
int drawAnnotationsOrig(bar->GetDrawAnnotations());
|
|
bar->SetDrawAnnotations(0);
|
|
|
|
// Render what's left:
|
|
bar->RenderOpaqueGeometry(ren);
|
|
bar->RenderOverlay(ren);
|
|
|
|
// Restore settings
|
|
bar->SetDrawColorBar(drawColorBarOrig);
|
|
bar->SetDrawTickLabels(drawTickLabelsOrig);
|
|
bar->SetDrawAnnotations(drawAnnotationsOrig);
|
|
|
|
// Copy the color bar into the output.
|
|
int rect[4];
|
|
bar->GetScalarBarRect(rect, ren);
|
|
this->CopyPixels(rect, ren);
|
|
}
|
|
|
|
void vtkGL2PSExporter::DrawViewportTextOverlay(const char *string,
|
|
vtkTextProperty *tprop,
|
|
vtkCoordinate *coord,
|
|
vtkRenderer *ren)
|
|
{
|
|
vtkOpenGLClearErrorMacro();
|
|
|
|
// Figure out the viewport information
|
|
int *winsize = this->RenderWindow->GetSize();
|
|
double *viewport = ren->GetViewport();
|
|
int viewportPixels[4] = {static_cast<int>(viewport[0] * winsize[0]),
|
|
static_cast<int>(viewport[1] * winsize[1]),
|
|
static_cast<int>(viewport[2] * winsize[0]),
|
|
static_cast<int>(viewport[3] * winsize[1])};
|
|
int viewportSpread[2] = {viewportPixels[2] - viewportPixels[0],
|
|
viewportPixels[3] - viewportPixels[1]};
|
|
|
|
// Get viewport coord
|
|
double *textPos2 = coord->GetComputedDoubleViewportValue(ren);
|
|
|
|
// convert to NDC with z on the near plane
|
|
double textPos[3];
|
|
textPos[0] = (2. * textPos2[0] / static_cast<double>(viewportSpread[0])) - 1.;
|
|
textPos[1] = (2. * textPos2[1] / static_cast<double>(viewportSpread[1])) - 1.;
|
|
textPos[2] = -1.;
|
|
|
|
// Setup the GL state to render into the viewport
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glViewport(viewportPixels[0], viewportPixels[1],
|
|
viewportSpread[0], viewportSpread[1]);
|
|
|
|
vtkGL2PSUtilities::DrawString(string, tprop, textPos, textPos[2] + 1e-6);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
|
|
vtkOpenGLCheckErrorMacro("failed after DrawViewportTextOverlay");
|
|
}
|
|
|
|
|
|
void vtkGL2PSExporter::CopyPixels(int copyRect[4], vtkRenderer *ren)
|
|
{
|
|
if (this->PixelData->GetScalarType() != VTK_FLOAT)
|
|
{
|
|
vtkErrorMacro(<<"Raster image is not correctly formatted.")
|
|
return;
|
|
}
|
|
|
|
vtkOpenGLClearErrorMacro();
|
|
|
|
// Figure out the viewport information
|
|
int *winsize = this->RenderWindow->GetSize();
|
|
double *viewport = ren->GetViewport();
|
|
int viewportPixels[4] = {static_cast<int>(viewport[0] * winsize[0]),
|
|
static_cast<int>(viewport[1] * winsize[1]),
|
|
static_cast<int>(viewport[2] * winsize[0]),
|
|
static_cast<int>(viewport[3] * winsize[1])};
|
|
int viewportSpread[2] = {viewportPixels[2] - viewportPixels[0],
|
|
viewportPixels[3] - viewportPixels[1]};
|
|
|
|
// convert to NDC with z on the near plane
|
|
double pos[3];
|
|
pos[0] = (2. * copyRect[0] / static_cast<double>(viewportSpread[0])) - 1.;
|
|
pos[1] = (2. * copyRect[1] / static_cast<double>(viewportSpread[1])) - 1.;
|
|
pos[2] = -1;
|
|
|
|
// Setup the GL state to render into the viewport
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glViewport(viewportPixels[0], viewportPixels[1],
|
|
viewportSpread[0], viewportSpread[1]);
|
|
|
|
int pixelDataDims[3];
|
|
this->PixelData->GetDimensions(pixelDataDims);
|
|
|
|
// Copy the relevant rectangle of pixel data memory into a new array.
|
|
float *dest = new float[copyRect[2] * copyRect[3] * 3];
|
|
int destWidth = copyRect[2] * 3;
|
|
int destWidthBytes = destWidth * sizeof(float);
|
|
int sourceWidth = pixelDataDims[0] * 3;
|
|
int sourceOffset = copyRect[0] * 3;
|
|
|
|
float *pixelArray = static_cast<float*>(this->PixelData->GetScalarPointer());
|
|
|
|
for (int row = 0;
|
|
row < copyRect[3] && // Copy until the top of the copyRect is reached,
|
|
row + copyRect[1] < pixelDataDims[1]; // or we exceed the cache
|
|
++row)
|
|
{
|
|
memcpy(dest + (row * destWidth),
|
|
pixelArray + ((copyRect[1] + row) * sourceWidth) + sourceOffset,
|
|
destWidthBytes);
|
|
}
|
|
|
|
// Inject the copied pixel buffer into gl2ps
|
|
glRasterPos3dv(pos);
|
|
gl2psDrawPixels(copyRect[2], copyRect[3], 0, 0, GL_RGB, GL_FLOAT, dest);
|
|
|
|
delete [] dest;
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
|
|
vtkOpenGLCheckErrorMacro("failed after CopyPixels");
|
|
}
|
|
|
|
void vtkGL2PSExporter::DrawContextActors(vtkPropCollection *contextActs,
|
|
vtkRendererCollection *renCol)
|
|
{
|
|
if (contextActs->GetNumberOfItems() != 0)
|
|
{
|
|
vtkNew<vtkContext2D> context;
|
|
vtkNew<vtkGL2PSContextDevice2D> gl2psDevice;
|
|
|
|
// Render ContextActors. Iterate through all actors again instead of using
|
|
// the collected actors (contextActs), since we need to know which
|
|
// actors belong to which renderers.
|
|
vtkRenderer *ren;
|
|
for (renCol->InitTraversal(); (ren = renCol->GetNextItem());)
|
|
{
|
|
gl2psDevice->Begin(ren);
|
|
context->Begin(gl2psDevice.GetPointer());
|
|
|
|
vtkContextActor *act;
|
|
vtkCollection *pCol = ren->GetViewProps();
|
|
for (pCol->InitTraversal();
|
|
(act = vtkContextActor::SafeDownCast(pCol->GetNextItemAsObject()));)
|
|
{
|
|
if (act)
|
|
{
|
|
act->SetVisibility(1);
|
|
act->GetScene()->SetGeometry(ren->GetSize());
|
|
act->GetScene()->Paint(context.GetPointer());
|
|
act->SetVisibility(0);
|
|
}
|
|
}
|
|
|
|
context->End();
|
|
gl2psDevice->End();
|
|
}
|
|
}
|
|
|
|
}
|