Alright, so this one is also lots of fun. We are going to create a NurbsCurve using OpenMaya, with a leading degree of 2 (Quadratic). Remember in the previous post about how I calculated the vectors between the two locator positions? Well this time, we are going to do the same, but creating nurbsCurve. This is because each CV needs a position vector array:.
def get_point_array(points_array, equal_distance=False): """ calculate the positional array object. :param points_array: :param equal_distance: <bool> calculate the equal distance of CV's :return: """ m_array = OpenMaya.MPointArray() if equal_distance: array_length = len(points_array) for idx, point in enumerate(points_array): if idx == 0: m_array.append(OpenMaya.MPoint(*point)) m_array.append(OpenMaya.MPoint(*point)) elif idx >= 1 and idx != array_length - 1: prev_p, cur_p, next_p = list_scanner(points_array, idx) cur_v = math_utils.Vector(*cur_p) prev_v = math_utils.Vector(*prev_p) new_vec = math_utils.Vector(cur_v - prev_v) new_vec = math_utils.Vector(new_vec * 0.5) new_vec = math_utils.Vector(prev_v + new_vec) m_array.append(OpenMaya.MPoint(*new_vec.position)) elif idx == array_length - 1: prev_p, cur_p, next_p = list_scanner(points_array, idx) prev_v = math_utils.Vector(*prev_p) next_v = math_utils.Vector(*next_p) new_vec = math_utils.Vector(next_v - prev_v) new_vec = math_utils.Vector(new_vec * 0.5) new_vec = math_utils.Vector(prev_v + new_vec) # add two points in the same spot m_array.append(OpenMaya.MPoint(*new_vec.position)) m_array.append(OpenMaya.MPoint(*point)) else: for idx, point in enumerate(points_array): if idx == 1: prev_p, cur_p, next_p = list_scanner(points_array, idx) cur_v = math_utils.Vector(*cur_p) prev_v = math_utils.Vector(*prev_p) new_vec = math_utils.Vector(cur_v - prev_v) new_vec = math_utils.Vector(new_vec * 0.5) new_vec = math_utils.Vector(prev_v + new_vec) m_array.append(OpenMaya.MPoint(*new_vec.position)) elif idx == len(points_array) - 1: prev_p, cur_p, next_p = list_scanner(points_array, idx) prev_v = math_utils.Vector(*prev_p) next_v = math_utils.Vector(*next_p) new_vec = math_utils.Vector(next_v - prev_v) new_vec = math_utils.Vector(new_vec * 0.5) new_vec = math_utils.Vector(prev_v + new_vec) m_array.append(OpenMaya.MPoint(*new_vec.position)) m_array.append(OpenMaya.MPoint(*point)) return m_array
So above is just a point array collector that recalculates positions from an existing array of positions: Like selected locators or joints. Preferably at world-space co-ordinates. We then take these recalculated positional array into the OpenMaya.MFnNurbsCurve.create function. I wrote this create_curve_from_points function below that uses this:
def create_curve_from_points(points_array, degree=2, curve_name="", equal_cv_positions=False): """ create a nurbs curve from points. :param points_array: <tuple> positional points array. :param degree: <int> curve degree. :param curve_name: <str> the name of the curve to create. :param equal_cv_positions: <bool> if True create CV's at equal positions. :return: <str> maya curve name. """ knot_length = len(points_array) knot_array = get_knot_sequence(knot_length, degree) m_point_array = get_point_array(points_array, equal_distance=equal_cv_positions) # curve_data = OpenMaya.MFnNurbsCurveData().create() curve_fn = OpenMaya.MFnNurbsCurve() curve_fn.create(m_point_array, knot_array, degree, OpenMaya.MFnNurbsCurve.kOpen, False, False) m_path = OpenMaya.MDagPath() curve_fn.getPath(m_path) if curve_name: parent_obj = object_utils.get_parent_obj(m_path.partialPathName())[0] object_utils.rename_node(parent_obj, curve_name) return curve_name return curve_fn.name()
In the function above, there is a boolean parameter: equal_cv_positions. The default is False. The result of this is creating CV’s at their locator’s positions, like so:
![](https://i0.wp.com/gaidachevrigs.com/wp-content/uploads/2020/03/MFnCreateCurve.gif?resize=525%2C473&ssl=1)
And if the equal_cv_positions is set to True, this is the result:
![](https://i0.wp.com/gaidachevrigs.com/wp-content/uploads/2020/03/MFnCreateCurve1.gif?resize=525%2C473&ssl=1)
As you can see, this utility tool is going to become immediately useful. You could already guess at plans use this already!