/*========================================================================= Program: Visualization Toolkit Module: vtkImageProcessingPass.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 "vtk_glew.h" #include "vtkImageProcessingPass.h" #include "vtkObjectFactory.h" #include #include "vtkRenderState.h" #include "vtkRenderer.h" #include "vtkOpenGLFramebufferObject.h" #include "vtkTextureObject.h" #include "vtkOpenGLRenderWindow.h" // to be able to dump intermediate passes into png files for debugging. // only for vtkImageProcessingPass developers. //#define VTK_IMAGE_PROCESSING_PASS_DEBUG #include "vtkPixelBufferObject.h" #include "vtkCamera.h" #include "vtkMath.h" vtkCxxSetObjectMacro(vtkImageProcessingPass,DelegatePass,vtkRenderPass); // ---------------------------------------------------------------------------- vtkImageProcessingPass::vtkImageProcessingPass() { this->DelegatePass=nullptr; } // ---------------------------------------------------------------------------- vtkImageProcessingPass::~vtkImageProcessingPass() { if(this->DelegatePass!=nullptr) { this->DelegatePass->Delete(); } } // ---------------------------------------------------------------------------- void vtkImageProcessingPass::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "DelegatePass:"; if(this->DelegatePass!=nullptr) { this->DelegatePass->PrintSelf(os,indent); } else { os << "(none)" <GetContext()!=0 // \pre target_exists: target!=0 // \pre target_has_context: target->GetContext()!=0 void vtkImageProcessingPass::RenderDelegate(const vtkRenderState *s, int width, int height, int newWidth, int newHeight, vtkOpenGLFramebufferObject *fbo, vtkTextureObject *target) { assert("pre: s_exists" && s!=nullptr); assert("pre: fbo_exists" && fbo!=nullptr); assert("pre: fbo_has_context" && fbo->GetContext()!=nullptr); assert("pre: target_exists" && target!=nullptr); assert("pre: target_has_context" && target->GetContext()!=nullptr); #ifdef VTK_IMAGE_PROCESSING_PASS_DEBUG cout << "width=" << width << endl; cout << "height=" << height << endl; cout << "newWidth=" << newWidth << endl; cout << "newHeight=" << newHeight << endl; #endif vtkRenderer *r=s->GetRenderer(); vtkRenderState s2(r); s2.SetPropArrayAndCount(s->GetPropArray(),s->GetPropArrayCount()); // Adapt camera to new window size vtkCamera *savedCamera=r->GetActiveCamera(); savedCamera->Register(this); vtkCamera *newCamera=vtkCamera::New(); newCamera->DeepCopy(savedCamera); #ifdef VTK_IMAGE_PROCESSING_PASS_DEBUG cout << "old camera params="; savedCamera->Print(cout); cout << "new camera params="; newCamera->Print(cout); #endif r->SetActiveCamera(newCamera); if(newCamera->GetParallelProjection()) { newCamera->SetParallelScale( newCamera->GetParallelScale()*newHeight/static_cast(height)); } else { double large; double small; if(newCamera->GetUseHorizontalViewAngle()) { large=newWidth; small=width; } else { large=newHeight; small=height; } double angle=vtkMath::RadiansFromDegrees(newCamera->GetViewAngle()); #ifdef VTK_IMAGE_PROCESSING_PASS_DEBUG cout << "old angle =" << angle << " rad="<< vtkMath::DegreesFromRadians(angle) << " deg" <(small)); #ifdef VTK_IMAGE_PROCESSING_PASS_DEBUG cout << "new angle =" << angle << " rad="<< vtkMath::DegreesFromRadians(angle) << " deg" <SetViewAngle(vtkMath::DegreesFromRadians(angle)); } s2.SetFrameBuffer(fbo); if(target->GetWidth()!=static_cast(newWidth) || target->GetHeight()!=static_cast(newHeight)) { target->Create2D(newWidth,newHeight,4,VTK_UNSIGNED_CHAR,false); } fbo->AddColorAttachment( fbo->GetBothMode(), 0, target); // because the same FBO can be used in another pass but with several color // buffers, force this pass to use 1, to avoid side effects from the // render of the previous frame. fbo->ActivateBuffer(0); fbo->AddDepthAttachment(fbo->GetBothMode()); fbo->StartNonOrtho(newWidth,newHeight); glViewport(0, 0, newWidth, newHeight); glScissor(0, 0, newWidth, newHeight); // 2. Delegate render in FBO glEnable(GL_DEPTH_TEST); this->DelegatePass->Render(&s2); this->NumberOfRenderedProps+= this->DelegatePass->GetNumberOfRenderedProps(); #ifdef VTK_IMAGE_PROCESSING_PASS_DEBUG vtkPixelBufferObject *pbo=target->Download(); unsigned int dims[2]; vtkIdType continuousInc[3]; dims[0]=static_cast(newWidth); dims[1]=static_cast(newHeight); continuousInc[0]=0; continuousInc[1]=0; continuousInc[2]=0; int byteSize=newWidth*newHeight*4*sizeof(float); float *buffer=new float[newWidth*newHeight*4]; pbo->Download2D(VTK_FLOAT,buffer,dims,4,continuousInc); vtkImageImport *importer=vtkImageImport::New(); importer->CopyImportVoidPointer(buffer,static_cast(byteSize)); importer->SetDataScalarTypeToFloat(); importer->SetNumberOfScalarComponents(4); importer->SetWholeExtent(0,newWidth-1,0,newHeight-1,0,0); importer->SetDataExtentToWholeExtent(); importer->Update(); vtkPNGWriter *writer=vtkPNGWriter::New(); writer->SetFileName("ip.png"); writer->SetInputConnection(importer->GetOutputPort()); importer->Delete(); cout << "Writing " << writer->GetFileName() << endl; writer->Write(); cout << "Wrote " << writer->GetFileName() << endl; writer->Delete(); pbo->Delete(); delete[] buffer; #endif newCamera->Delete(); r->SetActiveCamera(savedCamera); savedCamera->UnRegister(this); } // ---------------------------------------------------------------------------- // Description: // Release graphics resources and ask components to release their own // resources. // \pre w_exists: w!=0 void vtkImageProcessingPass::ReleaseGraphicsResources(vtkWindow *w) { assert("pre: w_exists" && w!=nullptr); if(this->DelegatePass!=nullptr) { this->DelegatePass->ReleaseGraphicsResources(w); } }