You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
8.4 KiB
C++
254 lines
8.4 KiB
C++
|
1 month ago
|
/*=========================================================================
|
||
|
|
|
||
|
|
Program: Visualization Toolkit
|
||
|
|
Module: vtkHardwareSelectionPolyDataPainter.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.
|
||
|
|
|
||
|
|
=========================================================================*/
|
||
|
|
#include "vtkHardwareSelectionPolyDataPainter.h"
|
||
|
|
|
||
|
|
#include "vtkActor.h"
|
||
|
|
#include "vtkCellArray.h"
|
||
|
|
#include "vtkCellData.h"
|
||
|
|
#include "vtkHardwareSelector.h"
|
||
|
|
#include "vtkIdTypeArray.h"
|
||
|
|
#include "vtkObjectFactory.h"
|
||
|
|
#include "vtkPainterDeviceAdapter.h"
|
||
|
|
#include "vtkPointData.h"
|
||
|
|
#include "vtkPolyData.h"
|
||
|
|
#include "vtkRenderer.h"
|
||
|
|
#include "vtkRenderWindow.h"
|
||
|
|
#include "vtkTimerLog.h"
|
||
|
|
#include "vtkUnsignedIntArray.h"
|
||
|
|
|
||
|
|
vtkStandardNewMacro(vtkHardwareSelectionPolyDataPainter);
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
static inline int vtkHardwareSelectionPolyDataPainterGetTotalCells(vtkPolyData* pd,
|
||
|
|
unsigned long typeflags)
|
||
|
|
{
|
||
|
|
int total_cells = 0;
|
||
|
|
total_cells += (typeflags & vtkPainter::VERTS)?
|
||
|
|
pd->GetNumberOfVerts() : 0;
|
||
|
|
total_cells += (typeflags & vtkPainter::LINES)?
|
||
|
|
pd->GetNumberOfLines() : 0;
|
||
|
|
total_cells += (typeflags & vtkPainter::POLYS)?
|
||
|
|
pd->GetNumberOfPolys() : 0;
|
||
|
|
total_cells += (typeflags & vtkPainter::STRIPS)?
|
||
|
|
pd->GetNumberOfStrips() : 0;
|
||
|
|
return total_cells;
|
||
|
|
}
|
||
|
|
//----------------------------------------------------------------------------
|
||
|
|
vtkHardwareSelectionPolyDataPainter::vtkHardwareSelectionPolyDataPainter()
|
||
|
|
{
|
||
|
|
this->EnableSelection = 1;
|
||
|
|
this->PointIdArrayName = NULL;
|
||
|
|
this->CellIdArrayName = NULL;
|
||
|
|
this->ProcessIdArrayName = NULL;
|
||
|
|
this->CompositeIdArrayName = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------------
|
||
|
|
vtkHardwareSelectionPolyDataPainter::~vtkHardwareSelectionPolyDataPainter()
|
||
|
|
{
|
||
|
|
this->SetPointIdArrayName(NULL);
|
||
|
|
this->SetCellIdArrayName(NULL);
|
||
|
|
this->SetProcessIdArrayName(NULL);
|
||
|
|
this->SetCompositeIdArrayName(NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
void vtkHardwareSelectionPolyDataPainter::RenderInternal(
|
||
|
|
vtkRenderer* renderer,
|
||
|
|
vtkActor* vtkNotUsed(actor),
|
||
|
|
unsigned long typeflags,
|
||
|
|
bool vtkNotUsed(forceCompileOnly))
|
||
|
|
{
|
||
|
|
if (typeflags == 0)
|
||
|
|
{
|
||
|
|
// No primitive to render.
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
vtkPainterDeviceAdapter* device =
|
||
|
|
renderer->GetRenderWindow()->GetPainterDeviceAdapter();
|
||
|
|
if (device == NULL)
|
||
|
|
{
|
||
|
|
vtkErrorMacro("Painter Device Adapter missing!");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
vtkPolyData* pd = this->GetInputAsPolyData();
|
||
|
|
this->TotalCells = vtkHardwareSelectionPolyDataPainterGetTotalCells(pd, typeflags);
|
||
|
|
|
||
|
|
if (this->TotalCells == 0)
|
||
|
|
{
|
||
|
|
// skip empty polydatas.
|
||
|
|
this->TimeToDraw = 0;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
vtkHardwareSelector* selector = renderer->GetSelector();
|
||
|
|
if (this->EnableSelection)
|
||
|
|
{
|
||
|
|
selector->BeginRenderProp();
|
||
|
|
// We emphasis the vertex size to make sure they will be properly detected.
|
||
|
|
if (selector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS &&
|
||
|
|
selector->GetCurrentPass() > vtkHardwareSelector::ACTOR_PASS)
|
||
|
|
{
|
||
|
|
device->MakeVertexEmphasis(true);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
this->Timer->StartTimer();
|
||
|
|
vtkIdType startCell = 0;
|
||
|
|
|
||
|
|
if (typeflags & vtkPainter::VERTS)
|
||
|
|
{
|
||
|
|
this->DrawCells(VTK_POLY_VERTEX, pd->GetVerts(), startCell, renderer);
|
||
|
|
}
|
||
|
|
|
||
|
|
startCell += pd->GetNumberOfVerts();
|
||
|
|
if (typeflags & vtkPainter::LINES)
|
||
|
|
{
|
||
|
|
this->DrawCells(VTK_POLY_LINE, pd->GetLines(), startCell, renderer);
|
||
|
|
}
|
||
|
|
|
||
|
|
startCell += pd->GetNumberOfLines();
|
||
|
|
if (typeflags & vtkPainter::POLYS)
|
||
|
|
{
|
||
|
|
this->DrawCells(VTK_POLYGON, pd->GetPolys(), startCell, renderer);
|
||
|
|
}
|
||
|
|
|
||
|
|
startCell += pd->GetNumberOfPolys();
|
||
|
|
if (typeflags & vtkPainter::STRIPS)
|
||
|
|
{
|
||
|
|
this->DrawCells(VTK_TRIANGLE_STRIP, pd->GetStrips(), startCell, renderer);
|
||
|
|
}
|
||
|
|
if (this->EnableSelection)
|
||
|
|
{
|
||
|
|
selector->EndRenderProp();
|
||
|
|
// We revert back our Vertex emphasis
|
||
|
|
if (selector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS &&
|
||
|
|
selector->GetCurrentPass() > vtkHardwareSelector::ACTOR_PASS)
|
||
|
|
{
|
||
|
|
device->MakeVertexEmphasis(false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
this->Timer->StopTimer();
|
||
|
|
this->TimeToDraw = this->Timer->GetElapsedTime();
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
void vtkHardwareSelectionPolyDataPainter::DrawCells(
|
||
|
|
int mode, vtkCellArray *connectivity, vtkIdType startCellId,
|
||
|
|
vtkRenderer *renderer)
|
||
|
|
{
|
||
|
|
vtkPolyData* pd = this->GetInputAsPolyData();
|
||
|
|
vtkPainterDeviceAdapter* device = renderer->GetRenderWindow()->
|
||
|
|
GetPainterDeviceAdapter();
|
||
|
|
|
||
|
|
vtkHardwareSelector* selector = renderer->GetSelector();
|
||
|
|
int attributeMode = selector->GetFieldAssociation();
|
||
|
|
// While looking at point selection we render only vertex so each pass
|
||
|
|
// should fill the same pixels without risking of detecting vertex belonging
|
||
|
|
// to other cells or block. BUT we do that after the ACTOR_PASS to make sure
|
||
|
|
// we have the proper oclusion as we keep the Z-buffer arround. In that way
|
||
|
|
// vertex that are hidden by some surface won't get selected.
|
||
|
|
if (attributeMode == vtkDataObject::FIELD_ASSOCIATION_POINTS &&
|
||
|
|
selector->GetCurrentPass() > vtkHardwareSelector::ACTOR_PASS &&
|
||
|
|
this->EnableSelection)
|
||
|
|
{
|
||
|
|
mode = VTK_POLY_VERTEX;
|
||
|
|
}
|
||
|
|
|
||
|
|
vtkPoints* p = pd->GetPoints();
|
||
|
|
vtkIdType npts, *pts;
|
||
|
|
vtkIdType cellId = startCellId;
|
||
|
|
vtkUnsignedIntArray* procIdsArray = this->ProcessIdArrayName?
|
||
|
|
vtkArrayDownCast<vtkUnsignedIntArray>(
|
||
|
|
pd->GetPointData()->GetArray(this->ProcessIdArrayName)) : NULL;
|
||
|
|
|
||
|
|
vtkIdTypeArray* pidArray = this->PointIdArrayName? vtkArrayDownCast<vtkIdTypeArray>(
|
||
|
|
pd->GetPointData()->GetArray(this->PointIdArrayName)) : NULL;
|
||
|
|
|
||
|
|
vtkIdTypeArray* cidArray = this->CellIdArrayName? vtkArrayDownCast<vtkIdTypeArray>(
|
||
|
|
pd->GetCellData()->GetArray(this->CellIdArrayName)) : NULL;
|
||
|
|
|
||
|
|
vtkUnsignedIntArray* compositeIdArray = this->CompositeIdArrayName?
|
||
|
|
vtkArrayDownCast<vtkUnsignedIntArray>(
|
||
|
|
pd->GetCellData()->GetArray(this->CompositeIdArrayName)) : NULL;
|
||
|
|
|
||
|
|
int pointtype = p->GetDataType();
|
||
|
|
void* voidpoints = p->GetVoidPointer(0);
|
||
|
|
int count = 0;
|
||
|
|
|
||
|
|
// Note that cell attributes are overridden by point attributes.
|
||
|
|
for (connectivity->InitTraversal(); connectivity->GetNextCell(npts, pts); count++)
|
||
|
|
{
|
||
|
|
device->BeginPrimitive(mode);
|
||
|
|
if (this->EnableSelection && compositeIdArray)
|
||
|
|
{
|
||
|
|
selector->RenderCompositeIndex(compositeIdArray->GetValue(cellId));
|
||
|
|
}
|
||
|
|
if (attributeMode == vtkDataObject::FIELD_ASSOCIATION_CELLS &&
|
||
|
|
this->EnableSelection)
|
||
|
|
{
|
||
|
|
selector->RenderAttributeId(
|
||
|
|
cidArray? cidArray->GetValue(cellId) : cellId);
|
||
|
|
}
|
||
|
|
for (vtkIdType cellpointi = 0; cellpointi < npts; cellpointi++)
|
||
|
|
{
|
||
|
|
vtkIdType pointId = pts[cellpointi];
|
||
|
|
if (attributeMode == vtkDataObject::FIELD_ASSOCIATION_POINTS &&
|
||
|
|
this->EnableSelection)
|
||
|
|
{
|
||
|
|
selector->RenderAttributeId(
|
||
|
|
pidArray? pidArray->GetValue(pointId) : pointId);
|
||
|
|
}
|
||
|
|
if (this->EnableSelection && procIdsArray &&
|
||
|
|
selector->GetUseProcessIdFromData())
|
||
|
|
{
|
||
|
|
selector->RenderProcessId(procIdsArray->GetPointer(0)[pointId]);
|
||
|
|
}
|
||
|
|
device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
|
||
|
|
pointtype, voidpoints, 3*pointId);
|
||
|
|
}
|
||
|
|
device->EndPrimitive();
|
||
|
|
cellId++;
|
||
|
|
if (count == 10000)
|
||
|
|
{
|
||
|
|
count = 0;
|
||
|
|
// report progress
|
||
|
|
this->UpdateProgress(static_cast<double>(cellId - startCellId)/this->TotalCells);
|
||
|
|
// Abort render.
|
||
|
|
if (renderer->GetRenderWindow()->CheckAbortStatus())
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------------
|
||
|
|
void vtkHardwareSelectionPolyDataPainter::PrintSelf(ostream& os, vtkIndent indent)
|
||
|
|
{
|
||
|
|
this->Superclass::PrintSelf(os, indent);
|
||
|
|
os << indent << "EnableSelection: " << this->EnableSelection << endl;
|
||
|
|
os << indent << "CellIdArrayName: " <<
|
||
|
|
(this->CellIdArrayName? this->CellIdArrayName : "(none)") << endl;
|
||
|
|
os << indent << "PointIdArrayName: " <<
|
||
|
|
(this->PointIdArrayName? this->PointIdArrayName: "(none)") << endl;
|
||
|
|
os << indent << "CompositeIdArrayName: "
|
||
|
|
<< (this->CompositeIdArrayName? this->CompositeIdArrayName : "(none)")
|
||
|
|
<< endl;
|
||
|
|
}
|