1.3: Added 3D functions. Unfortunately I was hamstrung by a lack of arguments - 10 max, which is only 3 3D points.1.3: Improved bezier performance has improved slightly.1.3: Fixed bezier curves were colour/alpha interpolated backwards except for their endpoints. Whoops.

1.2: First release.

WHATCurves are nice. This draws curves. The tentacles in the title graphic were drawn using this extension, for example.

WHYCurves are nice, but calculating their vertices is far too slow for GML. They're also a bit difficult to grasp for novice programmers. That sucks.

HOWThe extension performs its calculations in machine code with SSE2 instructions, using GMAPI to call GM's primitive-drawing functions. This drastically increases performance. For example, a 40-vertex spline takes 95 times longer to draw in GML than with this extension. The difference becomes even more pronounced with higher vertex counts.

d3d_bezier_begin()Start drawing a bezier curve in 3D. You can specify 3 points for a quadratic curve, or 4 points for a cubic one. Excess points are ignored. This is the only way to draw a cubic bezier curve in 3D.

d3d_curve_vertex( x,y,z )d3d_curve_vertex2( x1,y1,z1, x2,y2,z2 )d3d_curve_vertex3( x1,y1,z1, x2,y2,z2, x3,y3,z3 )Set the curve points. You can specify up to three points at a time. This seems redundant, but because of the function call overhead, batching multiple points together is considerably faster than specifying them individually. The point order is the same as the normal functions - start, end, control1, control2.

d3d_bezier_end()This actually draws the curve. You can call this multiple times to redraw it without specifying the points again. This is useful if you want to draw the same curve rotated, scaled or translated using the d3d_transform functions.

The start/end/vertex functions work the same as with bezier curves, except that you can specify up to 512 points for the spline to pass through. As before, minimising function calls is good for speed, so I provided batch functions.

The DS functions allow you to pass up to 512 points in a list. The ds_list should be structured as coordinate pairs/triplets like this: [x1][y1][x2][y2] or [x1][y1][z1][x2][y2][z2] etc. These functions are a little slower than the others. Warning: if you pass a list containing a string or pass a nonexistent list, your game may hang or crash. For the sake of speed there are very few sanity checks.

draw_sector( x,y, radius, arc, dir )Draw an arc with the endpoints connected to the origin. Interpolates colour and alpha outwards from the origin.

Configurationdraw_set_bezier_precision( vertices )Number of vertices to use. 2 to 512, 28 by default. Note: even though you can go much higher, more than 64 points is usually a waste of resources given the tiny visual difference.

draw_set_bezier_primitive( primitive )Which primitive to use when drawing beziers. pr_linestrip by default. Use the other constants to get different effects; for example pr_linelist draws dashed lines.

draw_set_bezier_color( col1, col2 )Colour of the start and end points. Smoothly interpolated along the length of the curve. By default these are set to -1, which automatically uses the current colour as set by draw_set_color().

draw_set_bezier_alpha( alpha1, alpha2 )Alpha of the start and end points. Works the same as the colour.

draw_set_bezier_all( vertices, primitive, col1, col2, alpha1, alpha2 )Set everything at once. This is faster than doing it individually and usually more convenient.

Note that all these values are independent. Setting the colour or alpha doesn't affect GM's current drawing colour or the colour of any other type of curve.

draw_set_arc_precision( vertices )draw_set_arc_primitive( primitive )draw_set_arc_color( col1, col2 )draw_set_arc_alpha( alpha1, alpha2 )draw_set_arc_all( vertices, primitive, col1, col2, alpha1, alpha2 )Same as above, except arcs default to -1 precision. -1 means the number of vertices is dynamically selected according to a heuristic which takes into account the radius and arc width. It tries to provide the best performance without sacrificing visual quality. It will not exceed 64 vertices. At the moment the other functions don't have this, but I'll probably implement that in a future version.

PresetsBecause it can be tiresome to specify the curve settings every single time you draw a curve, you can store them for later use. This also helps performance.

draw_define_curve_preset( vertices, primitive, col1, col2, alpha1, alpha2 )Define a preset. Returns an index to use with the functions below. You can create up to 1024 presets. They can't be destroyed or modified afterwards; if you define more than 1024 the extension will start overwriting old ones. I'll make this more flexible in future if that proves to be a problem.

draw_set_bezier_preset( preset )draw_set_spline_preset( preset )draw_set_arc_preset( preset )Set the current drawing values from a preset you've created. You can also pass -1 to reset the values to their defaults.

