/*========================================================================= Program: Visualization Toolkit Module: vtkSurfaceLICComposite.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. =========================================================================*/ /** * @class vtkSurfaceLICComposite * * This class decomposes the image space and shuffles image space * data onto the new decomposition with the necessary guard cells * to prevent artifacts at the decomposition boundaries. After the * image LIC is computed on the new decomposition this class will * un-shuffle the computed LIC back onto the original decomposition */ #ifndef vtkSurfaceLICComposite_h #define vtkSurfaceLICComposite_h #include "vtkObject.h" #include "vtkPixelExtent.h" // for pixel extent #include "vtkRenderingLICOpenGL2Module.h" // for export macro #include // for deque #include // for vector class vtkFloatArray; class vtkOpenGLRenderWindow; class vtkTextureObject; class vtkPainterCommunicator; class VTKRENDERINGLICOPENGL2_EXPORT vtkSurfaceLICComposite : public vtkObject { public: static vtkSurfaceLICComposite* New(); vtkTypeMacro(vtkSurfaceLICComposite, vtkObject); void PrintSelf(ostream& os, vtkIndent indent) override; /** * Initialize the object based on the following description of the * blocks projected onto the render window. wholeExt describes the * window size, originalExts describe each block's extent in window * coords. stepSize is the window coordinate integration step size. * when inplace is true compositing happens on the original extent. */ void Initialize(const vtkPixelExtent& winExt, const std::deque& blockExts, int strategy, double stepSize, int nSteps, int normalizeVectors, int enhancedLIC, int anitalias); /** * Control the screen space decomposition. The available modes are: * INPLACE * use the block decomp. This may result in LIC being computed * many times for the same pixels and an excessive amount of * IPC during compositing if any of the block extents cover * or intersect a number of block extents. The input data * needs to be shuffled but not unshuffled since for overlapping * regions LIC is computed by all processes that overlap. * If there is very little overlap between block extents * then this method is superior since no unshuffle is needed. * INPLACE_DISJOINT * use a disjoint version of the block decomp. This will leave * non-overlapping data in place, reasigning overlapping regions * so that LIC is computed once for each pixel on the screen. * An unshuffle step to move data in overlapping region to all * processes that overlap. * BALANCED * move to a new decomp where each rank gets an equal number * of pixels. This ensures the best load balancing during LIC * and that LIC is computed once for each pixel. In the worst * case each pixel will be shuffled and unshuffled. * AUTO * Use a heuristic to select the mode. */ enum { COMPOSITE_INPLACE = 0, COMPOSITE_INPLACE_DISJOINT, COMPOSITE_BALANCED, COMPOSITE_AUTO }; void SetStrategy(int val) { this->Strategy = val; } int GetStrategy() { return this->Strategy; } /** * Get the number of new extents assigned to this rank after * the decomposition. */ int GetNumberOfCompositeExtents() const { return static_cast(this->CompositeExt.size()); } /** * Get the extent of the domain over which to compute the LIC. This can * be querried only after the Composite takes place. */ const vtkPixelExtent& GetGuardExtent(int i = 0) const { return this->GuardExt[i]; } const std::deque& GetGuardExtents() const { return this->GuardExt; } /** * Get the extent of the domain over which to compute the LIC. This can * be querried only after the Composite takes place. */ const vtkPixelExtent& GetDisjointGuardExtent(int i = 0) const { return this->DisjointGuardExt[i]; } const std::deque& GetDisjointGuardExtents() const { return this->GuardExt; } /** * Get the extent of the domain over which to compute the LIC. This can * be querried only after the Composite takes place. */ const vtkPixelExtent& GetCompositeExtent(int i = 0) const { return this->CompositeExt[i]; } const std::deque& GetCompositeExtents() const { return this->CompositeExt; } /** * Get the whole dataset extent (all blocks). */ const vtkPixelExtent& GetDataSetExtent() const { return this->DataSetExt; } /** * Get the whole window extent. */ const vtkPixelExtent& GetWindowExtent() const { return this->WindowExt; } /** * Set up for a serial run, makes the decomp disjoint and adds * requisite guard pixles. */ int InitializeCompositeExtents(float* vectors); /** * Set the rendering context. Must set prior to use. Reference is not * held, so caller must ensure the renderer is not destroyed during * use. */ virtual void SetContext(vtkOpenGLRenderWindow*) {} virtual vtkOpenGLRenderWindow* GetContext() { return nullptr; } /** * Set the communicator for parallel communication. A duplicate * is not made. It is up to the caller to manage the life of * the communicator such that it is around while this class * needs it and is released after. */ virtual void SetCommunicator(vtkPainterCommunicator*) {} /** * Set the communicator to the default communicator */ virtual void RestoreDefaultCommunicator() {} /** * Build programs to move data to the new decomp * In parallel THIS IS A COLLECTIVE OPERATION */ virtual int BuildProgram(float*) { return -1; } /** * Move a single buffer from the geometry decomp to the LIC decomp. * THIS IS A COLLECTIVE OPERATION */ virtual int Gather(void*, int, int, vtkTextureObject*&) { return -1; } /** * Move a single buffer from the LIC decomp to the geometry decomp * In parallel THIS IS A COLLECTIVE OPERATION */ virtual int Scatter(void*, int, int, vtkTextureObject*&) { return -1; } /** * Make a decomposition disjoint with respect to itself. Extents are * removed from the input array and disjoint extents are appended onto * the output array. This is a local operation. */ static int MakeDecompDisjoint(std::deque& in, std::deque& out); protected: vtkSurfaceLICComposite(); ~vtkSurfaceLICComposite() override; /** * For serial run. Make a decomposition disjoint. Sorts extents and * processes largest to smallest , repeatedly subtracting smaller * remaining blocks from the largest remaining. Each extent in the * new disjoint set is shrunk to tightly bound the vector data, * extents with empty vectors are removed. This is a local operation * since vector field is local. */ int MakeDecompDisjoint( const std::deque& in, std::deque& out, float* vectors); /** * Compute max(V) on the given extent. */ float VectorMax(const vtkPixelExtent& ext, float* vectors); /** * Compute max(V) on a set of extents. Neighboring extents are * including in the computation. */ int VectorMax(const std::deque& exts, float* vectors, std::vector& vMax); /** * Add guard pixels (Serial run) */ int AddGuardPixels(const std::deque& exts, std::deque& guardExts, std::deque& disjointGuardExts, float* vectors); /** * shrink pixel extent based on non-zero alpha channel values */ void GetPixelBounds(float* rgba, int ni, vtkPixelExtent& ext); /** * factor for determining extra padding for guard pixels. * depends on window aspect ratio because of anisotropic * transform to texture space. see note in implementation. */ float GetFudgeFactor(int nx[2]); protected: int Pass; // id for mpi tagging vtkPixelExtent WindowExt; // screen extent (screen size) vtkPixelExtent DataSetExt; // screen extent of the dataset std::deque BlockExts; // screen extents of blocks std::deque CompositeExt; // screen extents after decomp std::deque GuardExt; // screen extents w/ guard cells std::deque DisjointGuardExt; // screen extents w/ guard cells int Strategy; // control for parallel composite double StepSize; // window coordinates step size int NumberOfSteps; // number of integration steps int NormalizeVectors; // does integrator normailze int NumberOfGuardLevels; // 1.5 if enhanced LIC 1 otherwise int NumberOfEEGuardPixels; // 1 if enhanced LIC 0 otherwise int NumberOfAAGuardPixels; // n antialias passes private: vtkSurfaceLICComposite(const vtkSurfaceLICComposite&) = delete; void operator=(const vtkSurfaceLICComposite&) = delete; friend ostream& operator<<(ostream& os, vtkSurfaceLICComposite& ss); }; ostream& operator<<(ostream& os, vtkSurfaceLICComposite& ss); #endif