
>>> Download <<<
Latest version: 1.5
Last updated: 05/Dec/2010
Changelog
1.5: Added functions which set all curve parameters in one call.
1.5: Added functions to save and load sets of parameters.
1.4: Added a simpler method for drawing multipoint 2D/3D splines which supports up to 512 points.
1.4: Added the ability to draw 3D cubic beziers.
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.
WHAT
Curves are nice. This draws curves. The tentacles in the title graphic were drawn using this extension, for example.
WHY
Curves 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.
HOW
The 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.
DEMO
Here's a demo I created using Curves. Each tentacle is a spline.

Download EXE
Download GMK (works with GM7 and GM8)
HOW TO USE
Here is how to use the extension's functions and what kind of results you can expect from them.
Beziers

draw_bezier_quadratic( x1,y1, x2,y2, cx,cy )
Draw a bezier curve with one control point.
draw_bezier_cubic( x1,y1, x2,y2, cx1,cy1, cx2,cy2 )
Draw a bezier curve with two control points.
d3d_bezier_quadratic( x1,y1,z1, x2,y2,z2, cx,cy,cz )
Draw a bezier curve in 3D.
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.
Splines

draw_spline3( x1,y1, x2,y2, x3,y3 )
draw_spline4( x1,y1, x2,y2, x3,y3, x4,y4 )
draw_spline5( x1,y1, x2,y2, x3,y3, x4,y4, x5,y5 )
draw_spline_begin()
draw_curve_vertex( x,y )
draw_curve_vertex2( x1,y1, x2,y2 )
draw_curve_vertex3( x1,y1, x2,y2, x3,y3 )
draw_curve_vertex4( x1,y1, x2,y2, x3,y3, x4,y4 )
draw_curve_vertex5( x1,y1, x2,y2, x3,y3, x4,y4, x5,y5 )
draw_spline_end()
draw_spline_ds( ds_list )
d3d_spline3( x1,y1,z1, x2,y2,z2, x3,y3,z3 )
d3d_spline_begin()
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 )
d3d_spline_end()
d3d_spline_ds( ds_list )
Draw a curve which passes through all intermediary points.
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.
Arcs

draw_arc( x,y, radius, arc, dir )
Draw an arc centred on [x,y] [arc] degrees wide, centred around angle [dir]. Interpolates colour and alpha clockwise along the curve. (This can be inverted by negating the arc value)
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.
Configuration
draw_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_spline_precision( vertices )
draw_set_spline_primitive( primitive )
draw_set_spline_color( col1, col2 )
draw_set_spline_alpha( alpha1, alpha2 )
draw_set_spline_all( vertices, primitive, col1, col2, alpha1, alpha2 )
Same as above. Precision defaults to 40.
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.
Presets
Because 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.
Performance
Here'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.
Function Relative performance draw_bezier_quadratic 3.2 draw_bezier_cubic 3.5 draw_arc 2.5 draw_sector 2.7 draw_spline3 3.9 draw_spline4 4.1 draw_spline5 4.7 draw_spline_ds 8.1 (32 points / 64 ds_list entries) d3d_bezier_quadratic 3.0 d3d_spline3 3.4 d3d_spline_ds 15.2 (32 points / 96 ds_list entries)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.
>>> Download <<<
Latest version: 1.5
Last updated: 05/Dec/2010
Edited by LSnK, 19 December 2010 - 05:27 PM.















