/*========================================================================= Program: Visualization Toolkit Module: vtkUnstructuredGridVolumeZSweepMapper.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 vtkUnstructuredGridVolumeZSweepMapper * @brief Unstructured grid volume mapper based the ZSweep Algorithm * * * This is a volume mapper for unstructured grid implemented with the ZSweep * algorithm. This is a software projective method. * * @sa * vtkVolumetMapper * * @par Background: * The algorithm is described in the following paper: * Ricardo Farias, Joseph S. B. Mitchell and Claudio T. Silva. * ZSWEEP: An Efficient and Exact Projection Algorithm for Unstructured Volume * Rendering. In 2000 Volume Visualization Symposium, pages 91--99. * October 2000. * http://www.cse.ogi.edu/~csilva/papers/volvis2000.pdf */ #ifndef vtkUnstructuredGridVolumeZSweepMapper_h #define vtkUnstructuredGridVolumeZSweepMapper_h #include "vtkRenderingVolumeModule.h" // For export macro #include "vtkUnstructuredGridVolumeMapper.h" class vtkRenderer; class vtkVolume; class vtkRayCastImageDisplayHelper; class vtkCell; class vtkGenericCell; class vtkIdList; class vtkPriorityQueue; class vtkTransform; class vtkMatrix4x4; class vtkVolumeProperty; class vtkDoubleArray; class vtkUnstructuredGridVolumeRayIntegrator; class vtkRenderWindow; // Internal classes namespace vtkUnstructuredGridVolumeZSweepMapperNamespace { class vtkScreenEdge; class vtkSpan; class vtkPixelListFrame; class vtkUseSet; class vtkVertices; class vtkSimpleScreenEdge; class vtkDoubleScreenEdge; class vtkVertexEntry; class vtkPixelListEntryMemory; }; class VTKRENDERINGVOLUME_EXPORT vtkUnstructuredGridVolumeZSweepMapper : public vtkUnstructuredGridVolumeMapper { public: vtkTypeMacro(vtkUnstructuredGridVolumeZSweepMapper, vtkUnstructuredGridVolumeMapper); void PrintSelf(ostream& os, vtkIndent indent) override; /** * Set MaxPixelListSize to 32. */ static vtkUnstructuredGridVolumeZSweepMapper* New(); //@{ /** * Sampling distance in the XY image dimensions. Default value of 1 meaning * 1 ray cast per pixel. If set to 0.5, 4 rays will be cast per pixel. If * set to 2.0, 1 ray will be cast for every 4 (2 by 2) pixels. */ vtkSetClampMacro(ImageSampleDistance, float, 0.1f, 100.0f); vtkGetMacro(ImageSampleDistance, float); //@} //@{ /** * This is the minimum image sample distance allow when the image * sample distance is being automatically adjusted */ vtkSetClampMacro(MinimumImageSampleDistance, float, 0.1f, 100.0f); vtkGetMacro(MinimumImageSampleDistance, float); //@} //@{ /** * This is the maximum image sample distance allow when the image * sample distance is being automatically adjusted */ vtkSetClampMacro(MaximumImageSampleDistance, float, 0.1f, 100.0f); vtkGetMacro(MaximumImageSampleDistance, float); //@} //@{ /** * If AutoAdjustSampleDistances is on, the ImageSampleDistance * will be varied to achieve the allocated render time of this * prop (controlled by the desired update rate and any culling in * use). */ vtkSetClampMacro(AutoAdjustSampleDistances, vtkTypeBool, 0, 1); vtkGetMacro(AutoAdjustSampleDistances, vtkTypeBool); vtkBooleanMacro(AutoAdjustSampleDistances, vtkTypeBool); //@} //@{ /** * If IntermixIntersectingGeometry is turned on, the zbuffer will be * captured and used to limit the traversal of the rays. */ vtkSetClampMacro(IntermixIntersectingGeometry, vtkTypeBool, 0, 1); vtkGetMacro(IntermixIntersectingGeometry, vtkTypeBool); vtkBooleanMacro(IntermixIntersectingGeometry, vtkTypeBool); //@} /** * Maximum size allowed for a pixel list. Default is 32. * During the rendering, if a list of pixel is full, incremental compositing * is performed. Even if it is a user setting, it is an advanced parameter. * You have to understand how the algorithm works to change this value. */ int GetMaxPixelListSize(); /** * Change the maximum size allowed for a pixel list. It is an advanced * parameter. * \pre positive_size: size>1 */ void SetMaxPixelListSize(int size); //@{ /** * Set/Get the helper class for integrating rays. If set to NULL, a * default integrator will be assigned. */ virtual void SetRayIntegrator(vtkUnstructuredGridVolumeRayIntegrator* ri); vtkGetObjectMacro(RayIntegrator, vtkUnstructuredGridVolumeRayIntegrator); //@} /** * WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE * DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS * Render the volume */ void Render(vtkRenderer* ren, vtkVolume* vol) override; vtkGetVectorMacro(ImageInUseSize, int, 2); vtkGetVectorMacro(ImageOrigin, int, 2); vtkGetVectorMacro(ImageViewportSize, int, 2); protected: vtkUnstructuredGridVolumeZSweepMapper(); ~vtkUnstructuredGridVolumeZSweepMapper() override; /** * For each vertex, find the list of incident faces. */ void BuildUseSets(); /** * Reorder vertices `v' in increasing order in `w'. Return if the orientation * has changed. */ int ReorderTriangle(vtkIdType v[3], vtkIdType w[3]); /** * Project and sort the vertices by z-coordinates in view space in the * "event list" (an heap). * \pre empty_list: this->EventList->GetNumberOfItems()==0 */ void ProjectAndSortVertices(vtkRenderer* ren, vtkVolume* vol); /** * Create an empty "pixel list" for each pixel of the screen. */ void CreateAndCleanPixelList(); /** * MainLoop of the Zsweep algorithm. * \post empty_list: this->EventList->GetNumberOfItems()==0 */ void MainLoop(vtkRenderWindow* renWin); /** * Do delayed compositing from back to front, stopping at zTarget for each * pixel inside the bounding box. */ void CompositeFunction(double zTarget); /** * Convert and clamp a float color component into a unsigned char. */ unsigned char ColorComponentRealToByte(float color); /** * Perform scan conversion of a triangle face. */ void RasterizeFace(vtkIdType faceIds[3], int externalSide); /** * Perform scan conversion of a triangle defined by its vertices. * \pre ve0_exists: ve0!=0 * \pre ve1_exists: ve1!=0 * \pre ve2_exists: ve2!=0 */ void RasterizeTriangle(vtkUnstructuredGridVolumeZSweepMapperNamespace::vtkVertexEntry* ve0, vtkUnstructuredGridVolumeZSweepMapperNamespace::vtkVertexEntry* ve1, vtkUnstructuredGridVolumeZSweepMapperNamespace::vtkVertexEntry* ve2, bool exitFace); /** * Perform scan conversion of an horizontal span from left ro right at line * y. * \pre left_exists: left!=0 * \pre right_exists: right!=0 */ void RasterizeSpan(int y, vtkUnstructuredGridVolumeZSweepMapperNamespace::vtkScreenEdge* left, vtkUnstructuredGridVolumeZSweepMapperNamespace::vtkScreenEdge* right, bool exitFace); /** * Scan conversion of a straight line defined by endpoints v0 and v1. * \pre v0_exists: v0!=0 * \pre v1_exists: v1!=0 * \pre y_ordered v0->GetScreenY()<=v1->GetScreenY() */ void RasterizeLine(vtkUnstructuredGridVolumeZSweepMapperNamespace::vtkVertexEntry* v0, vtkUnstructuredGridVolumeZSweepMapperNamespace::vtkVertexEntry* v1, bool exitFace); void StoreRenderTime(vtkRenderer* ren, vtkVolume* vol, float t); float RetrieveRenderTime(vtkRenderer* ren, vtkVolume* vol); /** * Return the value of the z-buffer at screen coordinates (x,y). */ double GetZBufferValue(int x, int y); double GetMinimumBoundsDepth(vtkRenderer* ren, vtkVolume* vol); /** * Allocate an array of usesets of size `size' only if the current one is not * large enough. Otherwise clear each use set of each vertex. */ void AllocateUseSet(vtkIdType size); /** * Allocate a vertex array of size `size' only if the current one is not * large enough. */ void AllocateVertices(vtkIdType size); /** * For debugging purpose, save the pixel list frame as a dataset. */ void SavePixelListFrame(); int MaxPixelListSize; float ImageSampleDistance; float MinimumImageSampleDistance; float MaximumImageSampleDistance; vtkTypeBool AutoAdjustSampleDistances; vtkRayCastImageDisplayHelper* ImageDisplayHelper; // This is how big the image would be if it covered the entire viewport int ImageViewportSize[2]; // This is how big the allocated memory for image is. This may be bigger // or smaller than ImageFullSize - it will be bigger if necessary to // ensure a power of 2, it will be smaller if the volume only covers a // small region of the viewport int ImageMemorySize[2]; // This is the size of subregion in ImageSize image that we are using for // the current image. Since ImageSize is a power of 2, there is likely // wasted space in it. This number will be used for things such as clearing // the image if necessary. int ImageInUseSize[2]; // This is the location in ImageFullSize image where our ImageSize image // is located. int ImageOrigin[2]; // This is the allocated image unsigned char* Image; // This is the accumulating double RGBA image float* RealRGBAImage; float* RenderTimeTable; vtkVolume** RenderVolumeTable; vtkRenderer** RenderRendererTable; int RenderTableSize; int RenderTableEntries; vtkTypeBool IntermixIntersectingGeometry; float* ZBuffer; int ZBufferSize[2]; int ZBufferOrigin[2]; vtkDataArray* Scalars; int CellScalars; // if use CellScalars, we need to keep track of the // values on each side of the face and figure out // if the face is used by two cells (twosided) or one cell. double FaceScalars[2]; int FaceSide; vtkUnstructuredGridVolumeZSweepMapperNamespace::vtkSpan* Span; vtkUnstructuredGridVolumeZSweepMapperNamespace::vtkPixelListFrame* PixelListFrame; // Used by BuildUseSets(). vtkGenericCell* Cell; vtkUnstructuredGridVolumeZSweepMapperNamespace::vtkUseSet* UseSet; vtkPriorityQueue* EventList; vtkUnstructuredGridVolumeZSweepMapperNamespace::vtkVertices* Vertices; vtkTransform* PerspectiveTransform; vtkMatrix4x4* PerspectiveMatrix; // Used by the main loop int MaxPixelListSizeReached; int XBounds[2]; int YBounds[2]; vtkUnstructuredGridVolumeZSweepMapperNamespace::vtkSimpleScreenEdge* SimpleEdge; vtkUnstructuredGridVolumeZSweepMapperNamespace::vtkDoubleScreenEdge* DoubleEdge; vtkUnstructuredGridVolumeRayIntegrator* RayIntegrator; vtkUnstructuredGridVolumeRayIntegrator* RealRayIntegrator; vtkTimeStamp SavedTriangleListMTime; // Used during compositing vtkDoubleArray* IntersectionLengths; vtkDoubleArray* NearIntersections; vtkDoubleArray* FarIntersections; // Benchmark vtkIdType MaxRecordedPixelListSize; vtkUnstructuredGridVolumeZSweepMapperNamespace::vtkPixelListEntryMemory* MemoryManager; private: vtkUnstructuredGridVolumeZSweepMapper(const vtkUnstructuredGridVolumeZSweepMapper&) = delete; void operator=(const vtkUnstructuredGridVolumeZSweepMapper&) = delete; }; #endif