Search code examples
python3dmayacurvenurbs

Creating Nurbs Curve from points in Maya


I'm trying to create a function that takes a list of xyz points and creates a nurbs curve in Autodesk Maya, using python.

To generate the points, I've been grabbing the points from an existing curve that was made manually, using this:

import maya.cmds as cmds
import maya.api.OpenMaya as OpenMaya2

mayaSel = cmds.ls(selection=True)[0]

msel = om2.MSelectionList()
msel.add(mayaSel)
curveMob = msel.getDependNode(0)

curvFn = om2.MFnNurbsCurve(curveMob)
points = om2.MPointArray()

points = curvFn.cvPositions()

pointArray = []


for point in points:
    pointTuple = (point.x, point.y, point.z)
    pointArray.append(pointTuple)
    
print (pointArray)

I then pass the given pointArray to this:

curv = cmds.curve(p=pointArray)

And it is working! The curve is being created - But the ends of the curve seem to to overshoot somehow, making the shape slightly different to the original curve:

Original Curve: IMG

Curve created from the control points of the original curve: IMG

I tried messing with the open/close curve options, and while it does close the curve, I can't find a way to maintain the original shape.

I suspect it maaay have something to do with the knots of the curve? But I'm not too sure, and my knowledge of curve knots is a bit limited. If anyone can point me in the right direction, I would really appreciate it! :)


Solution

  • Probably something to do with the knots yes. It looks as though the original curve was periodic? (i.e. the curve loops back on itself, to form a closed loop), but it looks as though your recreated curve has been created as an open curve type?

    Maya's knots are a little non-standard, but basically if you have a strip of cv's to form a curve that is unconnected (i.e. non-periodic), then the number of knots should be the number of CV's + 2. i.e. the knot vectors will follow this pattern:

    4CVs -> 0, 0, 0, 1, 1, 1
    5CVs -> 0, 0, 0, 1, 2, 2, 2
    6CVs -> 0, 0, 0, 1, 2, 3, 3, 3
    7CVs -> 0, 0, 0, 1, 2, 3, 4, 4, 4
    etc, etc
    

    For periodic curves, you need to set the curve type to be periodic (instead of open, which is the default), and the knot vectors will follow this pattern instead:

    4CVs -> -2, -1, 0, 1, 2, 3
    5CVs -> -2, -1, 0, 1, 2, 3, 4
    6CVs -> -2, -1, 0, 1, 2, 3, 4, 5
    7CVs -> -2, -1, 0, 1, 2, 3, 4, 5, 6
    etc, etc
    

    I am assuming that you are specifying the curves using degree 3 here (i.e. cubic, because higher degrees are not typically all that useful....)

    For completeness, Maya also provides a closed curve type, which also forms a loop, however the continuity is NOT maintained when crossing from the first to last control points.

    I'm assuming that adding the periodic flag will fix this?

    curv = cmds.curve(p=pointArray, periodic=True)