Fix motion path lattice twist in Maya

#1

I need to place a bunch of object copies along the mesh edge loop (to model stitches). So I suppose the “attach to motion path” with “follow path object” is a potentially a good solution for that. Now I am trying to find a manual way to create an automatic tool for that later.

In practice, the lattice is twisted randomly and produce unusable results (I am using World Up set to Normal).

As far as I understand that is caused by messed curve normals. Is there a way to fix this? There is a solution for curve normals in Houdini, but I am not sure if the normals is a reason and how to deal with curve normals in Maya if it is…

#2

You can try this, maybe it will help .

https://berniebernie.fr/wiki/Maya_Python#No-flip_flow_motion_path_object_using_curve_normals

#3

Hi, Ihor,
Thanks for the reply, but the link does not work currently…

#4

Hello,

If I had to place things along a curve on a mesh I would create a curve from the edge loops.
From this curve you can query evenly spaced positions and from those positions you can query the normal on the mesh. This normal and the curve tangent on that position can then be used to generate a rotation.

#5

Hello, Joosten!
Can you explain a bit more in depth, please?

You are not supposing to use motionPath with lattice, correct? So the stitches would be only rotated, but not deformed? I am looking for a solution with the deformation of each stitch.

Also, how can I get evenly spaced positions from the curve? And how can I query a mesh normal from a certain position in space?

#6

Sorry, I must have misunderstood. I was under the assumption you’d be placing x amount of duplicates along the curve.

Principle still applies I think even with a lattice. You would just position and rotate a lattice point based on the point and normal.

If you want the stitches to be applied on a deforming mesh you can create follicles on the mesh. In that case all you need is the closest UV point of the position on the curve. This follicle can then drive a cluster that controls the lattice points of a row.

You can use the pointOnCurve command to query the position at a parameter. If you turn on percentage the parameter value is between 0 and 1. Incremental values going from 0 - 1 will give you evenly spaced positions on a curve.
https://download.autodesk.com/global/docs/maya2014/en_us/CommandsPython/pointOnCurve.html

Or use the maya API.
https://download.autodesk.com/us/maya/2011help/API/class_m_fn_nurbs_curve.html
Looking at the getPointAtParam function.

For the closest UV point you will need to use the maya API.
https://download.autodesk.com/us/maya/2011help/API/class_m_fn_mesh.html
Looking at the getUVAtPoint function.

1 Like
#7

Right, I am placing x amount of duplicates along the curve. The mesh is not deforming, it’s static, but I need to deform copied objects (so they replicate the curvature of the mesh ideally). That’s why I use motionPath - it can build a lattice around the curve with “Follow Path” constraint tool.

Maybe there is another way how I can create a lattice using surface normals and tangents… Will research this topic.

#8

the lattice itself would get created as normal. But you would position it’s rows, using the points and normals you queried from the curve. This will place your stitches along the curve. Is your plan to also deform the individual stitches to be wrapped around the mesh?

#9

This is what I am thinking about… If I will go with placing individual stitches along the curve without Motion Path I have no idea how to create a lattice (either for all combined stitches or for each stitch individually) around the curve.

#10

The curve you generate will have a length. So if you want to place all stitches at once you can generate a straight strip of stitches that is the same length as your curve. You can then create a lattice around all of those stitches. You can create divisions on your lattice based on the length of the curve and the amount of stitches.

For example if you have 5 lattice rows. You can split up the points and normals you query on the curve based on increments of 0.25. You query curve parameter 0, 0.25, 0.5, 0.75 and 1. You have created clusters for each of the rows on your lattice. You can translate and rotate those clusters based on your curve parameter position and normal.

1 Like
#11

Sounds like a plan, thank you, Joosten!

#12

I hope that will do the trick. Another more advanced solution would be to use a radial basis function to place the stitches on a vertex level. If you would go that route all you have to do is generate a curve the rest is just code to set the vertices positions directly.

1 Like
#13

Never heard about it… Any links?

#14

I have a 10 units curve, but the position at the parameter is confusing, I thought it should be 0.0, 0.1, 0.2, 0.3 etc

I suppose this happens because of uneven points location and rebuilding will fix it, but rebuilding curve also change it shape dramatically, so its not an option.

#15

In that case you can use the API. Here is a snippet that will give you evenly spaced points on a curve

from maya import OpenMaya

node = "curve1"
num = 10

selectionList = OpenMaya.MSelectionList()
selectionList.add(node)
dag = OpenMaya.MDagPath()
selectionList.getDagPath(0, dag)

c = OpenMaya.MFnNurbsCurve(dag)
p = OpenMaya.MPoint()

points = []
length = c.length()
increment = 1.0 / (num - 1)

for i in range(num):
    parameter = c.findParamFromLength(length * increment * i)
    c.getPointAtParam(parameter, p)
    
    points.append((p.x, p.y, p.z))
    
print points
1 Like
#16

Why in increment you are subtracting 1 from the number of points (increment = 1.0 / (num - 1))?

If I use increment = 1.0 /num I get expected results (using round here to get rid of numbers like -1.0000001909139464):
[(0.0, 0.0, 0.0), (0.0, 0.0, -1.0), (0.0, 0.0, -2.0), (0.0, 0.0, -3.0), (0.0, 0.0, -4.0), (0.0, 0.0, -5.0), (0.0, 0.0, -6.0), (0.0, 0.0, -7.0), (0.0, 0.0, -8.0), (0.0, 0.0, -9.0)]

#17

Don’t you want a point at the end of the curve as well?

#18

If I have a lattice (S=10, T=2, U=2), how can I get 4 lattice points for each of S divisions to create 10 clusters?

UPD

lattice = pm.PyNode('ffd2Lattice')

numberOfRowsS = lattice.sDivisions.get()

for i in range(numberOfRowsS):
    pm.cluster(lattice.pt[i][0:1][0], lattice.pt[i][0:1][1])
#19

Here what I have for now from left to right: source curve, test arrow object cloned along the curve and lattice deformed with clusters (and it is obviously wrong)

The coordinates of each cluster-arrow pair are the same but they located in space differently

Any thoughts on how to fix it?

#20

Ok, since the issue was that each cluster was away from the origin I got some sort of double transformations. So before creating clusters I just scale lattice to zero on the X axis, then create clusters and move them to a proper position on the curve.