[vtkusers] realtime terrain map, memory allocation/leak questions
Robert Dean
bob.dean at gmail.com
Sun Sep 2 19:40:35 EDT 2012
Hello,
I have a voxel type terrain/height map updated at 1Hz. At first I tried
using glyphs for the cells, which (un-surprisingly) turned out to be too
slow. I re-wrote it today to use cells of triangle strips. I have been
hitting my head on the wall with memory leaks, and after scouring the c++
examples I am almost to the point of scrapping everything and running back
to direct openGL.
As the number of cells, points, etc are constant, I thought it would be
possible to declare things as vtkSmartPointer<> kept as class members. This
works for the points data (points,normals, colors), but if I try it with
anything else (such as vtkcellarray, vtkPolyDataMapper, or vtkPolyData), i
see huge memory leaks. the leak from polydata was really weird
Would someone please look at the code below and tell me what i'm missing?
If i understand the book and tutorials, i should be able to just create
everything once and then update the data arrays... is there some sort of a
cleanup method I should be calling on each update? (also recommendations on
how to use less memory would be appreciated)
for reference a "MapHandle" is a boost::shared_ptr<Map>, where Map is a
vector of Cells. Map also has convenience methods to convert from iterators
to/from x.y.z points.
class MapActor
{
public:
MapActor();
~MapActor();
void updateMap(MapHandle handle, ColorMap &objectColors,
bool heightColor = false);
vtkActor * actorPointer() { return actor; };
private:
rframe::Timer updateTimer;
vtkSmartPointer<vtkPoints> points;
vtkSmartPointer<vtkFloatArray> normals;
vtkSmartPointer<vtkUnsignedCharArray> colors;
vtkSmartPointer<vtkPolyData> polydata;
vtkSmartPointer<vtkCellArray> celldata;
vtkSmartPointer<vtkPolyDataMapper> mapper;
vtkSmartPointer<vtkActor> actor;
vtkSmartPointer<vtkLookupTable> heightLut;
MapHandle mapHandle;
};
MapActor::MapActor()
{
polydata = vtkSmartPointer<vtkPolyData>::New();
// create empty polydata for now
polydata = vtkSmartPointer<vtkPolyData>::New();
heightLut = vtkSmartPointer<vtkLookupTable>::New();
heightLut->SetHueRange(0.6667,0.0);
// heightLut->SetTableRange(-3,10);
heightLut->SetTableRange(-1,1);
heightLut->Build();
actor = vtkSmartPointer<vtkActor>::New();
}
MapActor::~MapActor()
{
}
void MapActor::updateMap(MapHandle handle, ColorMap & objectColors, bool
heightColor)
{
updateTimer.start();
mapHandle = handle;
// Create points
if (!points)
{
cout << "creating points" << endl;
points = vtkSmartPointer<vtkPoints>::New();
points->SetNumberOfPoints(mapHandle->size()*8);
}
if (!normals)
{
normals = vtkSmartPointer<vtkFloatArray>::New();
normals->SetNumberOfComponents(3);
normals->SetName("normals");
normals->SetNumberOfTuples(mapHandle->size());
}
// if (!celldata)
{
celldata = vtkSmartPointer<vtkCellArray>::New(); // we want to
create a new cell data every time, for garbage collection
// the docs say there is now way to pre-allocate celldata storage...
}
// add points for elevation cells
Point p;
float resolution = mapHandle->resolution();
VirtualMap::MapType::iterator it, endIt;
int cellCount = 0;
int pointCount = 0;
vtkIdType indicies[14];
it = mapHandle->begin();
endIt = mapHandle->end();
double minZ, maxZ;
float normal[3];
double dcolor[3];
unsigned char color[3];
minZ = 999999;
maxZ = -999999;
if (!colors)
{
colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
colors->SetName("colors");
colors->SetNumberOfComponents(3);
colors->SetNumberOfTuples(mapHandle->size()*14);
}
while (it != endIt)
{
mapHandle->getPoint(p,it);
float height = -1*it->height();
if (height <= 0) height = 0.01;
double z = -1*it->ground();
if (heightColor == true)
{
// set color
heightLut->GetColor(height,dcolor);
}
else
{
dcolor[0] = objectColors[it->classType()].red();
dcolor[1] = objectColors[it->classType()].green();
dcolor[2] = objectColors[it->classType()].blue();
}
color[0] = static_cast<unsigned char>(255.0 * dcolor[0]);
color[1] = static_cast<unsigned char>(255.0 * dcolor[1]);
color[2] = static_cast<unsigned char>(255.0 * dcolor[2]);
// bottom front left
indicies[0] = pointCount;
points->SetPoint(pointCount,p.x(),-p.y(),z);
colors->InsertTupleValue(pointCount,color);
normal[0] = -1;
normal[1] = -1;
normal[2] = -1;
normals->InsertTupleValue(pointCount,normal);
pointCount++;
// top front left
indicies[1] = pointCount;
points->SetPoint(pointCount,p.x(),-p.y(),z+height);
colors->InsertTupleValue(pointCount,color);
normal[0] = -1;
normal[1] = -1;
normal[2] = 1;
normals->InsertTupleValue(pointCount,normal);
pointCount++;
// bottom front right
indicies[2] = pointCount;
points->SetPoint(pointCount,p.x()+resolution,-p.y(),z);
colors->InsertTupleValue(pointCount,color);
normal[0] = 1;
normal[1] = -1;
normal[2] = -1;
normals->InsertTupleValue(pointCount,normal);
pointCount++;
// top front right
indicies[3] = pointCount;
points->SetPoint(pointCount,p.x()+resolution,-p.y(),z+height);
colors->InsertTupleValue(pointCount,color);
normal[0] = 1;
normal[1] = -1;
normal[2] = 1;
normals->InsertTupleValue(pointCount,normal);
pointCount++;
// bootom back right
indicies[4] = pointCount;
points->SetPoint(pointCount,p.x()+resolution,-p.y()-resolution,z);
// <- should this be -resolution?
colors->InsertTupleValue(pointCount,color);
normal[0] = 1;
normal[1] = 1;
normal[2] = -1;
normals->InsertTupleValue(pointCount,normal);
pointCount++;
// top back right
indicies[5] = pointCount;
points->SetPoint(pointCount,p.x()+resolution,-p.y()-resolution,z+height);
colors->InsertTupleValue(pointCount,color);
normal[0] = 1;
normal[1] = 1;
normal[2] = 1;
normals->InsertTupleValue(pointCount,normal);
pointCount++;
// bottom back left
indicies[6] = pointCount;
points->SetPoint(pointCount,p.x(),-p.y()-resolution,z);
colors->InsertTupleValue(pointCount,color);
normal[0] = -1;
normal[1] = 1;
normal[2] = -1;
normals->InsertTupleValue(pointCount,normal);
pointCount++;
// top back left
indicies[7] = pointCount;
points->SetPoint(pointCount,p.x(),-p.y()-resolution,z+height);
colors->InsertTupleValue(pointCount,color);
normal[0] = -1;
normal[1] = 1;
normal[2] = 1;
normals->InsertTupleValue(pointCount,normal);
pointCount++;
// close box
indicies[8] = indicies[0];
indicies[9] = indicies[1];
// add top
// degenerate triangle
indicies[10] = indicies[1];
indicies[11] = indicies[7];
indicies[12] = indicies[3];
indicies[13] = indicies[5];
// indicies[12] = ;
// celldata->InsertNextCell(triangleStrip);
celldata->InsertNextCell(14,indicies);
if (height < minZ) minZ = height;
if (height > maxZ) maxZ = height;
++it;
++cellCount;
}
polydata = vtkSmartPointer<vtkPolyData>::New();
polydata->SetPoints(points);
polydata->GetPointData()->SetNormals(normals);
polydata->SetStrips(celldata);
// polydata->Update();
// polydata->GetCellData()->SetScalars(colors); well this doesn't work
right...
polydata->GetPointData()->SetScalars(colors);
polydata->Modified();
// Create a mapper and actor
// if (!mapper)
{
mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
}
//mapper->SetInputConnection(glyph3D->GetOutputPort());
mapper->SetInput(polydata);
actor->SetMapper(mapper);
// actor->GetProperty()->BackfaceCullingOn();
updateTimer.stop();
cout << "map update took: " << updateTimer.elapsedDouble() << ", avg: "
<< updateTimer.averageElapsedDouble() << endl;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20120902/0b0c036e/attachment.htm>
More information about the vtkusers
mailing list