如何使用 dear imgui 填充两条贝塞尔曲线之间的区域
How to fill the area between two bezier curves using dear imgui
如何使用 dear imgui 填充两条贝塞尔曲线之间的区域?
我使用 ImDrawList API 绘制曲线,如下所示:
ImVec2 p0(10, 100); ImVec2 c1(110, 50); ImVec2 p1(210, 100);
ImVec2 q0(10, 200); ImVec2 c2(110, 100); ImVec2 q1(210, 200);
auto col = IM_COL32(0,255,255, 255);
ImDrawList* draw_list = ImGui::GetWindowDrawList();
draw_list->AddBezierCurve(p0, c1, c1, p1, col, 1.0f);
draw_list->AddBezierCurve(q0, c2, c2, q1, col, 1.0f);
// I can close the curves, visually, with these lines
draw_list->AddLine(p0, q0, col, 1.0f);
draw_list->AddLine(p1, q1, col, 1.0f);
编辑:
我使用有状态的API绘制了我想要的路径,然后我调用了一个函数来填充这条路径。这是代码:
draw_list->PathLineTo(p0);
draw_list->PathBezierCurveTo(c1, c1, p1);
draw_list->PathLineTo(q1);
draw_list->PathBezierCurveTo(c2, c2, q0);
draw_list->PathFillConvex(col);
但是如您所见,有些地方不对劲:
正确的几何图形以白色绘制。
您 运行 遇到的问题是,OpenGL 中的填充基元仅针对 凸面 基元定义。一个集合被定义为凸如果对于集合内的任何两个点你可以在这些点之间画一条线而不离开所述集合的边界。
Dear-ImGUI 大多数情况下只是将翻译后的绘图命令按原样传递给 OpenGL,没有任何中间细分。 …这会导致您看到的问题以及为什么填充函数的名称中包含 …Convex
部分。
解决方案是将非凸形状分解为更小的凸子形状,或者使用也适用于凸形状的填充方法,例如 scanline 算法(在使用计算着色器最容易完成 GPU。
你需要一个凹面填充算法,亲爱的imgui没有提供。一般倾向于easier/faster把你的形状分解成凸形。填充 "between two beziers" 的一般情况很棘手,因为贝塞尔曲线可以相交,因此可以有多个区域。如果您知道它们永远不会相交并且您的切线不太疯狂,您可以使用各种近似值。也许尝试绘制 N 个四边形,其中每个四边形 links 贝塞尔曲线的两段以规则间隔等。Datenwolf 答案是更通用答案的一个很好的起点。
我还需要对 Datenwolf 的回答发表评论。亲爱的 ImGui 不 "passes on the translated drawing commands to OpenGL as they are" 这个声明在这里没有意义,因为所有三角测量都是由 imgui 执行的,并且没有 OpenGL 知道的填充或形状的概念,因为它只传递原始纹理三角形.
理论上,亲爱的 imgui 可以提供 "PathFillConcave()" 功能,但尚未实现,而且实现起来可能成本高昂且复杂。上面贴的link确实有一个
如何使用 dear imgui 填充两条贝塞尔曲线之间的区域?
我使用 ImDrawList API 绘制曲线,如下所示:
ImVec2 p0(10, 100); ImVec2 c1(110, 50); ImVec2 p1(210, 100);
ImVec2 q0(10, 200); ImVec2 c2(110, 100); ImVec2 q1(210, 200);
auto col = IM_COL32(0,255,255, 255);
ImDrawList* draw_list = ImGui::GetWindowDrawList();
draw_list->AddBezierCurve(p0, c1, c1, p1, col, 1.0f);
draw_list->AddBezierCurve(q0, c2, c2, q1, col, 1.0f);
// I can close the curves, visually, with these lines
draw_list->AddLine(p0, q0, col, 1.0f);
draw_list->AddLine(p1, q1, col, 1.0f);
编辑:
我使用有状态的API绘制了我想要的路径,然后我调用了一个函数来填充这条路径。这是代码:
draw_list->PathLineTo(p0);
draw_list->PathBezierCurveTo(c1, c1, p1);
draw_list->PathLineTo(q1);
draw_list->PathBezierCurveTo(c2, c2, q0);
draw_list->PathFillConvex(col);
但是如您所见,有些地方不对劲:
正确的几何图形以白色绘制。
您 运行 遇到的问题是,OpenGL 中的填充基元仅针对 凸面 基元定义。一个集合被定义为凸如果对于集合内的任何两个点你可以在这些点之间画一条线而不离开所述集合的边界。
Dear-ImGUI 大多数情况下只是将翻译后的绘图命令按原样传递给 OpenGL,没有任何中间细分。 …这会导致您看到的问题以及为什么填充函数的名称中包含 …Convex
部分。
解决方案是将非凸形状分解为更小的凸子形状,或者使用也适用于凸形状的填充方法,例如 scanline 算法(在使用计算着色器最容易完成 GPU。
你需要一个凹面填充算法,亲爱的imgui没有提供。一般倾向于easier/faster把你的形状分解成凸形。填充 "between two beziers" 的一般情况很棘手,因为贝塞尔曲线可以相交,因此可以有多个区域。如果您知道它们永远不会相交并且您的切线不太疯狂,您可以使用各种近似值。也许尝试绘制 N 个四边形,其中每个四边形 links 贝塞尔曲线的两段以规则间隔等。Datenwolf 答案是更通用答案的一个很好的起点。
我还需要对 Datenwolf 的回答发表评论。亲爱的 ImGui 不 "passes on the translated drawing commands to OpenGL as they are" 这个声明在这里没有意义,因为所有三角测量都是由 imgui 执行的,并且没有 OpenGL 知道的填充或形状的概念,因为它只传递原始纹理三角形.
理论上,亲爱的 imgui 可以提供 "PathFillConcave()" 功能,但尚未实现,而且实现起来可能成本高昂且复杂。上面贴的link确实有一个