Gouraud or Flat


(Cornelis Bockemühl) #1

Inside a self-written filter (C++) I am applying a “TubeFilter” to some line segments - works fine.

In order to make things perfect, I would like to have some of the tubes appear “round” and others appear “polygonal”. Normally this is achieved by switching shading between “Gouraud” or “Flat”.

Now this is a display property, not normally a job for the geometric part of the code, but still my first attempt was to simply remove the “Normals” attribute from the tube polydata - with the hope that the Gouraud shading would “fail” and leave them polygonal.

No chance - that Gouraud code seems to be too smart! :wink:

Or is there still a way how I can turn the effect locally off? At least I see that the “caps” of the tubes are showing quite “angular” transitions to the “round faces”, so somehow it must be possible!? Or is it just a question of an acute angle that is “seen” and then avoided? Not possible: even triangular “tubes” are still rounded, and their angles are even more acute than with the caps!

Another option would go the other way round, but so far I did not succeed either: If there would be some “Hint” to be put into the servermanager XML, like “shading=flat”, in order to simply turn off the Gouraud shading I would also have half the way already. I would then simply increase the number of faces a bit for the “round” tubes" (8 or 10 instead of normally 6 for “round” tubes): this might also look ok already.


(Michael Migliore) #2

Hi,
Removing normals using PassArrays filter makes the display of the tube flat for me.
How are you removing the normals?


(Cornelis Bockemühl) #3

Right, the PassArrays filter might be the better option still!

But just realize it might be a bit more complicated anyway, because the setup is the following:

loop over n tube types (with one being round, the others should be angular)
{
lines set (n)
apply Tube filter
if this is not the round case: remove the “Normals” attribute
(so far I did it with “RemoveArray” from the “CellData” of the polydata object)
append the resulting thing to the output polydata with the vtkAppendPolyData filter
}

The complication comes from the vtkAppendPolyData filter: the documentataion says that it will bring together also attributes that exist in ALL the input polydata sets (hmm, what else should it do??).

Meaning that I would lose the Normals also for my “round” data set - and the fact that it does not work so far only shows that I did not do the removal correctly yet…

But once I am doing better I will have the next problem!


(Cornelis Bockemühl) #4

Playing with the normals finally did the trick!
However, the Tube filter generates “TubeNormals”, and with the vtkPolyDataNormals filter and edge splitting I can generate “Normals” that will not be “smoothed”, like this (inside a loop that finally puts several such polydata items together, some “rounded”, others not):

        vtkSmartPointer<vtkTubeFilter> tube = vtkSmartPointer<vtkTubeFilter>::New();
        tube->SetInputData(generateSampling->GetOutput());
        tube->SetCapping(true);
        tube->SetNumberOfSides(sd);
        tube->SetRadius(std::stod((*it1)[2]));
        tube->SetOutputPointsPrecision(vtkTubeFilter::DOUBLE_PRECISION);
        tube->Update();

        if(rounded)
        {
            // use the TubeNormals attribute, copy into Normals and make "standard normals"
            vtkPointData* pData = tube->GetOutput()->GetPointData();
            vtkFloatArray* tnArr = vtkFloatArray::SafeDownCast(pData->GetArray("TubeNormals"));
            if(nullptr != tnArr)
            {
                vtkSmartPointer<vtkFloatArray> narr = vtkSmartPointer<vtkFloatArray>::New();
                narr->DeepCopy(tnArr);
                narr->SetName("Normals");
                pData->AddArray(narr);
                pData->SetNormals(narr);
            }
            pd->DeepCopy(tube->GetOutput());
        }

        else
        {
            // calculate normals with splitting, to avoid rounding effect
            vtkSmartPointer<vtkPolyDataNormals> pnorm = vtkSmartPointer<vtkPolyDataNormals>::New();
            pnorm->SetInputData(tube->GetOutput());
            pnorm->SetSplitting(true);
            pnorm->SetFeatureAngle(10.);
            pnorm->Update();
            pd->DeepCopy(pnorm->GetOutput());
        }