Skip to content

Ogre2FrustumVisual: draw wireframe at the actual frustum extents (backport #1276)#1279

Closed
mergify[bot] wants to merge 1 commit intogz-rendering8from
mergify/bp/gz-rendering8/pr-1276
Closed

Ogre2FrustumVisual: draw wireframe at the actual frustum extents (backport #1276)#1279
mergify[bot] wants to merge 1 commit intogz-rendering8from
mergify/bp/gz-rendering8/pr-1276

Conversation

@mergify
Copy link
Copy Markdown
Contributor

@mergify mergify Bot commented Apr 22, 2026

🦟 Bug fix

Fixes N/A — bug was not previously filed as an issue.

Summary

Ogre2FrustumVisual::Update() renders the camera / logical_camera frustum wireframe at roughly double the configured field of view. The LogicalCameraSensor detections and the planes[] produced by the same Update() are already correct — only the drawn wireframe is wrong.

For a logical_camera with horizontal_fov = 1.047 rad (60°) and aspect_ratio = 1.333, the current code draws a cone that measures ~98° across. This makes the VisualizeFrustum GUI plugin misleading: an object that looks "inside" the wireframe may in fact be outside the sensor's true FOV.

Root cause

In ogre2/src/Ogre2FrustumVisual.cc::Update() the four locals are defined as full plane dimensions:

double nearWidth = 2.0 * tanFOV2 * this->nearClip;
double nearHeight = nearWidth / this->aspectRatio;
double farWidth  = 2.0 * tanFOV2 * this->farClip;
double farHeight = farWidth  / this->aspectRatio;

They are halved when building the per-corner offset vectors that feed points[], edges[], and planes[] (so those are correct):

gz::math::Vector3d upNearHeight2  = up    * (nearHeight * 0.5);
gz::math::Vector3d rightNearWidth2= right * (nearWidth  * 0.5);
...

But the AddPoint() calls that populate the Ogre2DynamicRenderable — i.e. the visible wireframe — use the un-halved values directly as the corner coordinate:

renderable->AddPoint(math::Vector3d(this->nearClip, nearWidth, nearHeight));
...
renderable->AddPoint(math::Vector3d(this->farClip,  farWidth,  farHeight));

Every rendered corner therefore sits at twice its true distance from the optical axis, and the drawn cone is roughly 2× wider / taller than the configured FOV.

Fix

Redefine the four locals as half-extents (drop the 2.0 * factor) and drop the matching * 0.5 from the offset vectors. No other logic changes — points[], edges[], and planes[] come out exactly the same, and there is no public API/ABI change.

Diff: +11 / -11, single file (ogre2/src/Ogre2FrustumVisual.cc).

Reproduction & verification

Built the rotary gazebodistro collection (every gz-* repo at main) inside a container and ran a minimal world: a logical_camera + an RGB camera at the same pose (0, 1.5, 1.2) facing +X with horizontal_fov = 1.047 rad, plus four 1×1×1 boxes — two of them placed at ~44° and ~49° off the optical axis, well outside the 30° half-FOV.

In gz sim, opened the Visualize Frustum plugin, subscribed to /station_dual/camera_info (the RGB CameraInfo path added in gazebosim/gz-sim#3374), and switched the scene to top-orthographic.

Before (main, unpatched) — wireframe encloses every box, including the two off-axis ones

before_main_camera_info

After (main + this patch) — wireframe matches the configured 60°

after_main_camera_info

The two off-axis boxes are now clearly outside the cone, matching what the actual sensor geometry says. The rendered RGB image on the right side of the window is unchanged, confirming that only the wireframe visualization differs.

Cross-check against the logical_camera topic on the same scene:

$ gz topic -e -t /station_dual/logical -n 1 | grep "name:"
  name: "blue_box"
  name: "green_box"
# red_box and blue_box_1 are not listed — they are the two off-axis boxes.

In the unpatched wireframe (Before), red_box and blue_box_1 appear visually inside the cone even though the sensor correctly excludes them; after this patch, they sit outside the cone — the visualization now agrees with what the sensor has been reporting all along.

The same fix was independently verified on gz-rendering10 (Jetty). The Ogre2FrustumVisual.cc content is identical between main and gz-rendering10 aside from one unrelated GZ_PROFILE macro line.

Checklist

  • Signed all commits for DCO
  • Added a screen capture or video to the PR description that demonstrates the fix (as needed)
  • Updated documentation (as needed)
  • Updated migration guide (as needed)
  • Consider updating Python bindings (if the library has them)
  • codecheck passed (See contributing)
  • All tests passed (See test coverage)
  • Updated Bazel files (if adding new files). Created an issue otherwise.
  • While waiting for a review on your PR, please help review another open pull request to support the maintainers
  • Was GenAI used to generate this PR? If so, make sure to add "Generated-by" to your commits. (See this policy for more info.)

Generated-by: Claude Opus 4.7 noreply@anthropic.com

This PR was prepared with assistance from a generative AI tool (Claude). All code changes were manually reviewed, built, and visually verified by the contributor on both gz-rendering10 (Jetty) and the main rotary collection.


This is an automatic backport of pull request #1276 done by Mergify.

Ogre2FrustumVisual::Update() computed nearWidth/nearHeight/farWidth/farHeight
as full plane dimensions and then halved them when forming the per-corner
offset vectors (upNearHeight2, rightNearWidth2, ...). Those offset vectors
feed points[] / edges[] / planes[], which were therefore correct.

The Ogre2DynamicRenderable used for the visible wireframe, however, was
populated via AddPoint() calls that consumed the unhalved nearWidth,
nearHeight, farWidth, farHeight directly as corner coordinates. Every
drawn corner sat at twice its true distance from the optical axis, so the
wireframe always showed roughly double the configured horizontal and
vertical field of view (for example a logical_camera with
horizontal_fov=1.047 rad / 60 deg was rendered as a cone of ~98 deg).

Redefine the four locals as half-extents (drop the 2.0 factor) and drop
the matching 0.5 factor from the offset vectors. The AddPoint() calls now
consume the correct half-extents, while points[], edges[], and planes[]
are geometrically unchanged. No public API change.

Generated-by: Claude Opus 4.7 <noreply@anthropic.com>

Signed-off-by: MDEAGEWT <kmk6061602@naver.com>
(cherry picked from commit c001a37)

# Conflicts:
#	ogre2/src/Ogre2FrustumVisual.cc
@mergify mergify Bot requested a review from iche033 as a code owner April 22, 2026 16:58
@mergify mergify Bot added the conflicts label Apr 22, 2026
@mergify
Copy link
Copy Markdown
Contributor Author

mergify Bot commented Apr 22, 2026

Cherry-pick of c001a37 has failed:

On branch mergify/bp/gz-rendering8/pr-1276
Your branch is up to date with 'origin/gz-rendering8'.

You are currently cherry-picking commit c001a37f.
  (fix conflicts and run "git cherry-pick --continue")
  (use "git cherry-pick --skip" to skip this patch)
  (use "git cherry-pick --abort" to cancel the cherry-pick operation)

Unmerged paths:
  (use "git add/rm <file>..." as appropriate to mark resolution)
	deleted by us:   ogre2/src/Ogre2FrustumVisual.cc

no changes added to commit (use "git add" and/or "git commit -a")

To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally

@iche033
Copy link
Copy Markdown
Contributor

iche033 commented Apr 22, 2026

closing as Ogre2FrustumVisual is not available in gz-rendering8

@iche033 iche033 closed this Apr 22, 2026
@github-project-automation github-project-automation Bot moved this from Inbox to Done in Core development Apr 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants