diff --git a/CMake/vtkBackends.cmake b/CMake/vtkBackends.cmake index 85a972fd826..67d32fb0965 100644 --- a/CMake/vtkBackends.cmake +++ b/CMake/vtkBackends.cmake @@ -59,4 +59,5 @@ if (VTK_RENDERING_BACKEND STREQUAL "None") vtk_module(vtkRenderingNone ) vtk_module(vtkRenderingContextNone ) vtk_module(vtkRenderingVolumeNone ) + vtk_module(vtkIOExportNone ) # GL2PSExporter differs on OGL backends endif() diff --git a/Common/Core/vtkObjectFactory.cxx b/Common/Core/vtkObjectFactory.cxx index 14690f1c9a5..bf30e5ef2e3 100644 --- a/Common/Core/vtkObjectFactory.cxx +++ b/Common/Core/vtkObjectFactory.cxx @@ -46,7 +46,8 @@ static vtkCleanUpObjectFactory vtkCleanUpObjectFactoryGlobal; // Create an instance of a named vtk object using the loaded // factories -vtkObject* vtkObjectFactory::CreateInstance(const char* vtkclassname) +vtkObject* vtkObjectFactory::CreateInstance(const char* vtkclassname, + bool isAbstract) { if(!vtkObjectFactory::RegisteredFactories) { @@ -68,9 +69,12 @@ vtkObject* vtkObjectFactory::CreateInstance(const char* vtkclassname) // if the factory does not create the object, then // the object will be created with the name passed in, // so register the construction + if (!isAbstract) + { #ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::ConstructClass(vtkclassname); + vtkDebugLeaks::ConstructClass(vtkclassname); #endif + } return 0; } diff --git a/Common/Core/vtkObjectFactory.h b/Common/Core/vtkObjectFactory.h index c5d9c578171..b6590a2bfdc 100644 --- a/Common/Core/vtkObjectFactory.h +++ b/Common/Core/vtkObjectFactory.h @@ -52,7 +52,11 @@ class VTKCOMMONCORE_EXPORT vtkObjectFactory : public vtkObject // Each loaded vtkObjectFactory will be asked in the order // the factory was in the VTK_AUTOLOAD_PATH. After the // first factory returns the object no other factories are asked. - static vtkObject* CreateInstance(const char* vtkclassname); + // If the requested class is abstract, set isAbstract to true. Otherwise + // it is assumed that an instance of 'vtkclassname' will be instantiated + // by the caller when no override is found. + static vtkObject* CreateInstance(const char* vtkclassname, + bool isAbstract = false); // Description: // Call vtkDebugLeaks::ConstructClass if necessary. Does not attempt @@ -284,7 +288,7 @@ vtkObjectFactory* vtkLoad() \ // Macro to implement the body of the object factory form of the New() method. #define VTK_OBJECT_FACTORY_NEW_BODY(thisClass) \ - vtkObject* ret = vtkObjectFactory::CreateInstance(#thisClass); \ + vtkObject* ret = vtkObjectFactory::CreateInstance(#thisClass, false); \ if(ret) \ { \ return static_cast(ret); \ @@ -295,7 +299,7 @@ vtkObjectFactory* vtkLoad() \ // method, i.e. an abstract base class that can only be instantiated if the // object factory overrides it. #define VTK_ABSTRACT_OBJECT_FACTORY_NEW_BODY(thisClass) \ - vtkObject* ret = vtkObjectFactory::CreateInstance(#thisClass); \ + vtkObject* ret = vtkObjectFactory::CreateInstance(#thisClass, true); \ if(ret) \ { \ return static_cast(ret); \ diff --git a/IO/Export/module.cmake b/IO/Export/module.cmake index fcf2babd7fb..99ecb6cfa45 100644 --- a/IO/Export/module.cmake +++ b/IO/Export/module.cmake @@ -1,20 +1,16 @@ if(VTK_RENDERING_BACKEND STREQUAL "OpenGL") set(opengl_depends vtkRenderingGL2PS) set(private_opengl_depends vtkgl2ps) + set(test_opengl_depends vtkIOExportOpenGL) endif() vtk_module(vtkIOExport GROUPS Rendering DEPENDS vtkCommonCore - vtkRenderingAnnotation - vtkRenderingContext2D - vtkRenderingCore - vtkRenderingFreeType ${opengl_depends} - vtkRenderingLabel - vtkRendering${VTK_RENDERING_BACKEND} vtkImagingCore + vtkRenderingCore PRIVATE_DEPENDS vtkIOImage vtkFiltersGeometry @@ -23,9 +19,11 @@ vtk_module(vtkIOExport vtkCommonColor vtkChartsCore vtkInteractionImage + ${test_opengl_depends} vtkTestingRendering vtkInteractionStyle vtkRenderingAnnotation + vtkRenderingLabel vtkRenderingVolume${VTK_RENDERING_BACKEND} vtkRenderingContext${VTK_RENDERING_BACKEND} vtkViewsContext2D diff --git a/IO/Export/vtkGL2PSExporter.cxx b/IO/Export/vtkGL2PSExporter.cxx index 830c544bc3d..f88cfe052a0 100644 --- a/IO/Export/vtkGL2PSExporter.cxx +++ b/IO/Export/vtkGL2PSExporter.cxx @@ -15,55 +15,15 @@ #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 "vtkPropCollection.h" + #include "vtk_gl2ps.h" -#include "vtkOpenGLError.h" #include -vtkStandardNewMacro(vtkGL2PSExporter) +vtkAbstractObjectFactoryNewMacro(vtkGL2PSExporter) vtkCxxSetObjectMacro(vtkGL2PSExporter, RasterExclusions, vtkPropCollection) vtkGL2PSExporter::vtkGL2PSExporter() @@ -96,220 +56,6 @@ vtkGL2PSExporter::~vtkGL2PSExporter() 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 contextActorCol; - this->GetVisibleContextActors(contextActorCol.GetPointer(), renCol); - vtkNew specialPropCol; - this->RenderWindow->CaptureGL2PSSpecialProps(specialPropCol.GetPointer()); - - // Setup information that GL2PS will need to export the scene: - GLint options = static_cast(this->GetGL2PSOptions()); - GLint sort = static_cast(this->GetGL2PSSort()); - GLint format = static_cast(this->GetGL2PSFormat()); - int *winsize = this->RenderWindow->GetSize(); - GLint viewport[4] = {0, 0, static_cast(winsize[0]), - static_cast(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 windowToImage; - windowToImage->SetInput(this->RenderWindow); - windowToImage->SetInputBufferTypeToRGB(); - windowToImage->ReadFrontBufferOff(); - - // RGB buffers are captured as unsigned char, but gl2ps requires floats - vtkNew 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 rasterImage; - // Store visibility of actors/volumes if rasterizing. - vtkNew volVis; - vtkNew actVis; - vtkNew 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 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(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(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; @@ -455,616 +201,3 @@ void vtkGL2PSExporter::PrintSelf(ostream& os, vtkIndent indent) 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(volVis->GetComponent(tuple, component))); - } - - for (aCol->InitTraversal(), tuple=0; (act = aCol->GetNextActor()); ++tuple) - { - act->SetVisibility(static_cast(actVis->GetComponent(tuple, component))); - } - - for (a2Col->InitTraversal(), tuple=0; (act2d = a2Col->GetNextActor2D()); - ++tuple) - { - act2d->SetVisibility(static_cast(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 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(fgColord[0] * 255), - static_cast(fgColord[1] * 255), - static_cast(fgColord[2] * 255), - static_cast(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(bgColord[0] * 255), - static_cast(bgColord[1] * 255), - static_cast(bgColord[2] * 255), - static_cast(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 bgPath; - bgPath->InsertNextPoint(static_cast(metrics.TopLeft.GetX()), - static_cast(metrics.TopLeft.GetY()), - 0., vtkPath::MOVE_TO); - bgPath->InsertNextPoint(static_cast(metrics.TopRight.GetX()), - static_cast(metrics.TopRight.GetY()), - 0., vtkPath::LINE_TO); - bgPath->InsertNextPoint(static_cast(metrics.BottomRight.GetX()), - static_cast(metrics.BottomRight.GetY()), - 0., vtkPath::LINE_TO); - bgPath->InsertNextPoint(static_cast(metrics.BottomLeft.GetX()), - static_cast(metrics.BottomLeft.GetY()), - 0., vtkPath::LINE_TO); - bgPath->InsertNextPoint(static_cast(metrics.TopLeft.GetX()), - static_cast(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 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(viewport[0] * winsize[0]), - static_cast(viewport[1] * winsize[1]), - static_cast(viewport[2] * winsize[0]), - static_cast(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(viewportSpread[0])) - 1.; - textPos[1] = (2. * textPos2[1] / static_cast(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(viewport[0] * winsize[0]), - static_cast(viewport[1] * winsize[1]), - static_cast(viewport[2] * winsize[0]), - static_cast(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(viewportSpread[0])) - 1.; - pos[1] = (2. * copyRect[1] / static_cast(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(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 context; - vtkNew 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(); - } - } - -} diff --git a/IO/Export/vtkGL2PSExporter.h b/IO/Export/vtkGL2PSExporter.h index 12c369078cd..d453d661516 100644 --- a/IO/Export/vtkGL2PSExporter.h +++ b/IO/Export/vtkGL2PSExporter.h @@ -71,6 +71,7 @@ // .SECTION Thanks // Thanks to Goodwin Lawlor and Prabhu Ramachandran for this class. +class vtkPropCollection; #ifndef vtkGL2PSExporter_h #define vtkGL2PSExporter_h @@ -80,32 +81,11 @@ #include "vtkNew.h" // For vtkNew -class vtkActor; -class vtkActor2D; -class vtkCollection; -class vtkCoordinate; -class vtkImageData; -class vtkIntArray; -class vtkLabeledDataMapper; -class vtkLabeledContourMapper; -class vtkMatrix4x4; -class vtkPath; -class vtkProp; -class vtkPropCollection; -class vtkProp3DCollection; -class vtkRenderer; -class vtkRendererCollection; -class vtkScalarBarActor; -class vtkTextActor; -class vtkTextActor3D; -class vtkTextMapper; -class vtkTextProperty; - class VTKIOEXPORT_EXPORT vtkGL2PSExporter : public vtkExporter { public: static vtkGL2PSExporter *New(); - vtkTypeMacro(vtkGL2PSExporter,vtkExporter); + vtkTypeMacro(vtkGL2PSExporter, vtkExporter) void PrintSelf(ostream& os, vtkIndent indent); // Description: @@ -308,50 +288,11 @@ class VTKIOEXPORT_EXPORT vtkGL2PSExporter : public vtkExporter vtkGL2PSExporter(); ~vtkGL2PSExporter(); - void WriteData(); - int GetGL2PSOptions(); int GetGL2PSSort(); int GetGL2PSFormat(); const char *GetFileExtension(); - void SavePropVisibility(vtkRendererCollection *renCol, - vtkIntArray *volVis, vtkIntArray *actVis, - vtkIntArray *act2dVis); - void RestorePropVisibility(vtkRendererCollection *renCol, - vtkIntArray *volVis, vtkIntArray *actVis, - vtkIntArray *act2dVis); - void Turn3DPropsOff(vtkRendererCollection *renCol); - void Turn2DPropsOff(vtkRendererCollection *renCol); - void GetVisibleContextActors(vtkPropCollection *contextActors, - vtkRendererCollection *renCol); - void SetPropVisibilities(vtkPropCollection *col, int vis); - - void DrawSpecialProps(vtkCollection *propCol, vtkRendererCollection *renCol); - // Description: - // Reimplement this to handle your own special props. Must call this function - // at the end of the override for default handling. - virtual void HandleSpecialProp(vtkProp *prop, vtkRenderer *ren); - void DrawTextActor(vtkTextActor *textAct, vtkRenderer *ren); - void DrawTextActor3D(vtkTextActor3D *textAct, vtkRenderer *ren); - void DrawTextMapper(vtkTextMapper *textMap, vtkActor2D *textAct, - vtkRenderer *ren); - void DrawLabeledDataMapper(vtkLabeledDataMapper *mapper, vtkRenderer *ren); - void DrawLabeledContourMapper(vtkActor *act, vtkLabeledContourMapper *mapper, - vtkRenderer *ren); - void DrawScalarBarActor(vtkScalarBarActor *bar, vtkRenderer *ren); - void DrawViewportTextOverlay(const char *string, vtkTextProperty *tprop, - vtkCoordinate *coord, vtkRenderer *ren); - - // Description: - // Copy the region copyRect from the framebuffer into the gl2ps document. - // copyRect is in viewport coordinates [xmin, ymin, width, height]. - void CopyPixels(int copyRect[4], vtkRenderer *ren); - - void DrawContextActors(vtkPropCollection *contextActs, - vtkRendererCollection *renCol); - - vtkPropCollection *RasterExclusions; char *FilePrefix; @@ -373,8 +314,6 @@ class VTKIOEXPORT_EXPORT vtkGL2PSExporter : public vtkExporter float PointSizeFactor; float LineWidthFactor; - vtkNew PixelData; - private: vtkGL2PSExporter(const vtkGL2PSExporter&); // Not implemented void operator=(const vtkGL2PSExporter&); // Not implemented diff --git a/IO/ExportOpenGL/CMakeLists.txt b/IO/ExportOpenGL/CMakeLists.txt new file mode 100644 index 00000000000..c19f8112376 --- /dev/null +++ b/IO/ExportOpenGL/CMakeLists.txt @@ -0,0 +1,13 @@ +include(vtkObjectFactory) +vtk_add_override(vtkGL2PSExporter vtkOpenGLGL2PSExporter) +vtk_object_factory_configure("${vtk_module_overrides}") + +set(Module_SRCS + vtkOpenGLGL2PSExporter.cxx + ${CMAKE_CURRENT_BINARY_DIR}/${vtk-module}ObjectFactory.cxx +) + +vtk_module_library(${vtk-module} ${Module_SRCS}) + +include(vtkOpenGL) +vtk_opengl_link(${vtk-module}) diff --git a/IO/ExportOpenGL/module.cmake b/IO/ExportOpenGL/module.cmake new file mode 100644 index 00000000000..3c97fe4da30 --- /dev/null +++ b/IO/ExportOpenGL/module.cmake @@ -0,0 +1,19 @@ +vtk_module(vtkIOExportOpenGL + IMPLEMENTS + vtkIOExport + BACKEND + OpenGL + DEPENDS + vtkCommonCore + vtkIOExport + vtkRenderingAnnotation + vtkRenderingContext2D + vtkRenderingCore + vtkRenderingFreeType + vtkRenderingGL2PS + vtkRenderingLabel + vtkRendering${VTK_RENDERING_BACKEND} + PRIVATE_DEPENDS + vtkgl2ps + EXCLUDE_FROM_WRAPPING +) diff --git a/IO/ExportOpenGL/vtkOpenGLGL2PSExporter.cxx b/IO/ExportOpenGL/vtkOpenGLGL2PSExporter.cxx new file mode 100644 index 00000000000..4814cd434ed --- /dev/null +++ b/IO/ExportOpenGL/vtkOpenGLGL2PSExporter.cxx @@ -0,0 +1,906 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: vtkOpenGLGL2PSExporter.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 "vtkOpenGLGL2PSExporter.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 "vtkOpenGLError.h" + +#include "vtk_gl2ps.h" + +#include + +vtkStandardNewMacro(vtkOpenGLGL2PSExporter) + +vtkOpenGLGL2PSExporter::vtkOpenGLGL2PSExporter() +{ +} + +vtkOpenGLGL2PSExporter::~vtkOpenGLGL2PSExporter() +{ +} + +void vtkOpenGLGL2PSExporter::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 contextActorCol; + this->GetVisibleContextActors(contextActorCol.GetPointer(), renCol); + vtkNew specialPropCol; + this->RenderWindow->CaptureGL2PSSpecialProps(specialPropCol.GetPointer()); + + // Setup information that GL2PS will need to export the scene: + GLint options = static_cast(this->GetGL2PSOptions()); + GLint sort = static_cast(this->GetGL2PSSort()); + GLint format = static_cast(this->GetGL2PSFormat()); + int *winsize = this->RenderWindow->GetSize(); + GLint viewport[4] = {0, 0, static_cast(winsize[0]), + static_cast(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 windowToImage; + windowToImage->SetInput(this->RenderWindow); + windowToImage->SetInputBufferTypeToRGB(); + windowToImage->ReadFrontBufferOff(); + + // RGB buffers are captured as unsigned char, but gl2ps requires floats + vtkNew 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 rasterImage; + // Store visibility of actors/volumes if rasterizing. + vtkNew volVis; + vtkNew actVis; + vtkNew 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 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(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(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(); +} + +void vtkOpenGLGL2PSExporter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +void vtkOpenGLGL2PSExporter::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 vtkOpenGLGL2PSExporter::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(volVis->GetComponent(tuple, component))); + } + + for (aCol->InitTraversal(), tuple=0; (act = aCol->GetNextActor()); ++tuple) + { + act->SetVisibility(static_cast(actVis->GetComponent(tuple, component))); + } + + for (a2Col->InitTraversal(), tuple=0; (act2d = a2Col->GetNextActor2D()); + ++tuple) + { + act2d->SetVisibility(static_cast(act2dVis->GetComponent(tuple, component))); + } + } +} + +void vtkOpenGLGL2PSExporter::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 vtkOpenGLGL2PSExporter::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 vtkOpenGLGL2PSExporter::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 vtkOpenGLGL2PSExporter::SetPropVisibilities(vtkPropCollection *col, int vis) +{ + vtkProp *prop; + for (col->InitTraversal(); + (prop = vtkProp::SafeDownCast(col->GetNextItemAsObject()));) + { + prop->SetVisibility(vis); + } +} + +void vtkOpenGLGL2PSExporter::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 vtkOpenGLGL2PSExporter::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 vtkOpenGLGL2PSExporter::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 vtkOpenGLGL2PSExporter::DrawTextActor3D(vtkTextActor3D *textAct, + vtkRenderer *ren) +{ + // Get path + const char *string = textAct->GetInput(); + vtkTextProperty *tprop = textAct->GetTextProperty(); + vtkNew 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(fgColord[0] * 255), + static_cast(fgColord[1] * 255), + static_cast(fgColord[2] * 255), + static_cast(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(bgColord[0] * 255), + static_cast(bgColord[1] * 255), + static_cast(bgColord[2] * 255), + static_cast(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 bgPath; + bgPath->InsertNextPoint(static_cast(metrics.TopLeft.GetX()), + static_cast(metrics.TopLeft.GetY()), + 0., vtkPath::MOVE_TO); + bgPath->InsertNextPoint(static_cast(metrics.TopRight.GetX()), + static_cast(metrics.TopRight.GetY()), + 0., vtkPath::LINE_TO); + bgPath->InsertNextPoint(static_cast(metrics.BottomRight.GetX()), + static_cast(metrics.BottomRight.GetY()), + 0., vtkPath::LINE_TO); + bgPath->InsertNextPoint(static_cast(metrics.BottomLeft.GetX()), + static_cast(metrics.BottomLeft.GetY()), + 0., vtkPath::LINE_TO); + bgPath->InsertNextPoint(static_cast(metrics.TopLeft.GetX()), + static_cast(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 vtkOpenGLGL2PSExporter::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 vtkOpenGLGL2PSExporter::DrawLabeledDataMapper(vtkLabeledDataMapper *mapper, + vtkRenderer *ren) +{ + vtkNew 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 vtkOpenGLGL2PSExporter::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 vtkOpenGLGL2PSExporter::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 vtkOpenGLGL2PSExporter::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(viewport[0] * winsize[0]), + static_cast(viewport[1] * winsize[1]), + static_cast(viewport[2] * winsize[0]), + static_cast(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(viewportSpread[0])) - 1.; + textPos[1] = (2. * textPos2[1] / static_cast(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 vtkOpenGLGL2PSExporter::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(viewport[0] * winsize[0]), + static_cast(viewport[1] * winsize[1]), + static_cast(viewport[2] * winsize[0]), + static_cast(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(viewportSpread[0])) - 1.; + pos[1] = (2. * copyRect[1] / static_cast(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(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 vtkOpenGLGL2PSExporter::DrawContextActors(vtkPropCollection *contextActs, + vtkRendererCollection *renCol) +{ + if (contextActs->GetNumberOfItems() != 0) + { + vtkNew context; + vtkNew 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(); + } + } +} diff --git a/IO/ExportOpenGL/vtkOpenGLGL2PSExporter.h b/IO/ExportOpenGL/vtkOpenGLGL2PSExporter.h new file mode 100644 index 00000000000..a47a837ea1c --- /dev/null +++ b/IO/ExportOpenGL/vtkOpenGLGL2PSExporter.h @@ -0,0 +1,160 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: vtkGL2PSExporter.h + + 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. + +=========================================================================*/ +// .NAME vtkGL2PSExporter - export a scene as a PostScript file using GL2PS. +// .SECTION Description +// vtkGL2PSExporter is a concrete subclass of vtkExporter that writes +// high quality vector PostScript (PS/EPS), PDF or SVG files by using +// GL2PS. GL2PS can be obtained at: http://www.geuz.org/gl2ps/. This +// can be very useful when one requires publication quality pictures. +// This class works best with simple 3D scenes and most 2D plots. +// Please note that GL2PS has its limitations since PostScript is not +// an ideal language to represent complex 3D scenes. However, this +// class does allow one to write mixed vector/raster files by using +// the Write3DPropsAsRasterImage ivar. Please do read the caveats +// section of this documentation. +// +// By default vtkGL2PSExporter generates Encapsulated PostScript (EPS) +// output along with the text in portrait orientation with the +// background color of the window being drawn. The generated output +// is also compressed using zlib. The various other options are set to +// sensible defaults. +// +// The output file format (FileFormat) can be either PostScript (PS), +// Encapsulated PostScript (EPS), PDF, SVG or TeX. The file extension +// is generated automatically depending on the FileFormat. The +// default is EPS. When TeX output is chosen, only the text strings +// in the plot are generated and put into a picture environment. One +// can turn on and off the text when generating PS/EPS/PDF/SVG files +// by using the Text boolean variable. By default the text is drawn. +// The background color of the renderwindow is drawn by default. To +// make the background white instead use the DrawBackgroundOff +// function. Landscape figures can be generated by using the +// LandscapeOn function. Portrait orientation is used by default. +// Several of the GL2PS options can be set. The names of the ivars +// for these options are similar to the ones that GL2PS provides. +// Compress, SimpleLineOffset, Silent, BestRoot, PS3Shading and +// OcclusionCull are similar to the options provided by GL2PS. Please +// read the function documentation or the GL2PS documentation for more +// details. The ivar Write3DPropsAsRasterImage allows one to generate +// mixed vector/raster images. All the 3D props in the scene will be +// written as a raster image and all 2D actors will be written as +// vector graphic primitives. This makes it possible to handle +// transparency and complex 3D scenes. This ivar is set to Off by +// default. Specific 3D props can be excluded from the rasterization +// process by adding them to the RasterExclusions ivar. Props in this +// collection will be rendered as 2D vector primitives instead. + +// .SECTION Caveats +// By default (with Write3DPropsAsRasterImage set to Off) exporting +// complex 3D scenes can take a long while and result in huge output +// files. Generating correct vector graphics output for scenes with +// transparency is almost impossible. However, one can set +// Write3DPropsAsRasterImageOn and generate mixed vector/raster files. +// This should work fine with complex scenes along with transparent +// actors. + +// .SECTION See Also +// vtkExporter + +// .SECTION Thanks +// Thanks to Goodwin Lawlor and Prabhu Ramachandran for this class. + + +#ifndef vtkOpenGLGL2PSExporter_h +#define vtkOpenGLGL2PSExporter_h + +#include "vtkIOExportOpenGLModule.h" // For export macro +#include "vtkGL2PSExporter.h" + +#include "vtkNew.h" // For vtkNew + +class vtkActor; +class vtkActor2D; +class vtkCollection; +class vtkCoordinate; +class vtkImageData; +class vtkIntArray; +class vtkLabeledDataMapper; +class vtkLabeledContourMapper; +class vtkMatrix4x4; +class vtkPath; +class vtkProp; +class vtkPropCollection; +class vtkProp3DCollection; +class vtkRenderer; +class vtkRendererCollection; +class vtkScalarBarActor; +class vtkTextActor; +class vtkTextActor3D; +class vtkTextMapper; +class vtkTextProperty; + +class VTKIOEXPORTOPENGL_EXPORT vtkOpenGLGL2PSExporter : public vtkGL2PSExporter +{ +public: + static vtkOpenGLGL2PSExporter *New(); + vtkTypeMacro(vtkOpenGLGL2PSExporter, vtkGL2PSExporter) + void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkOpenGLGL2PSExporter(); + ~vtkOpenGLGL2PSExporter(); + + void WriteData(); + + void SavePropVisibility(vtkRendererCollection *renCol, + vtkIntArray *volVis, vtkIntArray *actVis, + vtkIntArray *act2dVis); + void RestorePropVisibility(vtkRendererCollection *renCol, + vtkIntArray *volVis, vtkIntArray *actVis, + vtkIntArray *act2dVis); + void Turn3DPropsOff(vtkRendererCollection *renCol); + void Turn2DPropsOff(vtkRendererCollection *renCol); + void GetVisibleContextActors(vtkPropCollection *contextActors, + vtkRendererCollection *renCol); + void SetPropVisibilities(vtkPropCollection *col, int vis); + + void DrawSpecialProps(vtkCollection *propCol, vtkRendererCollection *renCol); + // Description: + // Reimplement this to handle your own special props. Must call this function + // at the end of the override for default handling. + virtual void HandleSpecialProp(vtkProp *prop, vtkRenderer *ren); + void DrawTextActor(vtkTextActor *textAct, vtkRenderer *ren); + void DrawTextActor3D(vtkTextActor3D *textAct, vtkRenderer *ren); + void DrawTextMapper(vtkTextMapper *textMap, vtkActor2D *textAct, + vtkRenderer *ren); + void DrawLabeledDataMapper(vtkLabeledDataMapper *mapper, vtkRenderer *ren); + void DrawLabeledContourMapper(vtkActor *act, vtkLabeledContourMapper *mapper, + vtkRenderer *ren); + void DrawScalarBarActor(vtkScalarBarActor *bar, vtkRenderer *ren); + void DrawViewportTextOverlay(const char *string, vtkTextProperty *tprop, + vtkCoordinate *coord, vtkRenderer *ren); + + // Description: + // Copy the region copyRect from the framebuffer into the gl2ps document. + // copyRect is in viewport coordinates [xmin, ymin, width, height]. + void CopyPixels(int copyRect[4], vtkRenderer *ren); + + void DrawContextActors(vtkPropCollection *contextActs, + vtkRendererCollection *renCol); + + vtkNew PixelData; + +private: + vtkOpenGLGL2PSExporter(const vtkOpenGLGL2PSExporter&); // Not implemented + void operator=(const vtkOpenGLGL2PSExporter&); // Not implemented +}; + +#endif diff --git a/Rendering/GL2PS/vtkGL2PSUtilities.h b/Rendering/GL2PS/vtkGL2PSUtilities.h index 5af98f232b8..82a5ebb25a7 100644 --- a/Rendering/GL2PS/vtkGL2PSUtilities.h +++ b/Rendering/GL2PS/vtkGL2PSUtilities.h @@ -101,7 +101,7 @@ class VTKRENDERINGGL2PS_EXPORT vtkGL2PSUtilities : public vtkObject { return vtkGL2PSUtilities::LineWidthFactor; } protected: - friend class vtkGL2PSExporter; + friend class vtkOpenGLGL2PSExporter; static void StartExport(); static void FinishExport();