PerformanceHere's a performance breakdown. The number next to the function signifies average execution time for the function in terms of multiples of the execution time of draw_line() using the default precision values. In other words, calling the function is equivalent in performance to calling draw_line() that many times. Lower is better. For reference, draw_line() takes 1.5 microseconds on my computer.

Note: Triangular primitives are slower to draw than lines or points. The above measurements were made using pr_linestrip.

To do:I'll add this stuff when I have some free time:- Precision heuristics for splines and beziers. The fewer function calls the better.- Any ideas? I've done everything I personally needed, so it's up to you guys.

Update: version 1.3I've added a few new functions and fixed a bug with bezier curves.

draw_spline_ds( ds_list )Draws a spline through a ds_list of points. This allows you to pass up to 512 points, but is slower than the standard functions. The more points the slower it becomes, although 32 points or less is still reasonably fast. The calculations and rendering steps involved are actually identical regardless of the number of points, the slow part is getting them out of the ds_list in the first place. Let me know if you have any ideas for handling this better.

d3d_bezier_quadratic( x1,y1,z1, x2,y2,z2, cx,cy,cz )Draw a bezier curve in 3D. Unfortunately I couldn't add the cubic version due to lack of arguments.

Wow, magic!I think that greatness of this extension can be describeed by the following image:Thats provided demo, maximum detail, most speed-consuming type. Still over 60 fps

I wish I had something like this for AS3. I have a couple of projects starving without proper bezier curves.

For the 3d beziers & splines, you can make something similar to standart primitive system. Define a array to store parameters in, and when _end() is executed, loop through it and draw everything on its places.

For the 3d beziers & splines, you can make something similar to standart primitive system. Define a array to store parameters in, and when _end() is executed, loop through it and draw everything on its places.

Good idea. I've implemented this and updated the first post with the changes.

I find it tiresome to use the config functions all the time, so I added _all variants which set everything at once. I've also added functions that define parameter presets, allowing you to load and save curve configurations. This makes it easier to use the functions since you don't have to specify everything constantly. It's also faster.

Thats so incredible. I'm dreaming of the great effects I could make with this extension xD
I think this is even faster then particles.

Since you are already using the GMApi to get informations from the game, could you make a possibility to stop drawing automatic when a 'tentacle' leaves the visible area (for example a given view).
That could fasten a game further.

But very very good work anyway.
I'll give you much credits in my game when I'm using this.

Since you are already using the GMApi to get informations from the game, could you make a possibility to stop drawing automatic when a 'tentacle' leaves the visible area (for example a given view).That could fasten a game further.

It's better to handle that with standard methods like instance deactivation.

Even if nothing is drawn the functions still take some CPU time due to overhead, which means the benefit would be pretty small. Also my code is structured in a way that makes it difficult to implement this, especially without degrading performance in the general case.

I actually looked at this a long time ago, but now decided to praise you. Really nice work. I was amazed about the example as it was so unexpectedly beautiful and fast considering GM is drawing it. Getting points on the curve is actually quite useful feature, but it possibly could be pain in the ass to find the point on a ds curve.I was actually inspired by this to make these functions. But I would want to know how did you make the continues curve with the d3d_bezier_begin function? Does it actually draw a Bezier or some spline with Hermite (or other) interpolation? You already have a spline_begin function so I guess it really draws a Bezier, but then what order curve is it? I actually haven't tested the bezier_begin function so I should probably do that.Anyway, really nice work.

But I would want to know how did you make the continues curve with the d3d_bezier_begin function? Does it actually draw a Bezier or some spline with Hermite (or other) interpolation? You already have a spline_begin function so I guess it really draws a Bezier, but then what order curve is it? I actually haven't tested the bezier_begin function so I should probably do that.Anyway, really nice work.

Nothing that nice I'm afraid! Those functions exist only because of GM's limit of ten arguments. They only draw single quadratic/cubic beziers, selecting which to use based on the number of points given. They ignore anything higher.

It would be useful if you added a little help file to the extension. Or at least a link to this topic (by including an .url file (created by right clicking - create new link...) instead of a help file) (yes this works, I just tested it, you just have to manually start typing the name of the link file when including it as its not shown even with "All Files" selected).

May I suggest a draw_pie function with the same parameters as draw_arc? I made one myself but I draw a lot of them quite often so I was hoping there was a similar way to make it faster as you've done with all of these.