[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