Commit 57daf0bc authored by Ken Martin's avatar Ken Martin

Some more features and some cleanup reorg.

parent 44e33c4a
......@@ -19,6 +19,7 @@
//-----------------------------------------------------------------------------
vtkAbstractObjectFactoryNewMacro(vtkPointGaussianMapper)
vtkCxxSetObjectMacro(vtkPointGaussianMapper, ScaleFunction, vtkPiecewiseFunction);
vtkCxxSetObjectMacro(vtkPointGaussianMapper, ScalarOpacityFunction, vtkPiecewiseFunction);
//-----------------------------------------------------------------------------
......@@ -27,10 +28,15 @@ vtkPointGaussianMapper::vtkPointGaussianMapper()
this->ScaleArray = 0;
this->OpacityArray = 0;
this->SplatShaderCode = 0;
this->ScaleFunction = 0;
this->ScaleTableSize = 1024;
this->ScalarOpacityFunction = 0;
this->DefaultRadius = 1.0;
this->Emissive = 1;
this->OpacityTableSize = 1024;
this->ScaleFactor = 1.0;
this->Emissive = 1;
}
//-----------------------------------------------------------------------------
......@@ -40,6 +46,7 @@ vtkPointGaussianMapper::~vtkPointGaussianMapper()
this->SetOpacityArray(0);
this->SetSplatShaderCode(0);
this->SetScalarOpacityFunction(0);
this->SetScaleFunction(0);
}
//-----------------------------------------------------------------------------
......@@ -50,7 +57,8 @@ void vtkPointGaussianMapper::PrintSelf(ostream& os, vtkIndent indent)
os << indent << "Scale Array: " << (this->ScaleArray ? this->ScaleArray : "(none)") << "\n";
os << indent << "Opacity Array: " << (this->OpacityArray ? this->OpacityArray : "(none)") << "\n";
os << indent << "SplatShaderCode: " << (this->SplatShaderCode ? this->SplatShaderCode : "(none)") << "\n";
os << indent << "Default Radius: " << this->DefaultRadius << "\n";
os << indent << "ScaleFactor: " << this->ScaleFactor << "\n";
os << indent << "Emissive: " << this->Emissive << "\n";
os << indent << "OpacityTableSize: " << this->OpacityTableSize << "\n";
os << indent << "ScaleTableSize: " << this->ScaleTableSize << "\n";
}
......@@ -32,18 +32,32 @@ public:
vtkTypeMacro(vtkPointGaussianMapper, vtkPolyDataMapper)
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Set/Get the optional scale transfer function. This is only
// used when a ScaleArray is also specified.
void SetScaleFunction(vtkPiecewiseFunction *);
vtkGetObjectMacro(ScaleFunction,vtkPiecewiseFunction);
// Description:
// The size of the table used in computing scale, used when
// converting a vtkPiecewiseFunction to a table
vtkSetMacro(ScaleTableSize, int);
vtkGetMacro(ScaleTableSize, int);
// Description:
// Convenience method to set the array to scale with.
vtkSetStringMacro(ScaleArray);
vtkGetStringMacro(ScaleArray);
// Description:
// Set the default radius of the point gaussians. This is used if the
// array to scale with has not been set or is set to NULL. If there
// is no scale array and the default radius is set to zero then
// the splats wil be rendered as simple points requiring less memory.
vtkSetMacro(DefaultRadius,double);
vtkGetMacro(DefaultRadius,double);
// Set the default scale factor of the point gaussians. This
// defaults to 1.0. All radius computations will be scaled by the factor
// including the ScaleArray. If a vtkPiecewideFunction is used the
// scaling happens prior to the function lookup.
// A scale factor of 0.0 indicates that the splats should be rendered
// as simple points.
vtkSetMacro(ScaleFactor,double);
vtkGetMacro(ScaleFactor,double);
// Description:
// Treat the points/splats as emissive light sources. The default is true.
......@@ -88,11 +102,14 @@ protected:
char *OpacityArray;
char *SplatShaderCode;
vtkPiecewiseFunction *ScaleFunction;
int ScaleTableSize;
vtkPiecewiseFunction *ScalarOpacityFunction;
int OpacityTableSize;
double DefaultRadius;
double ScaleFactor;
int Emissive;
int OpacityTableSize;
private:
vtkPointGaussianMapper(const vtkPointGaussianMapper&); // Not implemented.
......
......@@ -48,6 +48,15 @@ public:
vtkPointGaussianMapper *Owner;
bool UsingPoints;
float *OpacityTable; // the table
float OpacityScale; // used for quick lookups
float OpacityOffset; // used for quick lookups
float *ScaleTable; // the table
float ScaleScale; // used for quick lookups
float ScaleOffset; // used for quick lookups
protected:
vtkOpenGLPointGaussianMapperHelper();
~vtkOpenGLPointGaussianMapperHelper();
......@@ -85,18 +94,17 @@ protected:
virtual void RenderPieceDraw(vtkRenderer *ren, vtkActor *act);
// create the array for opacity values
void BuildOpacityArray(vtkPolyData *);
// create the table for opacity values
void BuildOpacityTable(vtkPolyData *);
// create the table for scale values
void BuildScaleTable(vtkPolyData *);
// Description:
// Does the shader source need to be recomputed
virtual bool GetNeedToRebuildShaders(vtkOpenGLHelper &cellBO,
vtkRenderer *ren, vtkActor *act);
bool UsingPoints;
vtkUnsignedCharArray *OpacityData;
private:
vtkOpenGLPointGaussianMapperHelper(const vtkOpenGLPointGaussianMapperHelper&); // Not implemented.
void operator=(const vtkOpenGLPointGaussianMapperHelper&); // Not implemented.
......@@ -109,7 +117,8 @@ vtkStandardNewMacro(vtkOpenGLPointGaussianMapperHelper)
vtkOpenGLPointGaussianMapperHelper::vtkOpenGLPointGaussianMapperHelper()
{
this->Owner = NULL;
this->OpacityData = 0;
this->OpacityTable = 0;
this->ScaleTable = 0;
}
......@@ -120,10 +129,7 @@ void vtkOpenGLPointGaussianMapperHelper::GetShaderTemplate(
{
this->Superclass::GetShaderTemplate(shaders,ren,actor);
vtkPolyData *poly = this->CurrentInput;
bool hasScaleArray = this->Owner->GetScaleArray() != NULL &&
poly->GetPointData()->HasArray(this->Owner->GetScaleArray());
if (!hasScaleArray && this->Owner->GetDefaultRadius() == 0.0)
if (this->Owner->GetScaleFactor() == 0.0)
{
this->UsingPoints = true;
}
......@@ -229,10 +235,15 @@ bool vtkOpenGLPointGaussianMapperHelper::GetNeedToRebuildShaders(
//-----------------------------------------------------------------------------
vtkOpenGLPointGaussianMapperHelper::~vtkOpenGLPointGaussianMapperHelper()
{
if (this->OpacityData)
if (this->OpacityTable)
{
this->OpacityData->Delete();
this->OpacityData = 0;
delete [] this->OpacityTable;
this->OpacityTable = 0;
}
if (this->ScaleTable)
{
delete [] this->ScaleTable;
this->ScaleTable = 0;
}
}
......@@ -300,268 +311,172 @@ void vtkOpenGLPointGaussianMapperHelper::SetMapperShaderParameters(vtkOpenGLHelp
namespace
{
// internal function called by CreateVBO
// if verts are provided then we only draw those points
// otherwise we draw all the points
template< typename PointDataType, typename SizeDataType >
void vtkOpenGLPointGaussianMapperHelperPackVBOTemplate2(
void vtkOpenGLPointGaussianMapperHelperPackVBOTemplate3(
std::vector< float >::iterator& it,
PointDataType* points, vtkIdType numPts,
vtkCellArray *verts,
PointDataType* points,
SizeDataType* sizes,
vtkIdType index,
vtkOpenGLPointGaussianMapperHelper *self,
unsigned char *colors, int colorComponents,
SizeDataType* sizes, float defaultSize,
unsigned char* opacityData)
vtkDataArray *opacities, float defaultScale)
{
PointDataType *pointPtr;
unsigned char *colorPtr;
unsigned char white[4] = {255, 255, 255, 255};
vtkucfloat rcolor;
int count = 0;
// if there are no per point sizes and the default size is zero
// then just render points, saving memory and speed
if (!sizes && defaultSize == 0.0)
pointPtr = points + index*3;
colorPtr = colors ? (colors + index*colorComponents) : white;
rcolor.c[0] = *(colorPtr++);
rcolor.c[1] = *(colorPtr++);
rcolor.c[2] = *(colorPtr++);
if (opacities)
{
if (verts->GetNumberOfCells())
{
vtkIdType* indices(NULL);
vtkIdType npts(0);
for (verts->InitTraversal(); verts->GetNextCell(npts, indices); )
{
for (int i = 0; i < npts; ++i)
{
pointPtr = points + indices[i]*3;
colorPtr = colors ? (colors + indices[i]*colorComponents) : white;
rcolor.c[0] = *(colorPtr++);
rcolor.c[1] = *(colorPtr++);
rcolor.c[2] = *(colorPtr++);
rcolor.c[3] = *(colorPtr++);
if (opacityData)
{
rcolor.c[3] = opacityData[count];
}
// Vertices
*(it++) = pointPtr[0];
*(it++) = pointPtr[1];
*(it++) = pointPtr[2];
*(it++) = rcolor.f;
count++;
}
}
}
else
float opacity = opacities->GetComponent(index,0);
if (self->OpacityTable)
{
for (vtkIdType i = 0; i < numPts; ++i)
{
pointPtr = points + i*3;
colorPtr = colors ? (colors + i*colorComponents) : white;
rcolor.c[0] = *(colorPtr++);
rcolor.c[1] = *(colorPtr++);
rcolor.c[2] = *(colorPtr++);
rcolor.c[3] = *(colorPtr++);
if (opacityData)
{
rcolor.c[3] = opacityData[i];
}
// Vertices
*(it++) = pointPtr[0];
*(it++) = pointPtr[1];
*(it++) = pointPtr[2];
*(it++) = rcolor.f;
}
float index = (opacity - self->OpacityOffset)*self->OpacityScale;
int iindex = static_cast<int>(index);
opacity = (1.0 - index + iindex)*self->OpacityTable[iindex] +
(index - iindex)*self->OpacityTable[iindex+1];
}
rcolor.c[3] = opacity*255.0;
}
else
{
rcolor.c[3] = (colorComponents == 4 ? *colorPtr : 255);
}
if (self->UsingPoints)
{
// Vertices
*(it++) = pointPtr[0];
*(it++) = pointPtr[1];
*(it++) = pointPtr[2];
*(it++) = rcolor.f;
}
else // otherwise splats
{
float cos30 = cos(vtkMath::RadiansFromDegrees(30.0));
if (verts->GetNumberOfCells())
float radius = sizes ? sizes[index] : 1.0;
radius *= defaultScale;
if (self->ScaleTable)
{
vtkIdType* indices(NULL);
vtkIdType npts(0);
for (verts->InitTraversal(); verts->GetNextCell(npts, indices); )
{
for (int i = 0; i < npts; ++i)
{
pointPtr = points + indices[i]*3;
colorPtr = colors ? (colors + indices[i]*colorComponents) : white;
rcolor.c[0] = *(colorPtr++);
rcolor.c[1] = *(colorPtr++);
rcolor.c[2] = *(colorPtr++);
rcolor.c[3] = *(colorPtr++);
if (opacityData)
{
rcolor.c[3] = opacityData[count];
}
float radius = sizes ? sizes[indices[i]] : defaultSize;
radius *= 3.0;
// Vertices
*(it++) = pointPtr[0];
*(it++) = pointPtr[1];
*(it++) = pointPtr[2];
*(it++) = rcolor.f;
*(it++) = -2.0f*radius*cos30;
*(it++) = -radius;
*(it++) = pointPtr[0];
*(it++) = pointPtr[1];
*(it++) = pointPtr[2];
*(it++) = rcolor.f;
*(it++) = 2.0f*radius*cos30;
*(it++) = -radius;
*(it++) = pointPtr[0];
*(it++) = pointPtr[1];
*(it++) = pointPtr[2];
*(it++) = rcolor.f;
*(it++) = 0.0f;
*(it++) = 2.0f*radius;
count++;
}
}
float index = (radius - self->ScaleOffset)*self->ScaleScale;
int iindex = static_cast<int>(index);
radius = (1.0 - index + iindex)*self->ScaleTable[iindex] +
(index - iindex)*self->ScaleTable[iindex+1];
}
else
radius *= 3.0;
// Vertices
*(it++) = pointPtr[0];
*(it++) = pointPtr[1];
*(it++) = pointPtr[2];
*(it++) = rcolor.f;
*(it++) = -2.0f*radius*cos30;
*(it++) = -radius;
*(it++) = pointPtr[0];
*(it++) = pointPtr[1];
*(it++) = pointPtr[2];
*(it++) = rcolor.f;
*(it++) = 2.0f*radius*cos30;
*(it++) = -radius;
*(it++) = pointPtr[0];
*(it++) = pointPtr[1];
*(it++) = pointPtr[2];
*(it++) = rcolor.f;
*(it++) = 0.0f;
*(it++) = 2.0f*radius;
}
}
// internal function called by CreateVBO
// if verts are provided then we only draw those points
// otherwise we draw all the points
template< typename PointDataType, typename SizeDataType >
void vtkOpenGLPointGaussianMapperHelperPackVBOTemplate2(
std::vector< float >::iterator& it,
PointDataType* points, vtkIdType numPts,
vtkOpenGLPointGaussianMapperHelper *self,
vtkCellArray *verts,
unsigned char *colors, int colorComponents,
SizeDataType* sizes, vtkDataArray *opacities)
{
float defaultSize = self->Owner->GetScaleFactor();
// iterate over cells or not
if (verts->GetNumberOfCells())
{
vtkIdType* indices(NULL);
vtkIdType npts(0);
for (verts->InitTraversal(); verts->GetNextCell(npts, indices); )
{
for (vtkIdType i = 0; i < numPts; ++i)
for (int i = 0; i < npts; ++i)
{
pointPtr = points + i*3;
colorPtr = colors ? (colors + i*colorComponents) : white;
rcolor.c[0] = *(colorPtr++);
rcolor.c[1] = *(colorPtr++);
rcolor.c[2] = *(colorPtr++);
rcolor.c[3] = *(colorPtr++);
if (opacityData)
{
rcolor.c[3] = opacityData[i];
}
float radius = sizes ? sizes[i] : defaultSize;
radius *= 3.0;
// Vertices
*(it++) = pointPtr[0];
*(it++) = pointPtr[1];
*(it++) = pointPtr[2];
*(it++) = rcolor.f;
*(it++) = -2.0f*radius*cos30;
*(it++) = -radius;
*(it++) = pointPtr[0];
*(it++) = pointPtr[1];
*(it++) = pointPtr[2];
*(it++) = rcolor.f;
*(it++) = 2.0f*radius*cos30;
*(it++) = -radius;
*(it++) = pointPtr[0];
*(it++) = pointPtr[1];
*(it++) = pointPtr[2];
*(it++) = rcolor.f;
*(it++) = 0.0f;
*(it++) = 2.0f*radius;
vtkOpenGLPointGaussianMapperHelperPackVBOTemplate3(
it, points, sizes, indices[i], self,
colors, colorComponents, opacities, defaultSize);
}
}
}
else
{
for (vtkIdType i = 0; i < numPts; ++i)
{
vtkOpenGLPointGaussianMapperHelperPackVBOTemplate3(
it, points, sizes, i, self,
colors, colorComponents, opacities, defaultSize);
}
}
}
template< typename PointDataType >
void vtkOpenGLPointGaussianMapperHelperPackVBOTemplate(
std::vector< float >::iterator& it,
PointDataType* points, vtkIdType numPts,
vtkOpenGLPointGaussianMapperHelper *self,
vtkCellArray *verts,
unsigned char *colors, int colorComponents,
vtkDataArray* sizes, float defaultSize,
unsigned char *opacityData)
vtkDataArray* sizes, vtkDataArray *opacities)
{
if (sizes)
{
switch (sizes->GetDataType())
{
vtkTemplateMacro(
vtkTemplateMacro(
vtkOpenGLPointGaussianMapperHelperPackVBOTemplate2(
it, points, numPts, verts, colors, colorComponents,
static_cast<VTK_TT*>(sizes->GetVoidPointer(0)),
defaultSize, opacityData)
it, points, numPts,
self, verts,
colors, colorComponents,
static_cast<VTK_TT*>(sizes->GetVoidPointer(0)), opacities)
);
}
}
else
{
vtkOpenGLPointGaussianMapperHelperPackVBOTemplate2(
it, points, numPts, verts, colors, colorComponents,
static_cast<float*>(NULL), defaultSize, opacityData);
it, points, numPts,
self, verts,
colors, colorComponents,
static_cast<float*>(NULL), opacities);
}
}
void vtkOpenGLPointGaussianMapperHelperCreateVBO(
vtkPoints* points,
vtkCellArray *verts,
unsigned char* colors, int colorComponents,
vtkDataArray* sizes, float defaultSize,
vtkOpenGLVertexBufferObject *VBO,
bool usingPoints, unsigned char *opacityData)
{
// Figure out how big each block will be, currently 6 floats.
int blockSize = 3; // x y z
VBO->VertexOffset = 0;
VBO->NormalOffset = 0;
VBO->TCoordOffset = 0;
VBO->TCoordComponents = 0;
// VBO->ColorComponents = colorComponents;
VBO->ColorComponents = 4;
VBO->ColorOffset = sizeof(float) * blockSize;
++blockSize; // color
if (usingPoints)
{
VBO->Stride = sizeof(float) * blockSize;
// Create a buffer, and copy the data over.
VBO->PackedVBO.resize(blockSize * points->GetNumberOfPoints());
std::vector<float>::iterator it = VBO->PackedVBO.begin();
switch(points->GetDataType())
{
vtkTemplateMacro(
vtkOpenGLPointGaussianMapperHelperPackVBOTemplate(
it, static_cast<VTK_TT*>(points->GetVoidPointer(0)),
points->GetNumberOfPoints(),
verts,
colors,colorComponents,
sizes,defaultSize, opacityData));
}
VBO->Upload(VBO->PackedVBO, vtkOpenGLBufferObject::ArrayBuffer);
VBO->VertexCount = points->GetNumberOfPoints();
}
else
{
// two more floats
blockSize += 2; // offset
VBO->Stride = sizeof(float) * blockSize;
// Create a buffer, and copy the data over.
VBO->PackedVBO.resize(blockSize * points->GetNumberOfPoints() * 3);
std::vector<float>::iterator it = VBO->PackedVBO.begin();
switch(points->GetDataType())
{
vtkTemplateMacro(
vtkOpenGLPointGaussianMapperHelperPackVBOTemplate(
it, static_cast<VTK_TT*>(points->GetVoidPointer(0)),
points->GetNumberOfPoints(),
verts,
colors,colorComponents,
sizes, defaultSize, opacityData));
}
VBO->Upload(VBO->PackedVBO, vtkOpenGLBufferObject::ArrayBuffer);
VBO->VertexCount = points->GetNumberOfPoints() * 3;
}
return;
}
}
} // anonymous namespace
//-------------------------------------------------------------------------
bool vtkOpenGLPointGaussianMapperHelper::GetNeedToRebuildBufferObjects(
......@@ -574,7 +489,9 @@ bool vtkOpenGLPointGaussianMapperHelper::GetNeedToRebuildBufferObjects(
this->VBOBuildTime < this->CurrentInput->GetMTime() ||
this->VBOBuildTime < this->Owner->GetMTime() ||
(this->Owner->GetScalarOpacityFunction() &&
this->VBOBuildTime < this->Owner->GetScalarOpacityFunction()->GetMTime())
this->VBOBuildTime < this->Owner->GetScalarOpacityFunction()->GetMTime()) ||
(this->Owner->GetScaleFunction() &&
this->VBOBuildTime < this->Owner->GetScaleFunction()->GetMTime())
)
{
return true;
......@@ -583,13 +500,8 @@ bool vtkOpenGLPointGaussianMapperHelper::GetNeedToRebuildBufferObjects(
}
//-------------------------------------------------------------------------
void vtkOpenGLPointGaussianMapperHelper::BuildOpacityArray(vtkPolyData *poly)
void vtkOpenGLPointGaussianMapperHelper::BuildOpacityTable(vtkPolyData *poly)
{
if (!this->OpacityData)
{
this->OpacityData = vtkUnsignedCharArray::New();
}
vtkDataArray *oda =
poly->GetPointData()->GetArray(this->Owner->GetOpacityArray());
double range[2];
......@@ -598,55 +510,50 @@ void vtkOpenGLPointGaussianMapperHelper::BuildOpacityArray(vtkPolyData *poly)
// if a piecewise function was provided, use it to map the opacities
vtkPiecewiseFunction *pwf = this->Owner->GetScalarOpacityFunction();
int tableSize = this->Owner->GetOpacityTableSize();
float *table = new float[tableSize+1];
if (this->OpacityTable)
{
delete [] this->OpacityTable;
}
this->OpacityTable = new float [tableSize+1];
if (pwf)
{
// build the interpolation table
pwf->GetTable(range[0],range[1],tableSize,table);
pwf->GetTable(range[0],range[1],tableSize,this->OpacityTable);
// duplicate the last value for bilinear interp edge case
table[tableSize] = table[tableSize-1];
this->OpacityTable[tableSize] = this->OpacityTable[tableSize-1];
this->OpacityScale = (tableSize - 1.0)/(range[1] - range[0]);
this->OpacityOffset = range[0];
}
vtkCellArray *verts = poly->GetVerts();
vtkIdType count = 0;
vtkIdType npts = 0;
if (verts->GetNumberOfCells())
}
//-------------------------------------------------------------------------
void vtkOpenGLPointGaussianMapperHelper::BuildScaleTable(vtkPolyData *poly)
{
vtkDataArray *oda =
poly->GetPointData()->GetArray(this->Owner->GetScaleArray());
double range[2];
oda->GetRange(range,0);
// if a piecewise function was provided, use it to map the opacities
vtkPiecewiseFunction *pwf = this->Owner->GetScaleFunction();
int tableSize = this->Owner->GetScaleTableSize();
if (this->ScaleTable)
{
vtkIdType* indices(NULL);
for (verts->InitTraversal(); verts->GetNextCell(npts, indices); )
{
for (int i = 0; i < npts; ++i)
{
float value = oda->GetComponent(indices[i],0);
if (pwf)
{
float index = (tableSize - 1.0)*(value - range[0])/(range[1] - range[0]);
int iindex = static_cast<int>(index);
value = (1.0 - index + iindex)*table[iindex] + (index - iindex)*table[iindex+1];
}
this->OpacityData->InsertValue(count,value*255.0);
count++;
}
}
delete [] this->ScaleTable;
}
else
this->ScaleTable = new float [tableSize+1];
if (pwf)
{
npts = poly->GetPoints()->GetNumberOfPoints();
for (int i = 0; i < npts; ++i)
{
float value = oda->GetComponent(i,0);
if (pwf)
{
float index = (tableSize-1.0)*(value - range[0])/(range[1] - range[0]);
int iindex = static_cast<int>(index);
value = (1.0 - index + iindex)*table[iindex] + (index - iindex)*table[iindex+1];
}
this->OpacityData->InsertValue(count,value*255.0);
count++;
}
// build the interpolation table
pwf->GetTable(range[0],range[1],tableSize,this->ScaleTable);
// duplicate the last value for bilinear interp edge case
this->ScaleTable[tableSize] = this->ScaleTable[tableSize-1];
this->ScaleScale = (tableSize - 1.0)/(range[1] - range[0]);
this->ScaleOffset = range[0];
}
delete [] table;
}
//-------------------------------------------------------------------------
......@@ -655,14 +562,27 @@ void vtkOpenGLPointGaussianMapperHelper::BuildBufferObjects(
{
vtkPolyData *poly = this->CurrentInput;
if (poly == NULL)// || !poly->GetPointData()->GetNormals())
if (poly == NULL)
{
return;
}
bool hasScaleArray = this->Owner->GetScaleArray() != NULL &&