Page MenuHomePhabricator

MITK doesn't visualize normalized and thus very small meshes in the expected way.
Closed, ResolvedPublic

Assigned To
Authored By
norajitr
Mar 1 2012, 7:20 PM
Referenced Files
F854412: mesh_two_faces.obj
Aug 22 2017, 7:01 PM
F802: testdata.zip
Sep 13 2012, 5:48 PM
F801: XYZCube.stl
Sep 12 2012, 11:16 AM
F800: GeometryBugs.pdf
Sep 11 2012, 7:37 PM
F799: camera_target_point_too_high.JPG
Sep 11 2012, 6:19 PM
F798: cube_0.25_vs_crosshair_2.0.JPG
Sep 11 2012, 6:18 PM
F797: left-mode1-var0_scaled100.stl
Apr 10 2012, 4:12 PM
F796: left-mode1-var0.stl
Apr 10 2012, 4:10 PM

Description

Might be related to T5535.

Revisions and Commits

Event Timeline

Please provide relevant data for this issue and describe what happens on your machine! :)

If we have more information we can accept this as party bug.

Yeah, right :) If I start the Sandbox Application on a windows machine and open an stl file containing a very small mesh, then the vtkOutputWindow pops up and says:

ERROR: In ..\..\CMakeExternals\Source\VTK\Graphics\vtkTransformPolyDataFilter.cxx, line 72
vtkTransformPolyDataFilter (000000000448B1C0): No transform defined!

ERROR: In ..\..\CMakeExternals\Source\VTK\Graphics\vtkTransformPolyDataFilter.cxx, line 72
vtkTransformPolyDataFilter (00000000044EF400): No transform defined!

ERROR: In ..\..\CMakeExternals\Source\VTK\Graphics\vtkTransformPolyDataFilter.cxx, line 72
vtkTransformPolyDataFilter (0000000004553420): No transform defined!

After that, you can see the mesh after some scrolling in the 3D view window, but the view cannot be properly centered on the mesh. There is also no crosshair visible, thus no cutting plane contour is shown in the according 2D windows. It seems like the vtk Transformation is unavailable for the tiny mesh and the viewer depends on that now lacking Transformation.

Can you please add an attachment containing such a .stl file?

I think we have a condition in MITK that geometries must have a certain minimum size (something like 1mm in each direction). So if you define a coordinate system in submillimeter space, this cannot be rendered.

The described effects of T11113 occur on this tiny mesh.

The effects of T11113 do not occur on the same but up-scaled tiny mesh.

Valid bug and could probably be fixed with the patch from Xplanes in T5535.

I have the same annoying bug. The problem occurs if an extent of a 3D geometry is <= 0.5 but not the smallest positive number, which seems to be a substitute for extents of 0.

My geometry is not small at all (several meters) but its spacing is set to (1000, 1000, 1000) since its coordinates are measured in m instead of mm. So the critical value is the return value of Geometry3D::GetExtent() and not GetExtentInMM().

Just a reminder: Check if there is code where GetExtent() needs to be replaced by GetExtentInMM().

The VTK warnings are issued by mitk::Geometry2DDataToSurfaceFilter::GenerateOutputInformation() in case the crosshair is visible (this class is used to create the crosshair planes). After the execution of an vtkStripper its output is checked for the number of points and if it is smaller than three (zero in our case) the method simply returns without any error handling:

if ( m_PlaneStripper->GetOutput()->GetNumberOfPoints() < 3 )
{
  return;
}

The usual output of this filter is a z-axis aligned plane (4 points):

   Z
   |.....
   |    .
   |    .
   |____.__X
  /
 /
Y

I guess the input of the filter is faulty. There is some geometry generation and transformation stuff going on which has to be examined closer.

Lord jesus, seems like I stired up a hornet's nest. We have a combination of a few bugs here including infamous 0.5-offset-bugs. But first things first. What Tobi originally reported can be explained as follows...

If I start the Sandbox Application on a windows machine
and open an stl file containing a very small mesh, then
the vtkOutputWindow pops up:

The following text assumes that there is only one object in the scene in which case it makes up the complete global geometry from which the crosshair is created.

If an object has an extent smaller than 0.5 (regardless of its same extent in mm), crosshair creation fails. Crosshair creation for extents bigger than that but still smaller than 1 doesn't fail but is erroneous. This is due to translations of plane geometries which include a subtraction of 0.5 from somewhere.

Imagine an object with extents (1, 1, 0.75). The first two generated planes meet at their center but the third one is 0.25 below the center, yet still intersect the bounding box which is implicitly defined by the first two planes.

This is not the case anymore if the third extent is smaller than 0.5. The generated plane doesn't intersect the bouding box anymore which leads to the VTK warnings.

There is a trick to visualize such a malformed crosshair anyway: Load an object with extents bigger than 1. Load another object with an extent smaller than 0.5. Since the crosshair captures both objects there is no problem. Now delete the bigger object and what you see is the erroneous crosshair.

