gazebosim / gz-rendering

C++ library designed to provide an abstraction for different rendering engines. It offers unified APIs for creating 3D graphics applications.
https://gazebosim.org
Apache License 2.0
50 stars 48 forks source link

Axis rendering has odd rings #771

Open Levi-Armstrong opened 1 year ago

Levi-Armstrong commented 1 year ago

I am currently using rendering6 binary on ubuntu 20.04.

    ignition::rendering::AxisVisualPtr axis = scene->CreateAxisVisual(pose_entity.id, pose_entity.unique_name);
    axis->SetLocalPose(ignition::math::eigen3::convert(pose));
    axis->SetInheritScale(false);
    axis->Scale(0.05, 0.05, 0.05);
    axis->SetVisible(true);

image

iche033 commented 1 year ago

it could be the axis->SetVisible(true) call that recursively updated the child arrow rotation visual (ring) visibility to true. If the SetVisible call is needed, one workaround is to loop through the child visuals, cast them to ArrowVisual and call ShowArrowRotation(false) to turn them off

Levi-Armstrong commented 1 year ago

I will remove the setVisible call to see if that fixes things. The other odd thing is that I am doing the same thing other places which do not result in the rings being visible.

Levi-Armstrong commented 1 year ago

@iche033 The issue is that I have all axis visual objects as children of visual objects and if you call setVisual(true) on the parent visual object this occurs. I assume this is a bug since they should not be present for a axis. Any thoughts on how to resolve this short term and long term?

Levi-Armstrong commented 1 year ago

Use the code below to solve the issue in the short term.

  void showAxis(const ignition::rendering::NodePtr& node)
  {
    for (std::size_t i = 0; i < node->ChildCount(); ++i)
    {
      auto child_node = node->ChildByIndex(i);
      auto axis = std::dynamic_pointer_cast<ignition::rendering::AxisVisual>(child_node);
      if (axis != nullptr)
      {
        for (std::size_t j = 0; j < axis->ChildCount(); ++j)
        {
          auto arrow = std::dynamic_pointer_cast<ignition::rendering::ArrowVisual>(axis->ChildByIndex(j));
          if (arrow != nullptr)
            arrow->ShowArrowRotation(false);
        }
      }
      else
      {
        showAxis(child_node);
      }
    }
  }
iche033 commented 1 year ago

yeah that workaround looks good.

One fix would be to update the logic in Ogre2Visual::Setvisible. Instead of calling ogre's setVisible function, we do this recursively by calling our own Visual::SetVisible function. Then in BaseArrowVisual class, we override the SetVisible function and make sure to set the visibility of the arrow head and shaft visuals only and not the arrow rotation visual. Not sure if overriding the SetVisible function will break ABI or not, hence this may be more of a long term solution

Levi-Armstrong commented 1 year ago

It looks like everything is already done in BaseArrowVisual and BaseAxisVisual so no changes needed here. So to solve the issue only Ogre2Visual::SetVisible would need to be updated to call Visual::SetVisible.

Levi-Armstrong commented 1 year ago

Since the issue is only with Ogre2Visual::SetVisible my function can be simplified to the following.

  void showAxis(const ignition::rendering::NodePtr& node)
  {
    for (std::size_t i = 0; i < node->ChildCount(); ++i)
    {
      auto child_node = node->ChildByIndex(i);
      auto axis = std::dynamic_pointer_cast<ignition::rendering::AxisVisual>(child_node);
      if (axis != nullptr)
        axis->SetVisible(true);
      else
        showAxis(child_node);
    }
  }

... Calling code

  auto visual_node = scene.VisualById(entity.id)
  if (visual_node != nullptr)
  {
    visual_node->SetVisible(visible);
    if (visible == true)
      showAxis(visual_node);
  }