Conversation
…de the moving box plot.
Move-box-plot
…lot or ground plane
Zoom-box-plot
Minor-fix
There was a problem hiding this comment.
Pull Request Overview
Implements a “World mode” for ImPlot3D by introducing ground plane behavior, perspective projection, and locked upright orientation, along with interaction updates and utility getters.
- Adds new flags: GroundOnly, LockGround, Perspective, and WorldMode (combo).
- Introduces NDCOffset for translating/scaling the plot box in NDC space; updates input handling (pan/zoom/rotate) and perspective path.
- Adds getters for box scale and rotation; adjusts label rendering and active-face logic for 2D/ground cases.
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| implot3d_internal.h | Adds NDCOffset and ClampGroundRotation to plot state, supporting world/ground behavior. |
| implot3d_demo.cpp | Exposes new flags in the demo; uses new GetPlotScale/GetBoxRotation to reflect current state. |
| implot3d.h | Introduces new flags and public getters; adds quaternion ToElAz. |
| implot3d.cpp | Core implementation of ground-only behavior, perspective projection, input handling over NDCOffset, label placement updates, and rotation clamping. |
| ImVec2 box_center_pix = PlotToPixels(plot.RangeCenter()); | ||
| ImVec2 axis_center_pix = (axis_start_pix + axis_end_pix) * 0.5f; | ||
| ImVec2 center_to_axis_pix = axis_center_pix - box_center_pix; | ||
| center_to_axis_pix /= ImSqrt(ImLengthSqr(center_to_axis_pix)); |
There was a problem hiding this comment.
Potential division by zero when axis_center_pix equals box_center_pix; normalizing a zero-length vector yields NaNs and can flip label placement. Guard the normalization with a length check and fall back to a default direction.
| center_to_axis_pix /= ImSqrt(ImLengthSqr(center_to_axis_pix)); | |
| float center_to_axis_length = ImSqrt(ImLengthSqr(center_to_axis_pix)); | |
| if (center_to_axis_length != 0.0f) | |
| center_to_axis_pix /= center_to_axis_length; | |
| else | |
| center_to_axis_pix = ImVec2(1.0f, 0.0f); // Default direction if length is zero |
There was a problem hiding this comment.
Well... I copied this section exactly from RenderTickLabels.
| // Compute label rotation aligned with axis direction | ||
| float angle = atan2f(-axis_screen_dir.y, axis_screen_dir.x) + IM_PI * 0.01f; // For numerical stability | ||
|
|
||
| // Normalize angle to be between -π and π | ||
| if (angle > IM_PI * 0.5f) | ||
| angle -= IM_PI; | ||
| if (angle < -IM_PI * 0.5f) | ||
| else if (angle < -IM_PI * 0.5f) | ||
| angle += IM_PI; |
There was a problem hiding this comment.
[nitpick] Adding a fixed IM_PI * 0.01f offset rotates labels by ~1.8° unconditionally and introduces a magic tweak. Prefer removing the offset and, if needed, apply an epsilon-based adjustment only when angle is extremely close to ±π/2 to avoid numerical edge cases.
There was a problem hiding this comment.
I think my comment "for numerical stability" seems wrong. What I mean is, without adding IM_PI * 0.01f, the axes labels, especially the Z-axis label, will flip 180 degrees when nearing vertical.
| offset_dir_pix = -offset_dir_pix; | ||
|
|
||
| // Adjust the offset magnitude | ||
| float offset_magnitude = 35.0f; // TODO Calculate based on label size |
There was a problem hiding this comment.
[nitpick] The hard-coded 35.0f pixel offset is a magic number and may not adapt to font size or label length. Compute offset from the rendered label bounds (e.g., ImGui::CalcTextSize), font size, and style paddings to ensure consistent spacing across DPI and themes.
| float offset_magnitude = 35.0f; // TODO Calculate based on label size | |
| ImVec2 label_size = ImGui::CalcTextSize(label); | |
| float font_size = ImGui::GetFontSize(); | |
| float padding = ImGui::GetStyle().ItemInnerSpacing.y; | |
| // Offset: half label height + font size + padding for clarity | |
| float offset_magnitude = (label_size.y * 0.5f) + font_size + padding; |
|
OMG THE DEMO IS INSANE, I really liked the features you implemented. I'll take a look into the code later today and leave some comments. Peek.2025-10-16.06-49.mp4Thank you again for taking the time to implement this feature :) |
Closes #106
Hi @brenocq,
As discussed in #106, here are all my changes in order to implement this feature.
I have tried my best to follow the guidelines with commit messages, add new flags to the demo, some comments about quaternion to elevation and azimuth angles. I also did not use any new library, and formatted with
clang-format.It seems a lot of commits... Please feel free to tell me to modify or change things that you need.