Avoiding precision problems in VTK

It’s a common issue in graphics that large position values start to affect visuals, due to single precision floats. Some games solve this by implementing a sort of segment-offset scheme for world coordinates, where XYZ values are turned into segment(int)+offset(small float). All positions are then computed with respect to segments first, using ints to deal with the large part of the coordinate, and only sending small floats to the graphics pipeline.

Does VTK provide some method to deal with this problem? If not, any suggestion on how to do it without compromising existing functionality?

Below is a simple example to illustrate the issue. A sphere generated very far from the origin will have its coordinates clamped due to extreme rounding errors.


import vtk

center_pos = 50000000.0

sphereSource = vtk.vtkSphereSource()
sphereSource.SetCenter(center_pos, 0.0, 0.0)
sphereSource.SetRadius(5.0)
sphereSource.SetPhiResolution(10)
sphereSource.SetThetaResolution(10)

mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(sphereSource.GetOutputPort())

actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetInterpolationToFlat()

ren = vtk.vtkRenderer()
ren.AddActor(actor)

renwin = vtk.vtkRenderWindow()
renwin.SetSize(1280, 780)
renwin.AddRenderer(ren)

iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renwin)

iren.Initialize()
renwin.Render()
iren.Start()

You would usually work with object coordinates and scene-coordinates. For your example, I would do the following.

transform = vtk.vtkTransform()
transform.Translate(center_pos, 0.0, 0.0)
actor.SetUserTransform(transform)

and your are all set. Of course, then set the center of the sphere to 0.0, 0.0, 0.0.

2 Likes

There is a way for vtkPolyDataMapper to do this automatically for you, though it’s not obvious from the documentation.

Call vtkPolyDataMapper::SetVBOShiftScaleMethod() with one of the enums listed here. vtkPolyDataMapper::AUTO_SHIFT_SCALE is probably the one that works best most of the time.

1 Like