-
-
Notifications
You must be signed in to change notification settings - Fork 10.7k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Improve on automatic circle segment count calculation #3808
Conversation
eb71b82
to
92a0005
Compare
Going to have to create new certificates like the one in #3627 .. |
off_x += 10.0f + rad * 2.0f; | ||
const float rad = RAD_MIN + (RAD_MAX - RAD_MIN) * (float)n / (9.0f - 1.0f); | ||
|
||
const int segment_count = draw_list->_CalcCircleAutoSegmentCount(rad); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imgui_demo never relies on private APIs, except this one new case.
Lines 2440 to 2447 in 00d570e
// [Internal helpers] | |
IMGUI_API void _ResetForNewFrame(); | |
IMGUI_API void _ClearFreeMemory(); | |
IMGUI_API void _PopUnusedDrawCmd(); | |
IMGUI_API void _OnChangedClipRect(); | |
IMGUI_API void _OnChangedTextureID(); | |
IMGUI_API void _OnChangedVtxOffset(); | |
IMGUI_API int _CalcCircleAutoSegmentCount(float radius) const; |
When porting over the demo, I had to skip this line:
I think this should be fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is documented as private but available in imgui.h and we use it to provide info about tessellation in the demo. I think that's fine, and very obviously we don't expect people to copy/reuse this overly specific tessellation display code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please consider that previously it would be 100% true to say "absolutely everything in imgui_demo can be done without internal calls". I think that's worth something. But now you cannot say this.
This PR improves on automatic number of circle segment calculation for anti-aliased and non anti-aliased shapes.
The Old
After analyzing equation in
IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC
few issues were discovered:N
was two times bigger than necessary (error was applied to half of an angle spanned by the segment)This is event somewhat acknowledged in the code, because small circles received too many segments:
FIXME: the minimum number of auto-segment may be undesirably high for very small radiuses (e.g. 1.0f)
.CircleSegmentMaxError
claim to be expressed in pixels, but default value 1.6 seems to not reflect thatThe New
Equation for number of circle segments was derived from scratch using method described in this stackoverflow post. Which lead to discoveries listed above about old method.
New method:
CircleSegmentMaxError
to 0.5f, which is half of a pixelMore details
Number of segments (N) is calculated using equation:
Note:
Rendering circles with an odd number of segments, while mathematically correct will produce
asymmetrical results on the raster grid. Therefore we're rounding
N
to next even number.(7 became 8, 11 became 12, but 8 will still be 8).
Error value is expressed in pixels and defaults to 0.5f, half a pixel. Which produce
non anti-aliased circles where segments cannot be spotted.
Anti-aliasing work on much finer grid than pixels which make segments visible. To mitigate this
issue error is scaled by
IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_AA_ERROR_SCALE_FACTOR
defaulting to0.5f
.This make anti-aliased circles use
0.25f
as an error value, making segments unnoticeable.Derivation
N
equation was derived by following steps in method described in this stackoverflow post. What I did differently is I choose differentA
andB
points to make calculations simpler.Comparison
At previews you can see actual maximum error value used.
Old vs. New
Anti-Aliased
Non Anti-Aliased
Notice there are gaps on the circumference of the circle N 27 in the Old. They appear if mesh is too dense.
New Method: AA vs. Non AA
Maximum error: 0.5
Notice that you can spot line segments when circle is drawn with same number of segments for AA and not-AA circles.
Maximum error: 0.25
Notice that non anti-aliased primitives has gaps due to too dense mesh (first circle), but anti-aliased drawing give the desired result.