User:Dilithjay/GSoC 2021/Curve Improvements

= Curve Improvements =

Name
Dilith Jayakody

Contact
@dilithjay on devtalk, d.b.o & chat

Synopsis
The Curve object type has been subject to a number of user requests for improvement from several different aspects. The goal of this project is to address and build solutions for some of these suggestions.

Benefits
With the addition of these improvements, the user would be able to perform operations on curves more efficiently instead of following longer routes to get to the same end product. This would lead to faster and smoother workflows when modeling curves.

Deliverables
to assist a smoother workflow. (see request here)
 * A modal tool in which curves can be edited more efficiently using simple shortcuts
 * Click to add new control point
 * Mouse down + drag to add a new control point and adjust handles.
 * Shift + drag to adjust handles as free handles.
 * Ctrl + Click a segment to make a cut
 * Ctrl + Click a point to delete point
 * Click and Drag points/handles to move
 * A tool to perform a vertex-bevel-like rounding of corners. (see request here)

Functionality 1

 * When the mouse is pressed while a control point is selected, a new control point that’s connected to the selected point shall be added directly underneath the mouse pointer. (see ed_editcurve_addvert in editcurve.c)
 * If the mouse press was followed by a release (a click), then the control point would have handles of type “vector”, with one handle pointing to the previous control point (if any) and the other pointing to the next (if/when added).
 * If the mouse was pressed and dragged, then handles of type “aligned” are created and moved with the mouse cursor until released.
 * If shift was pressed before or during dragging, the inner handle would be of type “vector” while the outer would be of type “free”, where the handle location for the free handle would be determined by the location of the mouse cursor.
 * The functionality would be expanded to add a new spline if no control point is selected.

Functionality 2

 * An indicator point that would snap onto nearby edges (similar to the knife tool; knife_find_closest_edge_of_face in editmesh_knife.c can be referred) would appear while the Ctrl button is pressed and upon the user’s click, a control point of handle type “automatic” shall be added at the indicator’s location.
 * The snapping of the indicator can be achieved by looping over all edges of each spline, calculating the smallest distance between the cursor and each edge (taking the view context into consideration), checking if the smallest distance is less than a certain threshold (implementation of knife_snap_size in editmesh_knife.c can be referred) and displaying the indicator on the closest point on the edge.

Functionality 3

 * When a control point is clicked while Ctrl is pressed, the point is deleted by duplicating the spline with the exclusion of the clicked point.
 * If the point was the only control point, then the entire spline shall be deleted.

Functionality 4

 * This functionality is meant to work exactly like the existing tweak tool under the select toolset and thus, its implementation can be referred to during development.

I implemented the base for the tool after looking over existing implementations of different tools within the Blender source code. I’m hoping that the head-start would make the completion of the rest of the other beveling project possible. The current implementation of the tool (as of the submission of the proposal) simply replicates the “Extrude to Cursor” tool except for the fact that clicking on an existing control point selects it instead of extruding to the point.

''Note: The naming of the tool and the functions are yet to be decided and finalized and they would almost definitely change from that of the current implementation. Additionally, it should be noted that even the algorithm would likely undergo some changes since the provided skeleton is based on my limited knowledge regarding available functions within the source code. I intend to continue to try and understand the source code and accordingly, the diff file may be updated if I find something that can be improved. Admittedly, the current implementation has a lot of room for improvement, but I’m confident in my ability to get it up to the standards maintained in Blender’s code base.''

Vertex-bevel-like Rounding of Corners
The bevel can be created by dividing the selected point into 2 separate control points, and then moving them along the respective edges which were initially connected to the selected point. According to multiple sources, a good approximation for the handle lengths (𝐿) of the two control points forming the circular arc, could 𝐿 be calculated as 𝐿 = 4𝑅/3 * 𝑡𝑎𝑛(𝐴/4), where R is the radius of curvature and A is the angle, both of which can be calculated using the location of the control points and the angle between the adjacent edges.

While 2 control points are sufficient to get a fairly good approximation of a circular arc using the above mentioned equation (0.027253% error for a quarter of a circle as mentioned in https://spencermortensen.com/articles/bezier-circle/), as the angle increases, the error too seems to increase (see Figures 1 & 2 below). Accordingly, for such cases, an option to create bevels with a user-defined number of curve segments and an option for an adaptive number of segments (increment number of segments each time the angle between adjacent edges exceeds a certain threshold) would be provided (the larger the number of control points, the better the approximation of the circle).

Once the number of segments is decided on, the coordinates of the rest of the control points can be determined by uniformly sampling a parametric equation of a circular arc. Afterwards, the handle lengths (equal for all control points inside the arc) can be found using the previously mentioned method where R is the radius formed by the two end points and A is the angle formed by the two endpoints divided by the number of segments between the endpoints.

Additionally, similar to bevels on meshes, an option to use a “superellipse” as a parameter to alter the profile of the bevel can be provided. This can be achieved by first sampling the respective superellipse parametric equation for a required number of segments (existing functions like superellipse_co in bmesh_bevel.c can be utilized). Afterwards the required Bezier curve can be obtained using FitCurve.cpp.

''Note: For the summer, I wish to guarantee the implementation up until the creation of a tool to perform a circular bevel with a single segment. I also intend to complete as much of the remaining features (bevel with user-defined number of segments, bevel with an adaptive number of segments and the superellipse bevel) within the summer, and the rest, afterwards.''

Project Schedule
I would likely have an exam (date not yet announced) during the GSoC time period for which I have allocated 2 weeks during which I may not be able to work on the project much. As for the rest of the time period, I intend to work for 18 hours a week for approximately 3 weeks preceding the exam and almost full-time (approximately 30 hours per week) for the rest of the time period.

Community bonding period (May 17, 2021 to June 7, 2021): Get familiar with the implementations of all the UI components that would likely be used (tool menu, knife tool UI, specials pop-up menu, tool handles)

During the 10 weeks from June 7, 2021 to August 16, 2021:

Bio
I am Dilith Jayakody, a 3rd year Computer Science and Engineering undergraduate at the University of Moratuwa, Sri Lanka.

My passion for programming began back in 2017 when I grew an interest in creating video games. I learned to program in C# for Unity and I started using Blender for 3D modelling and animations. Around the same time, I also learned C in an online course known as CS50’s Introduction to Computer Science offered by Harvard University. Since then, I have engaged in multiple programming-related projects, most of which used Python for some computer vision task. Admittedly, I only have one project for which I used C++ but I am quite comfortable with the syntax of the language since I followed multiple online courses to learn it. I also tried my hand at competitive programming and freelancing using Python and C++ through which my programming knowledge grew.

I believe that I would be the best person for this project because I already have some experience with working with the Curve objects in Blender (see D9684) while also being quite comfortable with the math behind the implementations. Additionally, I intend to contribute to Blender even after the GSoC period as often as I can. So, I’d be able to continue from where I left off at the end of the period. Last but not least, programming is something I genuinely do enjoy and something I could work hard at.