I attached a screenshot (cube_0.25_vs_geometry_2.0.JPG) of such a scene where I loaded a two cubes (one with extents 2 and one with extents 0.25. Even worse: in case an object has a spacing different than 1, the loose surface is scaled by the objects spacing.

After that, you can see the mesh after some scrolling
in the 3D view window, but the view cannot be properly
centered on the mesh. There is also no crosshair visible,
thus no cutting plane contour is shown in the according
2D windows.

The camera target point seems to be set hardcoded 0.5 above the origin (camera_target_point_too_high.JPG). In case one loads only a very small mesh, 0.5 can be a pretty huge distance by which the camera miss the actual object.

Erroneous crosshair of an object smaller than 0.5.

cube_0.25_vs_crosshair_2.0.JPG (708×402 px, 19 KB)

Camera target point too high (0.5).

camera_target_point_too_high.JPG (438×740 px, 18 KB)

More bugs which might be related.

In mitk::CameraController::SetStandardView() the bounding box of the visible scene is computed. This is done by the following call:

bb = ds->ComputeBoundingBox();

This is wrong since the widget[1,2,3]Planes are taken into account which have strange extents. Hence, the following call is preferable:

bb = ds->ComputeBoundingBox("visible", NULL, "includeInBoundingBox")

Now, only visible objects which don't have their includeInBoundingBox property set are taken into account and the center point for a symmetric object at the origin is correctly calculated, i.e. (0, 0, 0).

I mean objects which HAVE their includeInBoundingBox property set, sorry.

ASCII art for understanding another bug in SetStandardView():

           cranial
              |posterior    
              | /
              |/
sinister -----+----- dexter
             /|
            / |
      anterior|
            caudal
Saggital-> /|
  +-------+------+__
  |      /|      | / <- Axial
  |_____/ |______|/
  /     | /      /
 /______|/______/|
  +-----| /------+ <- Coronal
        |/

Okay, the bug is not in SetStandardView() since the focal point of the camera is (0, 0, 0) and the position is along one of the main axes. Loading a cube with an extent of (1, 1, 1), centered at the origin, the fix point for camera rotation lies on one of its sides instead of being the origin. I guess we can finally deduce that there must be a wrong 0.5-offset somewhere in the renderer (as the geometry is correct).

Awesome test cube with extents (1, 1, 1) plus attached axis indicators.

Cubes in 0.25, 0.5, 1, and 2. Sphere in 2. Images in 4x2 and 5x5.

What is the status here? Seems like a lot of work has been done already.

Again: What is the status here? Seems like a lot of work has been done already.

TL;DR: Camera target point of 3d view is (0, 0.5, 0) or similar instead of origin.

kislinsk lowered the priority of this task from High to Low.Oct 28 2016, 3:26 PM
kislinsk edited projects, added MITK; removed MITK (2016-11).

The problem is that the renderer geometries are shifted by half a voxel along the renderer plane normal compared to the 'reference' geometry.

It is done here:
https://github.com/MITK/MITK/blob/master/Modules/Core/src/DataManagement/mitkPlaneGeometry.cpp#L441

If you remove adding and subtracting the 'halves', you will probable see the small surfaces correctly.

However, the renderer planes are used to display the crosshair, so with this correction the crosshair planes will be at voxel boundaries rather than voxel centres.

Saying this, the sliced geometry and plane geometry origins should not be shifted away, the crosshair position should be corrected in some different way.

This depends on: T22114 and T20180
I provided fixes for both.

The line causing this bug is here in the PR:

https://github.com/NifTK/MITK/blob/T22114-reinit-fix/Modules/Core/src/DataManagement/mitkPlaneGeometry.cpp#L515

I also ran into this bug when loading attached small mesh:

In current code, loading this mesh will violate an assertion in SlicedGeometry3D's copy constructor because the original SlicedGeometry3D::InitializePlanes(geometry, orientation, top, front, rotated) would decide to initialize a SlicedGeometry3D marked as "evenly spaced" but containing zero plane geometries. Such an initialization violates expectations in a number of places, so I consider it reasonable to modify the calculation of the number of slices: whenever there is at least a minimum extent in a given direction, then there shall also be at least one slice in this direction.

After applying this patch, the attached mesh can be loaded and will correctly be displayed in 3D. In 2D there will still be a single slice in all dimensions, but at least we can have a look and will not crash the application. Comments welcome! Code is available at

https://github.com/maleike/MITK/commits/T11113-create-proper-geometry-for-small-meshes

I can confirm that Daniels fix will work on the current master and will show something in 3D. Also it will no longer crash when doing a reinit on the surface.

However the displayed surface remains solid black for me despite changes in the rendering properties and doing a reinit will result in the object no longer being visible.

In T11113#108062, @goch wrote:

However the displayed surface remains solid black for me despite changes in the rendering properties

Hmm, this is not the case on my version (did _not_ check master). When loading mesh_two_faces.obj as a mitk::Surface it is rendered correctly with its default color.
However, I also got black objects initially when I load the file into a custom surface-like data structure. In this case it seems that lighting does not appreciate the tiny extent and calculate too much black. In this case it helped to change "surface interpolation" to "flat". Did you try if this helps?

@maleike
I did not and it does. Gouraud and Phong result in a black object for me, Flat has the proper color.

kislinsk added a revision: Restricted Differential Revision.Mar 6 2018, 12:13 PM