Commit 5331a3a2 authored by David E. DeMarle's avatar David E. DeMarle

ENH: Add support for area selection using rendering hardware.

parent f6ae8561
......@@ -20,7 +20,7 @@
#include "vtkPropCollection.h"
#include "vtkWindow.h"
vtkCxxRevisionMacro(vtkViewport, "1.6");
vtkCxxRevisionMacro(vtkViewport, "1.7");
//----------------------------------------------------------------------------
// Create a vtkViewport with a black background, a white ambient light,
......@@ -65,10 +65,13 @@ vtkViewport::vtkViewport()
this->PickedProp = NULL;
this->PickFromProps = NULL;
this->PickResultProps = NULL;
this->IsPicking = 0;
this->CurrentPickId = 0;
this->PickX = -1;
this->PickY = -1;
this->PickX1 = -1;
this->PickY1 = -1;
this->PickX2 = -1;
this->PickY2 = -1;
this->Props = vtkPropCollection::New();
......@@ -97,6 +100,10 @@ vtkViewport::~vtkViewport()
{
this->PickedProp->UnRegister(this);
}
if ( this->PickResultProps != NULL )
{
this->PickResultProps->Delete();
}
}
//----------------------------------------------------------------------------
......@@ -364,8 +371,10 @@ void vtkViewport::PrintSelf(ostream& os, vtkIndent indent)
<< this->WorldPoint[1] << ", " << this->WorldPoint[2] << ", "
<< this->WorldPoint[3] << ")\n";
os << indent << "Pick Position X Y: " << this->PickX
<< " " << this->PickY << endl;
os << indent << "Pick Position X1 Y1: " << this->PickX1
<< " " << this->PickY1 << endl;
os << indent << "Pick Position X2 Y2: " << this->PickX2
<< " " << this->PickY2 << endl;
os << indent << "IsPicking boolean: " << this->IsPicking << endl;
os << indent << "Props:\n";
this->Props->PrintSelf(os,indent.GetNextIndent());
......
......@@ -204,9 +204,12 @@ public:
// Description:
// Methods used to return the pick (x,y) in local display coordinates (i.e.,
// it's that same as selectionX and selectionY).
vtkGetMacro(PickX, double);
vtkGetMacro(PickY, double);
double GetPickX() const {return (this->PickX1 + this->PickX2)*0.5;}
double GetPickY() const {return (this->PickY1 + this->PickY2)*0.5;}
double GetPickWidth() const {return this->PickX2 - this->PickX1 + 1;};
double GetPickHeight() const {return this->PickY2 - this->PickY1 + 1;};
vtkGetMacro(IsPicking, int);
vtkGetObjectMacro(PickResultProps, vtkPropCollection);
// Description:
// Return the Z value for the last picked Prop.
......@@ -265,17 +268,25 @@ protected:
virtual void DonePick() = 0;
// Return the id of the picked object, only valid after a call to DonePick
virtual unsigned int GetPickedId() = 0;
// Return the number of objects picked, only valid after a call to DonePick
virtual unsigned int GetNumPickedIds() = 0;
// Put no more than atMost picked object ids into the callerBuffer and
// return the number of picked objects returned.
virtual int GetPickedIds(unsigned int atMost, unsigned int *callerBuffer) = 0;
//ETX
// Ivars for picking
// Store a picked Prop (contained in an assembly path)
vtkAssemblyPath* PickedProp;
vtkPropCollection* PickFromProps;
vtkPropCollection* PickResultProps;
// Boolean flag to determine if picking is enabled for this render
int IsPicking;
unsigned int CurrentPickId;
double PickX;
double PickY;
double PickX1;
double PickY1;
double PickX2;
double PickY2;
// End Ivars for picking
vtkPropCollection *Props;
......
......@@ -101,7 +101,7 @@ protected:
virtual void Initialize();
void DefineFrustum(double x0, double y0, double x1, double y1, vtkRenderer *renderer);
int PickProps(vtkRenderer *renderer);
virtual int PickProps(vtkRenderer *renderer);
int ABoxFrustumIsect(double bounds[], double &mindist);
vtkPoints *ClipPoints;
......
......@@ -69,6 +69,8 @@ protected:
virtual void UpdatePickId();
virtual void DonePick();
virtual unsigned int GetPickedId();
virtual unsigned int GetNumPickedIds();
virtual int GetPickedIds(unsigned int atMost, unsigned int *callerBuffer);
virtual double GetPickedZ();
// Ivars used in picking
class vtkGLPickInfo* PickInfo;
......
......@@ -26,7 +26,7 @@
#include <math.h>
#ifndef VTK_IMPLEMENT_MESA_CXX
vtkCxxRevisionMacro(vtkOpenGLCamera, "1.64");
vtkCxxRevisionMacro(vtkOpenGLCamera, "1.65");
vtkStandardNewMacro(vtkOpenGLCamera);
#endif
......@@ -105,7 +105,9 @@ void vtkOpenGLCamera::Render(vtkRenderer *ren)
{
int size[2]; size[0] = usize; size[1] = vsize;
glLoadIdentity();
vtkgluPickMatrix(ren->GetPickX(), ren->GetPickY(), 1, 1, lowerLeft, size);
vtkgluPickMatrix(ren->GetPickX(), ren->GetPickY(),
ren->GetPickWidth(), ren->GetPickHeight(),
lowerLeft, size);
glMultMatrixd(matrix->Element[0]);
}
else
......
......@@ -90,7 +90,7 @@ vtkOpenGLFreeTypeTextMapper_GetGL2PSFontName(vtkTextProperty *tprop,
//----------------------------------------------------------------------------
#ifndef VTK_IMPLEMENT_MESA_CXX
vtkCxxRevisionMacro(vtkOpenGLFreeTypeTextMapper, "1.45");
vtkCxxRevisionMacro(vtkOpenGLFreeTypeTextMapper, "1.46");
vtkStandardNewMacro(vtkOpenGLFreeTypeTextMapper);
#endif
......@@ -304,7 +304,9 @@ void vtkOpenGLFreeTypeTextMapper::RenderOverlay(vtkViewport* viewport,
if(viewport->GetIsPicking())
{
vtkgluPickMatrix(viewport->GetPickX(), viewport->GetPickY(),
1, 1, viewport->GetOrigin(), viewport->GetSize());
viewport->GetPickWidth(),
viewport->GetPickHeight(),
viewport->GetOrigin(), viewport->GetSize());
}
glMatrixMode(GL_MODELVIEW);
......
......@@ -28,7 +28,7 @@
#include <limits.h>
#ifndef VTK_IMPLEMENT_MESA_CXX
vtkCxxRevisionMacro(vtkOpenGLImageMapper, "1.64");
vtkCxxRevisionMacro(vtkOpenGLImageMapper, "1.65");
vtkStandardNewMacro(vtkOpenGLImageMapper);
#endif
......@@ -617,7 +617,9 @@ void vtkOpenGLImageMapper::RenderData(vtkViewport* viewport,
if(viewport->GetIsPicking())
{
vtkgluPickMatrix(viewport->GetPickX(), viewport->GetPickY(),
1, 1, viewport->GetOrigin(), vsize);
viewport->GetPickWidth(),
viewport->GetPickHeight(),
viewport->GetOrigin(), vsize);
}
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
......
......@@ -38,7 +38,7 @@
#include <math.h>
#ifndef VTK_IMPLEMENT_MESA_CXX
vtkCxxRevisionMacro(vtkOpenGLPolyDataMapper2D, "1.56");
vtkCxxRevisionMacro(vtkOpenGLPolyDataMapper2D, "1.57");
vtkStandardNewMacro(vtkOpenGLPolyDataMapper2D);
#endif
......@@ -186,7 +186,9 @@ void vtkOpenGLPolyDataMapper2D::RenderOverlay(vtkViewport* viewport,
if(viewport->GetIsPicking())
{
vtkgluPickMatrix(viewport->GetPickX(), viewport->GetPickY(),
1, 1, viewport->GetOrigin(), viewport->GetSize());
viewport->GetPickWidth(),
viewport->GetPickHeight(),
viewport->GetOrigin(), viewport->GetSize());
}
glMatrixMode( GL_MODELVIEW );
......
......@@ -33,10 +33,11 @@ class vtkGLPickInfo
public:
GLuint* PickBuffer;
GLuint PickedId;
GLuint NumPicked;
};
#ifndef VTK_IMPLEMENT_MESA_CXX
vtkCxxRevisionMacro(vtkOpenGLRenderer, "1.50");
vtkCxxRevisionMacro(vtkOpenGLRenderer, "1.51");
vtkStandardNewMacro(vtkOpenGLRenderer);
#endif
......@@ -48,6 +49,7 @@ vtkOpenGLRenderer::vtkOpenGLRenderer()
this->NumberOfLightsBound = 0;
this->PickInfo->PickBuffer = 0;
this->PickInfo->PickedId = 0;
this->PickInfo->NumPicked = 0;
this->PickedZ = 0;
}
......@@ -183,6 +185,7 @@ void vtkOpenGLRenderer::PrintSelf(ostream& os, vtkIndent indent)
this->NumberOfLightsBound << "\n";
os << indent << "PickBuffer " << this->PickInfo->PickBuffer << "\n";
os << indent << "PickedId" << this->PickInfo->PickedId<< "\n";
os << indent << "NumPicked" << this->PickInfo->NumPicked<< "\n";
os << indent << "PickedZ " << this->PickedZ << "\n";
}
......@@ -218,6 +221,11 @@ void vtkOpenGLRenderer::StartPick(unsigned int pickFromSize)
// a MakeCurrent was called.
this->RenderWindow->MakeCurrent();
this->RenderWindow->IsPickingOn();
if (this->PickInfo->PickBuffer)
{
delete [] this->PickInfo->PickBuffer;
this->PickInfo->PickBuffer = 0;
}
this->PickInfo->PickBuffer = new GLuint[bufferSize];
glSelectBuffer(bufferSize, this->PickInfo->PickBuffer);
// change to selection mode
......@@ -265,6 +273,8 @@ void vtkOpenGLRenderer::DonePick()
{
glFlush();
GLuint hits = glRenderMode(GL_RENDER);
this->PickInfo->NumPicked = hits;
unsigned int depth = (unsigned int)-1;
GLuint* ptr = this->PickInfo->PickBuffer;
this->PickInfo->PickedId = 0;
......@@ -307,8 +317,12 @@ void vtkOpenGLRenderer::DonePick()
this->PickedZ = (this->PickedZ < 0.0) ? 0.0 : this->PickedZ;
this->PickedZ = (this->PickedZ > 1.0) ? 1.0: this->PickedZ;
}
delete [] this->PickInfo->PickBuffer;
this->PickInfo->PickBuffer = 0;
//Don't delete the list, keep it around in case caller wants all
//of the hits. Delete it elsewhere when needed.
//delete [] this->PickInfo->PickBuffer;
//this->PickInfo->PickBuffer = 0;
this->RenderWindow->IsPickingOff();
}
......@@ -332,3 +346,33 @@ vtkOpenGLRenderer::~vtkOpenGLRenderer()
delete this->PickInfo;
}
unsigned int vtkOpenGLRenderer::GetNumPickedIds()
{
return (unsigned int)this->PickInfo->NumPicked;
}
int vtkOpenGLRenderer::GetPickedIds(unsigned int atMost, unsigned int *callerBuffer)
{
if (!this->PickInfo->PickBuffer)
{
return 0;
}
unsigned int max = (atMost < this->PickInfo->NumPicked) ? atMost : this->PickInfo->NumPicked;
unsigned int depth = (unsigned int)-1;
GLuint* iptr = this->PickInfo->PickBuffer;
unsigned int *optr = callerBuffer;
unsigned int k;
for(k =0; k < max; k++)
{
int num_names = *iptr;
iptr++; // move to first depth value
iptr++; // move to next depth value
iptr++; // move to first name picked
*optr = (unsigned int)*iptr;
optr++;
// skip additonal names
iptr += num_names;
}
return k;
}
......@@ -58,6 +58,8 @@ protected:
virtual void UpdatePickId();
virtual void DonePick();
virtual unsigned int GetPickedId();
virtual unsigned int GetNumPickedIds();
virtual int GetPickedIds(unsigned int atMost, unsigned int *callerBuffer);
virtual double GetPickedZ();
// Ivars used in picking
class vtkGLPickInfo* PickInfo;
......
......@@ -28,12 +28,14 @@
#include "vtkMatrix4x4.h"
#include "vtkOutputWindow.h"
#include "vtkPicker.h"
#include "vtkAreaPicker.h"
#include "vtkProp3DCollection.h"
#include "vtkRenderWindow.h"
#include "vtkTimerLog.h"
#include "vtkVolume.h"
#include "vtkPropCollection.h"
vtkCxxRevisionMacro(vtkRenderer, "1.221");
vtkCxxRevisionMacro(vtkRenderer, "1.222");
//----------------------------------------------------------------------------
// Needed when we don't use the vtkStandardNewMacro.
......@@ -1261,12 +1263,15 @@ unsigned long int vtkRenderer::GetMTime()
}
vtkAssemblyPath* vtkRenderer::PickProp(double selectionX, double selectionY)
vtkAssemblyPath* vtkRenderer::PickProp(double selectionX1, double selectionY1,
double selectionX2, double selectionY2)
{
// initialize picking information
this->CurrentPickId = 1; // start at 1, so 0 can be a no pick
this->PickX = selectionX;
this->PickY = selectionY;
this->PickX1 = (selectionX1 < selectionX2) ? selectionX1 : selectionX2;
this->PickY1 = (selectionY1 < selectionY2) ? selectionY1 : selectionY2;
this->PickX2 = (selectionX1 > selectionX2) ? selectionX1 : selectionX2;
this->PickY2 = (selectionY1 > selectionY2) ? selectionY1 : selectionY2;
int numberPickFrom;
vtkPropCollection *props;
......@@ -1290,6 +1295,7 @@ vtkAssemblyPath* vtkRenderer::PickProp(double selectionX, double selectionY)
// Actually perform the pick
this->PickRender(props); // do the pick render
this->IsPicking = 0; // turn off picking
this->DonePick();
vtkDebugMacro(<< "z value for pick " << this->GetPickedZ() << "\n");
......@@ -1314,7 +1320,27 @@ vtkAssemblyPath* vtkRenderer::PickProp(double selectionX, double selectionY)
this->PickedProp->Register(this);
}
//convert the list of picked props from integers to prop pointers
if (this->PickResultProps != NULL)
{
this->PickResultProps->Delete();
this->PickResultProps = NULL;
}
this->PickResultProps = vtkPropCollection::New();
unsigned int numPicked = this->GetNumPickedIds();
unsigned int *idBuff = new unsigned int[numPicked];
this->GetPickedIds(numPicked, idBuff);
unsigned int nextId;
for (unsigned int pIdx = 0; pIdx < numPicked; pIdx++)
{
nextId = idBuff[pIdx] - 1; // pick ids start at 1, so move back one
nextId = nextId % this->PathArrayCount;
vtkProp *propCandidate = this->PathArray[nextId]->GetLastNode()->GetViewProp();
this->PickResultProps->AddItem(propCandidate);
}
// Clean up stuff from picking after we use it
delete [] idBuff;
delete [] this->PathArray;
this->PathArray = NULL;
......@@ -1366,20 +1392,49 @@ void vtkRenderer::PickRender(vtkPropCollection *props)
// reduce the number of polygons that the hardware has to pick from, and
// speeds things up substantially.
//
// Create a picker to do the culling process
vtkPicker* cullPicker = vtkPicker::New();
// Add each of the Actors from the pickFrom list into the picker
for ( pickFrom->InitTraversal(pit); (aProp = pickFrom->GetNextProp(pit)); )
vtkPicker* pCullPicker = NULL;
vtkAreaPicker *aCullPicker = NULL;
vtkProp3DCollection* cullPicked;
if (this->GetPickWidth()==1 && this->GetPickHeight()==1)
{
cullPicker->AddPickList(aProp);
// Create a picker to do the culling process
pCullPicker = vtkPicker::New();
// Add each of the Actors from the pickFrom list into the picker
for ( pickFrom->InitTraversal(pit); (aProp = pickFrom->GetNextProp(pit)); )
{
pCullPicker->AddPickList(aProp);
}
// make sure this selects from the pickers list and not the renderers list
pCullPicker->PickFromListOn();
// do the pick
pCullPicker->Pick(this->GetPickX(), this->GetPickY(), 0, this);
cullPicked = pCullPicker->GetProp3Ds();
}
else
{
aCullPicker = vtkAreaPicker::New();
// Add each of the Actors from the pickFrom list into the picker
for ( pickFrom->InitTraversal(pit); (aProp = pickFrom->GetNextProp(pit)); )
{
aCullPicker->AddPickList(aProp);
}
// make sure this selects from the pickers list and not the renderers list
cullPicker->PickFromListOn();
// make sure this selects from the pickers list and not the renderers list
aCullPicker->PickFromListOn();
// do the pick
cullPicker->Pick(this->PickX, this->PickY, 0, this);
vtkProp3DCollection* cullPicked = cullPicker->GetProp3Ds();
// do the pick
aCullPicker->AreaPick(this->PickX1, this->PickY1,
this->PickX2, this->PickY2,
this);
cullPicked = aCullPicker->GetProp3Ds();
}
// Put all the ones that were picked by the cull process
// into the PathArray to be picked from
......@@ -1398,7 +1453,14 @@ void vtkRenderer::PickRender(vtkPropCollection *props)
// Clean picking support objects up
pickFrom->Delete();
cullPicker->Delete();
if (pCullPicker)
{
pCullPicker->Delete();
}
if (aCullPicker)
{
aCullPicker->Delete();
}
if ( this->PathArrayCount == 0 )
{
......
......@@ -347,7 +347,12 @@ public:
// prop that renders the pixel at selectionX, selectionY will be returned.
// If nothing was picked then NULL is returned. This method selects from
// the renderers Prop list.
vtkAssemblyPath* PickProp(double selectionX, double selectionY);
vtkAssemblyPath* PickProp(double selectionX, double selectionY)
{
return this->PickProp(selectionX, selectionY, selectionX, selectionY);
}
vtkAssemblyPath* PickProp(double selectionX1, double selectionY1,
double selectionX2, double selectionY2);
// Description:
// Do anything necessary between rendering the left and right viewpoints
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment