diff --git a/Rendering/Core/vtkPointGaussianMapper.cxx b/Rendering/Core/vtkPointGaussianMapper.cxx
index b9b289094895c54da2206f6ecab38a9c86c5e352..15faefe4712f771b055c5c836a4adf25ae08df2e 100644
--- a/Rendering/Core/vtkPointGaussianMapper.cxx
+++ b/Rendering/Core/vtkPointGaussianMapper.cxx
@@ -14,15 +14,28 @@
#include "vtkPointGaussianMapper.h"
#include "vtkObjectFactory.h"
+#include "vtkPiecewiseFunction.h"
//-----------------------------------------------------------------------------
vtkAbstractObjectFactoryNewMacro(vtkPointGaussianMapper)
+vtkCxxSetObjectMacro(vtkPointGaussianMapper, ScaleFunction, vtkPiecewiseFunction);
+vtkCxxSetObjectMacro(vtkPointGaussianMapper, ScalarOpacityFunction, vtkPiecewiseFunction);
+
//-----------------------------------------------------------------------------
vtkPointGaussianMapper::vtkPointGaussianMapper()
{
this->ScaleArray = 0;
- this->DefaultRadius = 1.0;
+ this->OpacityArray = 0;
+ this->SplatShaderCode = 0;
+
+ this->ScaleFunction = 0;
+ this->ScaleTableSize = 1024;
+
+ this->ScalarOpacityFunction = 0;
+ this->OpacityTableSize = 1024;
+
+ this->ScaleFactor = 1.0;
this->Emissive = 1;
}
@@ -30,6 +43,10 @@ vtkPointGaussianMapper::vtkPointGaussianMapper()
vtkPointGaussianMapper::~vtkPointGaussianMapper()
{
this->SetScaleArray(0);
+ this->SetOpacityArray(0);
+ this->SetSplatShaderCode(0);
+ this->SetScalarOpacityFunction(0);
+ this->SetScaleFunction(0);
}
//-----------------------------------------------------------------------------
@@ -38,6 +55,10 @@ void vtkPointGaussianMapper::PrintSelf(ostream& os, vtkIndent indent)
this->Superclass::PrintSelf(os, indent);
os << indent << "Scale Array: " << (this->ScaleArray ? this->ScaleArray : "(none)") << "\n";
- os << indent << "Default Radius: " << this->DefaultRadius << "\n";
+ os << indent << "Opacity Array: " << (this->OpacityArray ? this->OpacityArray : "(none)") << "\n";
+ os << indent << "SplatShaderCode: " << (this->SplatShaderCode ? this->SplatShaderCode : "(none)") << "\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";
}
diff --git a/Rendering/Core/vtkPointGaussianMapper.h b/Rendering/Core/vtkPointGaussianMapper.h
index 1a7aa02c2c3e1af80d31c24d70b1ac9a6390ac24..079eb18ed0f160ba4bdedfc497a4ec17cebff44a 100644
--- a/Rendering/Core/vtkPointGaussianMapper.h
+++ b/Rendering/Core/vtkPointGaussianMapper.h
@@ -23,6 +23,8 @@
#include "vtkRenderingCoreModule.h" // For export macro
#include "vtkPolyDataMapper.h"
+class vtkPiecewiseFunction;
+
class VTKRENDERINGCORE_EXPORT vtkPointGaussianMapper : public vtkPolyDataMapper
{
public:
@@ -30,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.
@@ -49,12 +65,50 @@ public:
vtkGetMacro(Emissive, int);
vtkBooleanMacro(Emissive, int);
+ // Description:
+ // Set/Get the optional opacity transfer function. This is only
+ // used when an OpacityArray is also specified.
+ void SetScalarOpacityFunction(vtkPiecewiseFunction *);
+ vtkGetObjectMacro(ScalarOpacityFunction,vtkPiecewiseFunction);
+
+ // Description:
+ // The size of the table used in computing opacities, used when
+ // converting a vtkPiecewiseFunction to a table
+ vtkSetMacro(OpacityTableSize, int);
+ vtkGetMacro(OpacityTableSize, int);
+
+ // Description:
+ // Method to set the optional opacity array. If specified this
+ // array will be used to generate the opacity values.
+ vtkSetStringMacro(OpacityArray);
+ vtkGetStringMacro(OpacityArray);
+
+ // Description:
+ // Method to override the fragment shader code for the splat. You can
+ // set this to draw other shapes. For the OPenGL2 backend some of
+ // the variables you can use and/or modify include,
+ // opacity - 0.0 to 1.0
+ // diffuseColor - vec3
+ // ambientColor - vec3
+ // offsetVCVSOutput - vec2 offset in view coordinates from the splat center
+ vtkSetStringMacro(SplatShaderCode);
+ vtkGetStringMacro(SplatShaderCode);
+
protected:
vtkPointGaussianMapper();
~vtkPointGaussianMapper();
char *ScaleArray;
- double DefaultRadius;
+ char *OpacityArray;
+ char *SplatShaderCode;
+
+ vtkPiecewiseFunction *ScaleFunction;
+ int ScaleTableSize;
+
+ vtkPiecewiseFunction *ScalarOpacityFunction;
+ int OpacityTableSize;
+
+ double ScaleFactor;
int Emissive;
private:
diff --git a/Rendering/OpenGL2/Testing/Cxx/CMakeLists.txt b/Rendering/OpenGL2/Testing/Cxx/CMakeLists.txt
index 407b121b84f2fc26ab320171c606726e3a4a9b6b..5a0841e1aa09be68bdc276314a03b25d763f84aa 100644
--- a/Rendering/OpenGL2/Testing/Cxx/CMakeLists.txt
+++ b/Rendering/OpenGL2/Testing/Cxx/CMakeLists.txt
@@ -1,6 +1,7 @@
vtk_add_test_cxx(${vtk-module}CxxTests tests
#TestRenderWidget.cxx # Very experimental, fails, does nothing useful yet.
TestPointGaussianMapper.cxx
+ TestPointGaussianMapperOpacity.cxx
TestVBOPLYMapper.cxx
TestVBOPointsLines.cxx
TestGaussianBlurPass.cxx
diff --git a/Rendering/OpenGL2/Testing/Cxx/TestPointGaussianMapper.cxx b/Rendering/OpenGL2/Testing/Cxx/TestPointGaussianMapper.cxx
index b30dbafccf547df81f20b95c8d69b2efe3ff362f..b84ee9099c19bf56284e9caf506027f9f4e398c5 100644
--- a/Rendering/OpenGL2/Testing/Cxx/TestPointGaussianMapper.cxx
+++ b/Rendering/OpenGL2/Testing/Cxx/TestPointGaussianMapper.cxx
@@ -16,7 +16,8 @@
// .SECTION Thanks
//
//
-// This file is part of the PointSprites plugin developed and contributed by
+// This file is based loosely on the PointSprites plugin developed
+// and contributed by
//
// Copyright (c) CSCS - Swiss National Supercomputing Centre
// EDF - Electricite de France
@@ -25,8 +26,6 @@
// Stephane Ploix (EDF)
//
//
-// .SECTION Description
-// this program tests the point sprite support by vtkPointSpriteProperty.
#include "vtkActor.h"
diff --git a/Rendering/OpenGL2/Testing/Cxx/TestPointGaussianMapperOpacity.cxx b/Rendering/OpenGL2/Testing/Cxx/TestPointGaussianMapperOpacity.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b8afe014a84eda2ac1d8904cf1a6fc4eeb11e27c
--- /dev/null
+++ b/Rendering/OpenGL2/Testing/Cxx/TestPointGaussianMapperOpacity.cxx
@@ -0,0 +1,163 @@
+/*=========================================================================
+
+ Program: Visualization Toolkit
+ Module: TestSprites.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.
+
+ =========================================================================*/
+
+// .SECTION Thanks
+//
+//
+// This file is based loosely on the PointSprites plugin developed
+// and contributed by
+//
+// Copyright (c) CSCS - Swiss National Supercomputing Centre
+// EDF - Electricite de France
+//
+// John Biddiscombe, Ugo Varetto (CSCS)
+// Stephane Ploix (EDF)
+//
+//
+
+#include "vtkActor.h"
+#include "vtkCamera.h"
+#include "vtkColorTransferFunction.h"
+#include "vtkDataObject.h"
+#include "vtkDataSetAttributes.h"
+#include "vtkNew.h"
+#include "vtkPiecewiseFunction.h"
+#include "vtkPointGaussianMapper.h"
+#include "vtkPointSource.h"
+#include "vtkProperty.h"
+#include "vtkRandomAttributeGenerator.h"
+#include "vtkRenderWindow.h"
+#include "vtkRenderWindowInteractor.h"
+#include "vtkRenderer.h"
+#include "vtkSphereSource.h"
+#include "vtkTimerLog.h"
+
+#include "vtkTestUtilities.h"
+#include "vtkRegressionTestImage.h"
+
+int TestPointGaussianMapperOpacity(int argc, char *argv[])
+{
+ int desiredPoints = 1.0e4;
+
+ vtkNew points;
+ points->SetNumberOfPoints(desiredPoints);
+ points->SetRadius(pow(desiredPoints,0.33)*10.0);
+ points->Update();
+
+ vtkNew randomAttr;
+ randomAttr->SetInputConnection(points->GetOutputPort());
+
+ vtkNew mapper;
+
+ vtkNew renderer;
+ renderer->SetBackground(0.0, 0.0, 0.0);
+ vtkNew renderWindow;
+ renderWindow->SetSize(300, 300);
+ renderWindow->SetMultiSamples(0);
+ renderWindow->AddRenderer(renderer.Get());
+ vtkNew iren;
+ iren->SetRenderWindow(renderWindow.Get());
+
+ vtkNew actor;
+ actor->SetMapper(mapper.Get());
+ renderer->AddActor(actor.Get());
+
+ randomAttr->SetDataTypeToFloat();
+ randomAttr->GeneratePointScalarsOn();
+ randomAttr->GeneratePointVectorsOn();
+ randomAttr->GeneratePointArrayOn();
+ randomAttr->Update();
+
+ mapper->SetInputConnection(randomAttr->GetOutputPort());
+ mapper->SetColorModeToMapScalars();
+ mapper->SetScalarModeToUsePointFieldData();
+ mapper->SelectColorArray("RandomPointVectors");
+ mapper->SetInterpolateScalarsBeforeMapping(0);
+ mapper->SetScaleArray("RandomPointScalars");
+ mapper->SetOpacityArray("RandomPointArray");
+ mapper->EmissiveOff();
+
+ // show other shader examples
+ // the fragment that is rendered is that of a triangle
+ // large enough to encompass a circle of radius 3
+ mapper->SetSplatShaderCode(
+ // this first line keeps the default color opacity calcs
+ // which you can then modify with additional code below
+ "//VTK::Color::Impl\n"
+
+ // example of a circle with black edges
+ // " float dist = sqrt(dot(offsetVCVSOutput.xy,offsetVCVSOutput.xy));\n"
+ // " if (dist > 1.1) { discard; }\n"
+ // " if (dist < 0.5) { discard; }\n"
+ // // apply a black edge around the circle
+ // " if (dist > 1.0 || dist < 0.6) { diffuseColor = vec3(0,0,0); ambientColor = vec3(0,0,0); }\n"
+
+ // example for a square
+ " if (abs(offsetVCVSOutput.x) > 1.0 || abs(offsetVCVSOutput.y) > 1.0) { discard; }\n"
+ " if (abs(offsetVCVSOutput.x) < 0.6 && abs(offsetVCVSOutput.y) < 0.6) { discard; }\n"
+ );
+
+ vtkNew ctf;
+ ctf->AddHSVPoint(0.0,0.1,0.7,1.0);
+ ctf->AddHSVPoint(1.0,0.9,0.7,1.0);
+ ctf->SetColorSpaceToHSV();
+ ctf->HSVWrapOff();
+ mapper->SetLookupTable(ctf.Get());
+
+ vtkNew otf;
+ otf->AddPoint(0.0,0.3);
+ otf->AddPoint(1.0,1.0);
+ mapper->SetScalarOpacityFunction(otf.Get());
+
+ vtkNew timer;
+ timer->StartTimer();
+ renderWindow->Render();
+ timer->StopTimer();
+ double firstRender = timer->GetElapsedTime();
+ cerr << "first render time: " << firstRender << endl;
+
+ timer->StartTimer();
+ int numRenders = 85;
+ for (int i = 0; i < numRenders; ++i)
+ {
+ renderer->GetActiveCamera()->Azimuth(1);
+ renderer->GetActiveCamera()->Elevation(1);
+ renderWindow->Render();
+ }
+ timer->StopTimer();
+ double elapsed = timer->GetElapsedTime();
+
+ int numPts = mapper->GetInput()->GetPoints()->GetNumberOfPoints();
+ cerr << "interactive render time: " << elapsed / numRenders << endl;
+ cerr << "number of points: " << numPts << endl;
+ cerr << "points per second: " << numPts*(numRenders/elapsed) << endl;
+
+ renderer->GetActiveCamera()->SetPosition(0,0,1);
+ renderer->GetActiveCamera()->SetFocalPoint(0,0,0);
+ renderer->GetActiveCamera()->SetViewUp(0,1,0);
+ renderer->ResetCamera();
+ // renderer->GetActiveCamera()->Print(cerr);
+
+ renderer->GetActiveCamera()->Zoom(10.0);
+ renderWindow->Render();
+
+ int retVal = vtkRegressionTestImage( renderWindow.Get() );
+ if ( retVal == vtkRegressionTester::DO_INTERACTOR)
+ {
+ iren->Start();
+ }
+
+ return !retVal;
+}
diff --git a/Rendering/OpenGL2/Testing/Data/Baseline/TestPointGaussianMapperOpacity.png.md5 b/Rendering/OpenGL2/Testing/Data/Baseline/TestPointGaussianMapperOpacity.png.md5
new file mode 100644
index 0000000000000000000000000000000000000000..2d04e419e31f8326db76c2710625090fb6a23fea
--- /dev/null
+++ b/Rendering/OpenGL2/Testing/Data/Baseline/TestPointGaussianMapperOpacity.png.md5
@@ -0,0 +1 @@
+b666713a87d680a410bdc29aea9f5174
diff --git a/Rendering/OpenGL2/vtkOpenGLPointGaussianMapper.cxx b/Rendering/OpenGL2/vtkOpenGLPointGaussianMapper.cxx
index 06964bd3fdc50446bd8760f5fc48d7885e690489..fa2944f31a63a3c5e0baed7d4ef8427840b9a7e6 100644
--- a/Rendering/OpenGL2/vtkOpenGLPointGaussianMapper.cxx
+++ b/Rendering/OpenGL2/vtkOpenGLPointGaussianMapper.cxx
@@ -15,6 +15,7 @@
#include "vtkOpenGLHelper.h"
+#include "vtkCellArray.h"
#include "vtkHardwareSelector.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
@@ -25,6 +26,7 @@
#include "vtkOpenGLPolyDataMapper.h"
#include "vtkOpenGLVertexArrayObject.h"
#include "vtkOpenGLVertexBufferObject.h"
+#include "vtkPiecewiseFunction.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkProperty.h"
@@ -46,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();
@@ -83,13 +94,17 @@ protected:
virtual void RenderPieceDraw(vtkRenderer *ren, vtkActor *act);
+ // 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;
-
private:
vtkOpenGLPointGaussianMapperHelper(const vtkOpenGLPointGaussianMapperHelper&); // Not implemented.
void operator=(const vtkOpenGLPointGaussianMapperHelper&); // Not implemented.
@@ -102,6 +117,8 @@ vtkStandardNewMacro(vtkOpenGLPointGaussianMapperHelper)
vtkOpenGLPointGaussianMapperHelper::vtkOpenGLPointGaussianMapperHelper()
{
this->Owner = NULL;
+ this->OpacityTable = 0;
+ this->ScaleTable = 0;
}
@@ -112,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;
}
@@ -159,20 +173,25 @@ void vtkOpenGLPointGaussianMapperHelper::ReplaceShaderColor(
{
if (!this->UsingPoints)
{
- std::string VSSource = shaders[vtkShader::Vertex]->GetSource();
std::string FSSource = shaders[vtkShader::Fragment]->GetSource();
- vtkShaderProgram::Substitute(FSSource,"//VTK::Color::Impl",
- // compute the eye position and unit direction
- "//VTK::Color::Impl\n"
- " float dist2 = dot(offsetVCVSOutput.xy,offsetVCVSOutput.xy);\n"
- " if (dist2 > 9.0) { discard; }\n"
- " float gaussian = exp(-0.5*dist2);\n"
- " opacity = opacity*gaussian;"
- // " opacity = opacity*0.5;"
- , false);
-
- shaders[vtkShader::Vertex]->SetSource(VSSource);
+ if (this->Owner->GetSplatShaderCode())
+ {
+ vtkShaderProgram::Substitute(FSSource,"//VTK::Color::Impl",
+ this->Owner->GetSplatShaderCode(), false);
+ }
+ else
+ {
+ vtkShaderProgram::Substitute(FSSource,"//VTK::Color::Impl",
+ // compute the eye position and unit direction
+ "//VTK::Color::Impl\n"
+ " float dist2 = dot(offsetVCVSOutput.xy,offsetVCVSOutput.xy);\n"
+ " if (dist2 > 9.0) { discard; }\n"
+ " float gaussian = exp(-0.5*dist2);\n"
+ " opacity = opacity*gaussian;"
+ // " opacity = opacity*0.5;"
+ , false);
+ }
shaders[vtkShader::Fragment]->SetSource(FSSource);
}
@@ -216,6 +235,16 @@ bool vtkOpenGLPointGaussianMapperHelper::GetNeedToRebuildShaders(
//-----------------------------------------------------------------------------
vtkOpenGLPointGaussianMapperHelper::~vtkOpenGLPointGaussianMapperHelper()
{
+ if (this->OpacityTable)
+ {
+ delete [] this->OpacityTable;
+ this->OpacityTable = 0;
+ }
+ if (this->ScaleTable)
+ {
+ delete [] this->ScaleTable;
+ this->ScaleTable = 0;
+ }
}
//-----------------------------------------------------------------------------
@@ -282,69 +311,135 @@ 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,
+ PointDataType* points,
+ SizeDataType* sizes,
+ vtkIdType index,
+ vtkOpenGLPointGaussianMapperHelper *self,
unsigned char *colors, int colorComponents,
- SizeDataType* sizes, float defaultSize)
+ vtkDataArray *opacities, float defaultScale)
{
PointDataType *pointPtr;
unsigned char *colorPtr;
+ unsigned char white[4] = {255, 255, 255, 255};
+ vtkucfloat rcolor;
+
// 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)
- {
- unsigned char white[4] = {255, 255, 255, 255};
+ pointPtr = points + index*3;
+ colorPtr = colors ? (colors + index*colorComponents) : white;
+ rcolor.c[0] = *(colorPtr++);
+ rcolor.c[1] = *(colorPtr++);
+ rcolor.c[2] = *(colorPtr++);
- for (vtkIdType i = 0; i < numPts; ++i)
+ if (opacities)
+ {
+ float opacity = opacities->GetComponent(index,0);
+ if (self->OpacityTable)
{
- pointPtr = points + i*3;
- colorPtr = colors ? (colors + i*colorComponents) : white;
-
- // Vertices
- *(it++) = pointPtr[0];
- *(it++) = pointPtr[1];
- *(it++) = pointPtr[2];
- *(it++) = *reinterpret_cast(colorPtr);
+ float tindex = (opacity - self->OpacityOffset)*self->OpacityScale;
+ int itindex = static_cast(tindex);
+ opacity = (1.0 - tindex + itindex)*self->OpacityTable[itindex] +
+ (tindex - itindex)*self->OpacityTable[itindex+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));
- unsigned char white[4] = {255, 255, 255, 255};
+ float radius = sizes ? sizes[index] : 1.0;
+ radius *= defaultScale;
+ if (self->ScaleTable)
+ {
+ float tindex = (radius - self->ScaleOffset)*self->ScaleScale;
+ int itindex = static_cast(tindex);
+ radius = (1.0 - tindex + itindex)*self->ScaleTable[itindex] +
+ (tindex - itindex)*self->ScaleTable[itindex+1];
+ }
+
+ 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 (int i = 0; i < npts; ++i)
+ {
+ vtkOpenGLPointGaussianMapperHelperPackVBOTemplate3(
+ it, points, sizes, indices[i], self,
+ colors, colorComponents, opacities, defaultSize);
+ }
+ }
+ }
+ else
+ {
for (vtkIdType i = 0; i < numPts; ++i)
{
- pointPtr = points + i*3;
- colorPtr = colors ? (colors + i*colorComponents) : white;
- float radius = sizes ? sizes[i] : defaultSize;
- radius *= 3.0;
-
- // Vertices
- *(it++) = pointPtr[0];
- *(it++) = pointPtr[1];
- *(it++) = pointPtr[2];
- *(it++) = *reinterpret_cast(colorPtr);
- *(it++) = -2.0f*radius*cos30;
- *(it++) = -radius;
-
- *(it++) = pointPtr[0];
- *(it++) = pointPtr[1];
- *(it++) = pointPtr[2];
- *(it++) = *reinterpret_cast(colorPtr);
- *(it++) = 2.0f*radius*cos30;
- *(it++) = -radius;
-
- *(it++) = pointPtr[0];
- *(it++) = pointPtr[1];
- *(it++) = pointPtr[2];
- *(it++) = *reinterpret_cast(colorPtr);
- *(it++) = 0.0f;
- *(it++) = 2.0f*radius;
+ vtkOpenGLPointGaussianMapperHelperPackVBOTemplate3(
+ it, points, sizes, i, self,
+ colors, colorComponents, opacities, defaultSize);
}
}
}
@@ -353,88 +448,35 @@ 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)
+ vtkDataArray* sizes, vtkDataArray *opacities)
{
if (sizes)
{
switch (sizes->GetDataType())
{
- vtkTemplateMacro(
+ vtkTemplateMacro(
vtkOpenGLPointGaussianMapperHelperPackVBOTemplate2(
- it, points, numPts, colors, colorComponents,
- static_cast(sizes->GetVoidPointer(0)),
- defaultSize)
+ it, points, numPts,
+ self, verts,
+ colors, colorComponents,
+ static_cast(sizes->GetVoidPointer(0)), opacities)
);
}
}
else
{
vtkOpenGLPointGaussianMapperHelperPackVBOTemplate2(
- it, points, numPts, colors, colorComponents,
- static_cast(NULL), defaultSize);
+ it, points, numPts,
+ self, verts,
+ colors, colorComponents,
+ static_cast(NULL), opacities);
}
}
-void vtkOpenGLPointGaussianMapperHelperCreateVBO(
- vtkPoints* points, unsigned char* colors, int colorComponents,
- vtkDataArray* sizes, float defaultSize,
- vtkOpenGLVertexBufferObject *VBO,
- bool usingPoints)
-{
- // 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->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::iterator it = VBO->PackedVBO.begin();
-
- switch(points->GetDataType())
- {
- vtkTemplateMacro(
- vtkOpenGLPointGaussianMapperHelperPackVBOTemplate(
- it, static_cast(points->GetVoidPointer(0)),
- points->GetNumberOfPoints(),colors,colorComponents,
- sizes,defaultSize));
- }
- 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::iterator it = VBO->PackedVBO.begin();
-
- switch(points->GetDataType())
- {
- vtkTemplateMacro(
- vtkOpenGLPointGaussianMapperHelperPackVBOTemplate(
- it, static_cast(points->GetVoidPointer(0)),
- points->GetNumberOfPoints(),colors,colorComponents,
- sizes,defaultSize));
- }
- VBO->Upload(VBO->PackedVBO, vtkOpenGLBufferObject::ArrayBuffer);
- VBO->VertexCount = points->GetNumberOfPoints() * 3;
- }
- return;
-}
-}
+} // anonymous namespace
//-------------------------------------------------------------------------
bool vtkOpenGLPointGaussianMapperHelper::GetNeedToRebuildBufferObjects(
@@ -445,27 +487,102 @@ bool vtkOpenGLPointGaussianMapperHelper::GetNeedToRebuildBufferObjects(
if (this->VBOBuildTime < this->GetMTime() ||
this->VBOBuildTime < act->GetMTime() ||
this->VBOBuildTime < this->CurrentInput->GetMTime() ||
- this->VBOBuildTime < this->Owner->GetMTime())
+ this->VBOBuildTime < this->Owner->GetMTime() ||
+ (this->Owner->GetScalarOpacityFunction() &&
+ this->VBOBuildTime < this->Owner->GetScalarOpacityFunction()->GetMTime()) ||
+ (this->Owner->GetScaleFunction() &&
+ this->VBOBuildTime < this->Owner->GetScaleFunction()->GetMTime())
+ )
{
return true;
}
return false;
}
+//-------------------------------------------------------------------------
+void vtkOpenGLPointGaussianMapperHelper::BuildOpacityTable(vtkPolyData *poly)
+{
+ vtkDataArray *oda =
+ poly->GetPointData()->GetArray(this->Owner->GetOpacityArray());
+ double range[2];
+ oda->GetRange(range,0);
+
+ // if a piecewise function was provided, use it to map the opacities
+ vtkPiecewiseFunction *pwf = this->Owner->GetScalarOpacityFunction();
+ int tableSize = this->Owner->GetOpacityTableSize();
+
+ 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,this->OpacityTable);
+ // duplicate the last value for bilinear interp edge case
+ this->OpacityTable[tableSize] = this->OpacityTable[tableSize-1];
+ this->OpacityScale = (tableSize - 1.0)/(range[1] - range[0]);
+ this->OpacityOffset = range[0];
+ }
+
+}
+
+//-------------------------------------------------------------------------
+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)
+ {
+ delete [] this->ScaleTable;
+ }
+ this->ScaleTable = new float [tableSize+1];
+ if (pwf)
+ {
+ // 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];
+ }
+}
+
//-------------------------------------------------------------------------
void vtkOpenGLPointGaussianMapperHelper::BuildBufferObjects(
vtkRenderer *vtkNotUsed(ren), vtkActor *vtkNotUsed(act))
{
vtkPolyData *poly = this->CurrentInput;
- if (poly == NULL)// || !poly->GetPointData()->GetNormals())
+ if (poly == NULL)
{
return;
}
bool hasScaleArray = this->Owner->GetScaleArray() != NULL &&
- poly->GetPointData()->HasArray(this->Owner->GetScaleArray());
- if (!hasScaleArray && this->Owner->GetDefaultRadius() == 0.0)
+ poly->GetPointData()->HasArray(this->Owner->GetScaleArray());
+ if (hasScaleArray && this->Owner->GetScaleFunction())
+ {
+ this->BuildScaleTable(poly);
+ }
+ else
+ {
+ if (this->ScaleTable)
+ {
+ delete [] this->ScaleTable;
+ this->ScaleTable = 0;
+ }
+ }
+
+ if (this->Owner->GetScaleFactor() == 0.0)
{
this->UsingPoints = true;
}
@@ -474,6 +591,23 @@ void vtkOpenGLPointGaussianMapperHelper::BuildBufferObjects(
this->UsingPoints = false;
}
+ // if we have an opacity array then get it and if we have
+ // a ScalarOpacityFunction map the array through it
+ bool hasOpacityArray = this->Owner->GetOpacityArray() != NULL &&
+ poly->GetPointData()->HasArray(this->Owner->GetOpacityArray());
+ if (hasOpacityArray && this->Owner->GetScalarOpacityFunction())
+ {
+ this->BuildOpacityTable(poly);
+ }
+ else
+ {
+ if (this->OpacityTable)
+ {
+ delete [] this->OpacityTable;
+ this->OpacityTable = 0;
+ }
+ }
+
// For vertex coloring, this sets this->Colors as side effect.
// For texture map coloring, this sets ColorCoordinates
// and ColorTextureMap as a side effect.
@@ -482,16 +616,54 @@ void vtkOpenGLPointGaussianMapperHelper::BuildBufferObjects(
// then the scalars do not have to be regenerted.
this->MapScalars(1.0);
- // Iterate through all of the different types in the polydata, building OpenGLs
- // and IBOs as appropriate for each type.
- vtkOpenGLPointGaussianMapperHelperCreateVBO(
- poly->GetPoints(),
- this->Colors ? (unsigned char *)this->Colors->GetVoidPointer(0) : (unsigned char*)NULL,
- this->Colors ? this->Colors->GetNumberOfComponents() : 0,
- hasScaleArray ? poly->GetPointData()->GetArray(
- this->Owner->GetScaleArray()) : (vtkDataArray*)NULL,
- this->Owner->GetDefaultRadius(),
- this->VBO, this->UsingPoints);
+ // Figure out how big each block will be, currently 6 floats.
+ int blockSize = 3; // x y z
+ this->VBO->VertexOffset = 0;
+ this->VBO->NormalOffset = 0;
+ this->VBO->TCoordOffset = 0;
+ this->VBO->TCoordComponents = 0;
+ this->VBO->ColorComponents = 4;
+ this->VBO->ColorOffset = sizeof(float) * blockSize;
+ ++blockSize; // color
+
+ int splatCount = poly->GetPoints()->GetNumberOfPoints();
+ if (poly->GetVerts()->GetNumberOfCells())
+ {
+ splatCount = poly->GetVerts()->GetNumberOfConnectivityEntries() -
+ poly->GetVerts()->GetNumberOfCells();
+ }
+ if (!this->UsingPoints)
+ {
+ // two more floats
+ blockSize += 2; // offset
+ splatCount *= 3;
+ }
+
+ this->VBO->PackedVBO.resize(blockSize * splatCount);
+ this->VBO->Stride = sizeof(float) * blockSize;
+
+ // Create a buffer, and copy the data over.
+ std::vector::iterator it = this->VBO->PackedVBO.begin();
+
+ switch(poly->GetPoints()->GetDataType())
+ {
+ vtkTemplateMacro(
+ vtkOpenGLPointGaussianMapperHelperPackVBOTemplate(
+ it, static_cast(poly->GetPoints()->GetVoidPointer(0)),
+ poly->GetPoints()->GetNumberOfPoints(),
+ this,
+ poly->GetVerts(),
+ this->Colors ? (unsigned char *)this->Colors->GetVoidPointer(0) : (unsigned char*)NULL,
+ this->Colors ? this->Colors->GetNumberOfComponents() : 0,
+ hasScaleArray ? poly->GetPointData()->GetArray(
+ this->Owner->GetScaleArray()) : (vtkDataArray*)NULL,
+ hasOpacityArray ? poly->GetPointData()->GetArray(
+ this->Owner->GetOpacityArray()) : (vtkDataArray*)NULL
+ ));
+ }
+ this->VBO->Upload(this->VBO->PackedVBO, vtkOpenGLBufferObject::ArrayBuffer);
+
+ this->VBO->VertexCount = splatCount;
// we use no IBO
this->Points.IBO->IndexCount = 0;