You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
269 lines
9.6 KiB
269 lines
9.6 KiB
2 years ago
|
/*=========================================================================
|
||
|
|
||
|
Program: Visualization Toolkit
|
||
|
Module: $RCSfile: vtkUnstructuredGridBunykRayCastFunction.h,v $
|
||
|
|
||
|
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 vtkUnstructuredGridBunykRayCastFunction - a superclass for ray casting functions
|
||
|
|
||
|
// .SECTION Description
|
||
|
// vtkUnstructuredGridBunykRayCastFunction is a concrete implementation of a
|
||
|
// ray cast function for unstructured grid data. This class was based on the
|
||
|
// paper "Simple, Fast, Robust Ray Casting of Irregular Grids" by Paul Bunyk,
|
||
|
// Arie Kaufmna, and Claudio Silva. This method is quite memory intensive
|
||
|
// (with extra explicit copies of the data) and therefore should not be used
|
||
|
// for very large data. This method assumes that the input data is composed
|
||
|
// entirely of tetras - use vtkDataSetTriangleFilter before setting the input
|
||
|
// on the mapper.
|
||
|
//
|
||
|
// The basic idea of this method is as follows:
|
||
|
//
|
||
|
// 1) Enumerate the triangles. At each triangle have space for some
|
||
|
// information that will be used during rendering. This includes
|
||
|
// which tetra the triangles belong to, the plane equation and the
|
||
|
// Barycentric coefficients.
|
||
|
//
|
||
|
// 2) Keep a reference to all four triangles for each tetra.
|
||
|
//
|
||
|
// 3) At the beginning of each render, do the precomputation. This
|
||
|
// includes creating an array of transformed points (in view
|
||
|
// coordinates) and computing the view dependent info per triangle
|
||
|
// (plane equations and barycentric coords in view space)
|
||
|
//
|
||
|
// 4) Find all front facing boundary triangles (a triangle is on the
|
||
|
// boundary if it belongs to only one tetra). For each triangle,
|
||
|
// find all pixels in the image that intersect the triangle, and
|
||
|
// add this to the sorted (by depth) intersection list at each
|
||
|
// pixel.
|
||
|
//
|
||
|
// 5) For each ray cast, traverse the intersection list. At each
|
||
|
// intersection, accumulate opacity and color contribution
|
||
|
// per tetra along the ray until you reach an exiting triangle
|
||
|
// (on the boundary).
|
||
|
//
|
||
|
|
||
|
// .SECTION See Also
|
||
|
// vtkUnstructuredGridVolumeRayCastMapper
|
||
|
|
||
|
#ifndef __vtkUnstructuredGridBunykRayCastFunction_h
|
||
|
#define __vtkUnstructuredGridBunykRayCastFunction_h
|
||
|
|
||
|
#include "vtkUnstructuredGridVolumeRayCastFunction.h"
|
||
|
|
||
|
class vtkRenderer;
|
||
|
class vtkVolume;
|
||
|
class vtkUnstructuredGridVolumeRayCastMapper;
|
||
|
class vtkMatrix4x4;
|
||
|
class vtkPiecewiseFunction;
|
||
|
class vtkColorTransferFunction;
|
||
|
class vtkUnstructuredGrid;
|
||
|
class vtkIdList;
|
||
|
class vtkDoubleArray;
|
||
|
class vtkDataArray;
|
||
|
|
||
|
// We manage the memory for the list of intersections ourself - this is the
|
||
|
// storage used. We keep 10,000 elements in each array, and we can have up to
|
||
|
// 1,000 arrays.
|
||
|
#define VTK_BUNYKRCF_MAX_ARRAYS 10000
|
||
|
#define VTK_BUNYKRCF_ARRAY_SIZE 10000
|
||
|
|
||
|
class VTK_VOLUMERENDERING_EXPORT vtkUnstructuredGridBunykRayCastFunction : public vtkUnstructuredGridVolumeRayCastFunction
|
||
|
{
|
||
|
public:
|
||
|
static vtkUnstructuredGridBunykRayCastFunction *New();
|
||
|
vtkTypeRevisionMacro(vtkUnstructuredGridBunykRayCastFunction,vtkUnstructuredGridVolumeRayCastFunction);
|
||
|
virtual void PrintSelf(ostream& os, vtkIndent indent);
|
||
|
|
||
|
//BTX
|
||
|
// Description:
|
||
|
// Called by the ray cast mapper at the start of rendering
|
||
|
virtual void Initialize( vtkRenderer *ren, vtkVolume *vol );
|
||
|
|
||
|
// Description:
|
||
|
// Called by the ray cast mapper at the end of rendering
|
||
|
virtual void Finalize();
|
||
|
|
||
|
virtual vtkUnstructuredGridVolumeRayCastIterator *NewIterator();
|
||
|
|
||
|
// Used to store each triangle - made public because of the
|
||
|
// templated function
|
||
|
class Triangle {
|
||
|
public:
|
||
|
vtkIdType PointIndex[3];
|
||
|
vtkIdType ReferredByTetra[2];
|
||
|
double P1X, P1Y;
|
||
|
double P2X, P2Y;
|
||
|
double Denominator;
|
||
|
double A, B, C, D;
|
||
|
Triangle *Next;
|
||
|
};
|
||
|
|
||
|
// Used to store each intersection for the pixel rays - made
|
||
|
// public because of the templated function
|
||
|
class Intersection {
|
||
|
public:
|
||
|
Triangle *TriPtr;
|
||
|
double Z;
|
||
|
Intersection *Next;
|
||
|
};
|
||
|
|
||
|
// Description:
|
||
|
// Is the point x, y, in the given triangle? Public for
|
||
|
// access from the templated function.
|
||
|
int InTriangle( double x, double y,
|
||
|
Triangle *triPtr );
|
||
|
|
||
|
|
||
|
// Description:
|
||
|
// Access to an internal structure for the templated method.
|
||
|
double *GetPoints() {return this->Points;}
|
||
|
|
||
|
// Description:
|
||
|
// Access to an internal structure for the templated method.
|
||
|
vtkGetObjectMacro( ViewToWorldMatrix, vtkMatrix4x4 );
|
||
|
|
||
|
// Description:
|
||
|
// Access to an internal structure for the templated method.
|
||
|
vtkGetVectorMacro( ImageOrigin, int, 2 );
|
||
|
|
||
|
// Description:
|
||
|
// Access to an internal structure for the templated method.
|
||
|
vtkGetVectorMacro( ImageViewportSize, int, 2 );
|
||
|
|
||
|
// Description:
|
||
|
// Access to an internal structure for the templated method.
|
||
|
Triangle **GetTetraTriangles () {return this->TetraTriangles;}
|
||
|
|
||
|
// Description:
|
||
|
// Access to an internal structure for the templated method.
|
||
|
Intersection *GetIntersectionList( int x, int y ) { return this->Image[y*this->ImageSize[0] + x]; }
|
||
|
|
||
|
//ETX
|
||
|
|
||
|
protected:
|
||
|
vtkUnstructuredGridBunykRayCastFunction();
|
||
|
~vtkUnstructuredGridBunykRayCastFunction();
|
||
|
|
||
|
// These are cached during the initialize method so that they do not
|
||
|
// need to be passed into subsequent CastRay calls.
|
||
|
vtkRenderer *Renderer;
|
||
|
vtkVolume *Volume;
|
||
|
vtkUnstructuredGridVolumeRayCastMapper *Mapper;
|
||
|
|
||
|
// Computed during the initialize method - if something is
|
||
|
// wrong (no mapper, no volume, no input, etc.) then no rendering
|
||
|
// will actually be performed.
|
||
|
int Valid;
|
||
|
|
||
|
// These are the transformed points
|
||
|
int NumberOfPoints;
|
||
|
double *Points;
|
||
|
|
||
|
// This is the matrix that will take a transformed point back
|
||
|
// to world coordinates
|
||
|
vtkMatrix4x4 *ViewToWorldMatrix;
|
||
|
|
||
|
|
||
|
// This is the intersection list per pixel in the image
|
||
|
Intersection **Image;
|
||
|
|
||
|
// This is the size of the image we are computing (which does
|
||
|
// not need to match the screen size)
|
||
|
int ImageSize[2];
|
||
|
|
||
|
// Since we may only be computing a subregion of the "full" image,
|
||
|
// this is the origin of the region we are computing. We must
|
||
|
// subtract this origin from any pixel (x,y) locations before
|
||
|
// accessing the pixel in this->Image (which represents only the
|
||
|
// subregion)
|
||
|
int ImageOrigin[2];
|
||
|
|
||
|
// This is the full size of the image
|
||
|
int ImageViewportSize[2];
|
||
|
|
||
|
// These are values saved for the building of the TriangleList. Basically
|
||
|
// we need to check if the data has changed in some way.
|
||
|
vtkUnstructuredGrid *SavedTriangleListInput;
|
||
|
vtkTimeStamp SavedTriangleListMTime;
|
||
|
|
||
|
//BTX
|
||
|
// This is a memory intensive algorithm! For each tetra in the
|
||
|
// input data we create up to 4 triangles (we don't create duplicates)
|
||
|
// This is the TriangleList. Then, for each tetra we keep track of
|
||
|
// the pointer to each of its four triangles - this is the
|
||
|
// TetraTriangles. We also keep a duplicate list of points
|
||
|
// (transformed into view space) - these are the Points.
|
||
|
Triangle **TetraTriangles;
|
||
|
Triangle *TriangleList;
|
||
|
|
||
|
// Compute whether a boundary triangle is front facing by
|
||
|
// looking at the fourth point in the tetra to see if it is
|
||
|
// in front (triangle is backfacing) or behind (triangle is
|
||
|
// front facing) the plane containing the triangle.
|
||
|
int IsTriangleFrontFacing( Triangle *triPtr, vtkIdType tetraIndex );
|
||
|
|
||
|
// The image contains lists of intersections per pixel - we
|
||
|
// need to clear this during the initialization phase for each
|
||
|
// render.
|
||
|
void ClearImage();
|
||
|
|
||
|
// This is the memory buffer used to build the intersection
|
||
|
// lists. We do our own memory management here because allocating
|
||
|
// a bunch of small elements during rendering is too slow.
|
||
|
Intersection *IntersectionBuffer[VTK_BUNYKRCF_MAX_ARRAYS];
|
||
|
int IntersectionBufferCount[VTK_BUNYKRCF_MAX_ARRAYS];
|
||
|
|
||
|
// This method replaces new for creating a new element - it
|
||
|
// returns one from the big block already allocated (it
|
||
|
// allocates another big block if necessary)
|
||
|
void *NewIntersection();
|
||
|
|
||
|
// This method is used during the initialization process to
|
||
|
// check the validity of the objects - missing information
|
||
|
// such as the volume, renderer, mapper, etc. will be flagged
|
||
|
// and reported.
|
||
|
int CheckValidity(vtkRenderer *ren,
|
||
|
vtkVolume *vol);
|
||
|
|
||
|
// This method is used during the initialization process to
|
||
|
// transform the points to view coordinates
|
||
|
void TransformPoints();
|
||
|
|
||
|
// This method is used during the initialization process to
|
||
|
// create the list of triangles if the data has changed
|
||
|
void UpdateTriangleList();
|
||
|
|
||
|
// This method is used during the initialization process to
|
||
|
// update the view dependent information in the triangle list
|
||
|
void ComputeViewDependentInfo();
|
||
|
|
||
|
// This method is used during the initialization process to
|
||
|
// compute the intersections for each pixel with the boundary
|
||
|
// triangles.
|
||
|
void ComputePixelIntersections();
|
||
|
|
||
|
//ETX
|
||
|
|
||
|
private:
|
||
|
vtkUnstructuredGridBunykRayCastFunction(const vtkUnstructuredGridBunykRayCastFunction&); // Not implemented.
|
||
|
void operator=(const vtkUnstructuredGridBunykRayCastFunction&); // Not implemented.
|
||
|
};
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|