[shapes] Curved Line
Closed this issue · 14 comments
Hey!
I was wondering how I could draw a curved line with this? Or is it something I would have to implement myself using DrawPixel or something? If I have to do it myself, please do share tips on that.
Thanks!
Hi Chillance,
Note that 'curved lines' can be drawn in multiple different ways, more curved, less curved, with control points (bezier curves). raylib doesn't include by default a function to draw curved lines but you can use easing function. Those math functions return intermediate values when interpolating from one initial value to a final value, they are usually used for animations but they can also be used to draw curved lines. raylib includes an easings module, it's a header-only single-file module and you need to include it in your project.
To draw a curved line you need to draw multiple straight lines connected, everyone starting at the end of the previous, to calculate the intermediate values, you can use the easing functions.
Example:
void DrawLineEasing(Vector2 init, Vector2 final, int divs, Color color)
{
Vector2 previous = init;
Vector2 current;
for (int i = 1; i < divs; i++)
{
// NOTE: Easing is calcutated only for y position value
current.y = EaseCubicOut(i, init.y, final.y - init.y, divs);
current.x = previous.x + (final.x - init.x)/divs;
DrawLineV(previous, current, color);
previous = current;
}
}
Will this enable me to do this https://cloud.githubusercontent.com/assets/8057201/9976995/e81ac04a-5ef7-11e5-872b-acd54fbeee03.gif ?
The nuklear library seems to specify angles with the nk_stroke_curve function to draw curves.
I will try this out in the meantime, but having to specify amount of divisions here, could make it a bit odd when drawing different length of the curves unless I also update the amount of divisions based on length...
For bezier curves this tutorial can be used:
http://devmag.org.za/2011/04/05/bzier-curves-a-tutorial/
Hi @Chillance I worked on a node based tool for raylib to build shaders with nodes and compile it as a GLSL shader program. Here is the repo: https://github.com/victorfisac/FNode
Search in the repo the function: DrawNodeLine(). The param FLine contains the from and to nodes ids to get its positions and draw the line between the nodes.
Code to draw a curved line (from and to are position Vector2 of the line):
#define NODE_LINE_DIVISIONS 20 // Node curved line divisions
int current = 0;
while (current < NODE_LINE_DIVISIONS)
{
Vector2 fromCurve = { 0, 0 };
fromCurve.x = FEaseLinear(current, from.x, to.x - from.x, NODE_LINE_DIVISIONS);
fromCurve.y = FEaseInOutQuad(current, from.y, to.y - from.y, NODE_LINE_DIVISIONS);
current++;
Vector2 toCurve = { 0, 0 };
toCurve.x = FEaseLinear(current, from.x, to.x - from.x, NODE_LINE_DIVISIONS);
toCurve.y = FEaseInOutQuad(current, from.y, to.y - from.y, NODE_LINE_DIVISIONS);
DrawLine(fromCurve.x, fromCurve.y, toCurve.x, toCurve.y, BLACK);
}
// Returns an ease linear value between two parameters
static float FEaseLinear(float t, float b, float c, float d)
{
return (float)(c*t/d + b);
}
// Returns an ease quadratic in-out value between two parameters
static float FEaseInOutQuad(float t, float b, float c, float d)
{
float output = 0.0f;
t /= d/2;
if (t < 1) output = (float)(c/2*t*t + b);
else
{
t--;
output = (float)(-c/2*(t*(t-2) - 1) + b);
}
return output;
}
Note: to draw the line curved as a typical node editor, X axis needs to be EaseLinear and Y axis EaseInOutQuad.
Wow, thanks @victorfisac ! That works out fantastically! I'm actually using https://github.com/gen2brain/raylib-go (Go wrapper for raylib), and converted this to Go, and it works great! I assume this is not something that will be added to raylib? Drawing curved lines that is.
Uh, for some reason, wherever I put this code to draw this curved line, it seems to end up behind the other rectangles I draw within the Begin2dMode. Not sure why. Even if placed last, it's still behind the rectangles drawn earlier. After End2dMode is shows above the rectangles. Why is this? Order matters from what I can tell tell testing drawing the rectangles in different orders, where last one is above the others.
Hi Chillance,
I assume this is not something that will be added to raylib? Drawing curved lines that is.
It can be added. :)
About drawing order, that's related to the way raylib processes vertex information internally, QUADS buffers (used to draw rectangles and textures) are always processed after LINES buffers (used to draw lines). For that reason, LINES are always drawn first. Note that all drawing actually happens at EndDrawing()
, before that point, you're only storing required vertex data into buffers (it's a batching system).
SOLUTION: Use QUADS to draw lines instead of LINES. Just added DrawLineEx()
for that pourpose.
Cool! However, something is off regarding math, as now it draws the segments correctly in one direction, but not the other: http://i.imgur.com/QlU8CFp.png As you can see there, the segments are rotated in the wrong direction...
Cool! However, something is off regarding math, as now it draws the segments correctly in one direction, but not the other: http://i.imgur.com/QlU8CFp.png As you can see there, the segments are rotated in the wrong direction...
Is that issue happening when using DrawLineEx()
?
Does it only happen when (startPoint.x > endPoint.x)
?
About curved lines drawing, I can add the following function:
void DrawLineBezier(Vector2 startPos, Vector2 endPos, Color color)
Actually, to be technically correct, it would be a cubic-bezier line but the two control points are not configurable in the function... later on a DrawLineBezierEx()
could be added...
Yes, only happens with DrawLineEx(). And only when startPoint.x > endPoint.x.
Also, that DrawLineBezier would be cool. So, the Ex version would support points which would make it possible to change the angle or something? Right now, the curving is from the start and end position, but as I mentioned earlier, the function from nuklear supports angles that makes the curve bend (out from the start/end point) more before going towards the other point. As you can see here: http://i.imgur.com/MG0M5Kk.png I'm just saying that the Ex version could support that flexibility regarding the bending there.
DrawLineBezier()
added in commit 3813722.
Also corrected issue with DrawLineEx()
, actually, DrawLineBezier()
uses that function.
I recommend you to use
SetConfigFlags(FLAG_MSAA_4X_HINT);
before InitWindow()
to avoid aliasing.
Closing this issue for now.
Great! Thanks!