vtkGLTFImporter; rotating from y-up to z-up

glTF documents its internal coordinate space is y-up. This will be true for any portable glTF file. If I’m working in a domain that is z-up, I need to rotate the model from y-up to z-up.

So, here’s the circumstances:

I have a vtkRenderer (and concomitant infrastructure). I want to import a glTF file into a renderer with some arbitrary number of vtkActor already present. I need to rotate the model so it’s oriented to a z-up frame.

Here’s a reduction of my function:

void AddGltf(const std::string& file_name, vtkRenderer* renderer) {
  vtkNew<vtkGLTFImporter> importer;
  importer->SetFileName(file_name.c_str());
  importer->Update();

  auto* temp_renderer = importer->GetRenderer();

  fmt::print("Found {} actors\n", temp_renderer->VisibleActorCount());

  // All of the independent meshes/nodes in the file are put into a single
  // assembly. We rotate the assembly to account for the .gltf y-up standard.
  // This will ultimately become the child of another assembly that takes
  // the geometry's pose.
  vtkNew<vtkAssembly> file_assembly;
  file_assembly->RotateX(90);
  auto* actors = temp_renderer->GetActors();
  actors->InitTraversal();
  while (vtkActor* actor = actors->GetNextActor()) {
    file_assembly->AddPart(actor);
  }

  // We add one more assembly node that we use pose during simulation.
  vtkNew<vtkAssembly> root_assembly;
  root_assembly->AddPart(file_assembly.Get());
  renderer->AddActor(root_assembly);
}

I’ve attached a glTF file with the following hierarchy:
rwb_pyramid.gltf.zip (1.5 KB)

  empty
    |_ red_mesh
       |_ blue_mesh
           |_ white_mesh

Each node has a non-Identity pose w.r.t. to its parent frame.

The function prints out: Found 3 actors (mapping to the three meshes in the glTF file).

It renders the pyramid exactly as one would expect (see image below).

Here are my questions/concerns:

  1. I was expecting to be able to extract a single object (the root of the hierarchy) and place it into the given renderer, dragging along all of its children. I was stymied in how to identify that object.
  2. I stopped looking for the putative root object, as it seems it probably doesn’t exist. The code simply takes all the actors in the temporary renderer and stashes them on a single level into an assembly, assigning it to the target renderer. The object renders correctly, meaning that their transforms no longer depend on the hierarchy – they’ve been baked into each node.
  3. It seems if I did an import-export, the resulting glTF file would be appreciably different.
  4. Is there a better, more canonical way to achieve this end?

image

@mwestphal

Here’s the promised issue.

FYI @Tiffany_Chhim

FYI I believe I have a couple more bugs in the pipe. As soon as I can provide a reproduction example, I’ll open issues.

1 Like

FTR, I’ve read through the code, and it is now clear to me that the importing code explicitly flattens the hierarchy and only introduces nodes with visual elements. That, at least, has better informed my expectations.

1 Like