From BlenderWiki

Jump to: navigation, search

I needed a couple of new curve selection tools (mainly "Select Every Nth" and "Select Random") so I wrote them. While writing them I noticed that they could be written in a way that could reduce the amount of code overhead needed to do certain things. This was how idea for select_adjacent_cp was born.

I also decided to encapsulate basic selecting of a control point to a couple of functions: select_beztriple and select_bpoint. By control point I refer to both BezTriple and BPoint. Code had to be written for both types separately as no inheritance nor more advanced coding concepts could be used due to limitations set by coding language and skill. I will review the significant new functions created, new functionality gained and the overall architecture of the new system in this document.

Architecture

/* note; alfa location in struct is abused by Key system */
/* vec in BezTriple looks like this:
	vec[0][0]=x location of handle 1
	vec[0][1]=y location of handle 1
	vec[0][2]=z location of handle 1 (not used for IpoCurve Points(2d))
	vec[1][0]=x location of control point
	vec[1][1]=y location of control point
	vec[1][2]=z location of control point
	vec[2][0]=x location of handle 2
	vec[2][1]=y location of handle 2
	vec[2][2]=z location of handle 2 (not used for IpoCurve Points(2d))
*/
typedef struct BezTriple {
	float vec[3][3];
	float alfa, weight, radius;	/* alfa: tilt in 3D View, weight: used for softbody goal weight, radius: for bevel tapering */
	short h1, h2;
	char f1, f2, f3, hide;
} BezTriple;
 
/* note; alfa location in struct is abused by Key system */
typedef struct BPoint {
	float vec[4];
	float alfa, weight;		/* alfa: tilt in 3D View, weight: used for softbody goal weight */
	short f1, hide;
	float radius, pad;		/* user-set radius per point for bevelling etc */
} BPoint;
 
typedef struct Nurb {
	struct Nurb *next, *prev;	/* multiple nurbs per curve object are allowed */
	short type;
	short mat_nr;		/* index into material list */
	short hide, flag;
	short pntsu, pntsv;		/* number of points in the U or V directions */
	short resolu, resolv;	/* tesselation resolution in the U or V directions */
	short orderu, orderv;
	short flagu, flagv;
 
	float *knotsu, *knotsv;
	BPoint *bp;
	BezTriple *bezt;
 
	int charidx;
	int pad;
} Nurb;

Relevant structs related to curve selection code

Relevant structs based on viewpoint of selection tools can be seen above. As you can see it is possible that a curve object contains multiple Nurbs. Each Nurb may contain either BPoint or BezTriple based curve. So it is possible to have a curve object containing both NURBS (BPoint) and Beziér (BezTriple) based curves. Pure surfaced NURBS may not contain Beziér based curves though.

Selection functions

Each control point selection operation was changed to use functions briefly shown in this section. To make function calls easier to read defines are used as in following example in which BPoint called bp is SELECTed with flag status of flag and also HIDDEN one can be selected:

  • select_bpoint(bp, SELECT, flag, HIDDEN);

Basic selection functions

  • static short select_beztriple(BezTriple *bezt, short selstatus, short flag, short hidden)
  • static short select_bpoint(BPoint *bp, short selstatus, short flag, short hidden)

Reference to wanted control point, wanted selection status, flag status and special parameter called hidden are given to basic selection functions. hidden can be used to determine whether visibility status of given control point should be respected. Functions return value determining whether operation was successful.

Note that even if selection status of control point was for instance selected and select function is called to select it again. It will do the operation as expected. No special value is returned in this case. Return value is given as usual.

Swap selection functions

  • static short swap_selection_beztriple(BezTriple *bezt)
  • static short swap_selection_bpoint(BPoint *bp)

swap_selection functions can be used to inverse selection status of given control point.

Selectend Nurb

  • void selectend_nurb(short selfirst, short doswap, short selstatus)

selectend_nurb sets selection status of given end (selfirst is FIRST or LAST) of each Nurb in case doswap is false. If doswap is true, selection status is swapped.

Select Adjacent Control Point

  • static void select_adjacent_cp(short next, short cont, short selstatus)

This function can be used to cascade selection status (selstatus) of (de)selected control points to control points within distance given by next parameter. cont defines whether this operation should be done for selected neighbours as well. cont can be useful for cascading certain selection status for all control points. This function is widely used within revised selection tools.

Benefits of the New System

Complexity of certain selection tools reduced due to new, introduced functions shown. Good examples of such tools are deselectall_nurb(), select_next_nurb(), select_prev_nurb() and select_more_nurb(). Additionally select_more_nurb() was coded to work properly in case of NURBS. Previously it did not function as expected. Also select_less_nurb() should work now as expected.

Totally new functionality was gained as well. Examples of new functionality are select_every_nth_nurb() and select_random_nurb(). For latter a new function was created to generate an array containing discarded numbers.

Select Random linked list algorithm

This can be seen in generate_pickable_list(int *list, int size, int pickamount). It returns an array containing a linked list so that value of an item contains index of next member of the linked list. Index works as number in this case as well. In case an item is not part of the linked list, it contains -1 to show it has been discarded.

Illustration of a linked list structure used: 1->-1, 2->5, 3->-1, 4->-1, 5->6, 6->2, 7->-1

This list contains following list: 2->5->6. Note that it is circular meaning that the last item has a reference to the first item.

It would be possible to reuse this algorithm in other suitable random selection tools.

User Level Descriptions of the Selection Tools

User level descriptions of each curve selection tool can be found at this page.

Possible TODO

It would be possible to further clarify the concept of flag used within editcurve.c. Also it is worth investigating whether the curve structure can be simplified so that a cleaner interface for selecting control points is possible. New curve selection tools could be added and the overall user interface could be made more coherent with mesh edit mode for instance. Similar functionality such as edge loop select in mesh edit mode could be brought to curve selection tools.