PDA

View Full Version : position update from pointOnCurveInfo


ronviers
03-13-2009, 03:49 PM
I have this script that takes a selection of nurbs curves and distributes them along the path defined by the last item in the selection. In other words, all of the objects selected except the last one will be distributed along the path of the last item in the selection.

string $selectedTransforms[]=`ls -sl`;
string $selectedShapes[]=`ls -g -dag -sl`;
int $numCurves=`size $selectedShapes`-1;
string $intervalRange = `createNode multiplyDivide`;
setAttr .operation 2;//divide
setAttr .input1X 100;
setAttr .input2X ($numCurves-1);
string $intervalMd=`createNode multiplyDivide`;
setAttr .operation 2;//divide
connectAttr -f ($intervalRange+".outputX") ($intervalMd+".input1X");
setAttr .input2X 100;
for ($i=0;$i<$numCurves;$i++)
{
string $summateIntervalMd=`createNode multiplyDivide`;
setAttr .operation 1;//multiply
setAttr .input1X $i;
connectAttr -f ($intervalMd+".outputX") ($summateIntervalMd+".input2X");
string $pociName=`createNode pointOnCurveInfo`;
setAttr .turnOnPercentage 1;
connectAttr -f ($selectedShapes[`size $selectedShapes`-1]+".worldSpace[0]") ($pociName+".inputCurve");
connectAttr -f ($summateIntervalMd+".outputX") ($pociName+".parameter");
connectAttr -f ($pociName+".position") ($selectedTransforms[$i]+".translate");
}

I am having trouble reconciling the way it works, and the way I expect it to work. I need the positions of the objects that are distributed along the path to be updated constantly. So if a cv is moved, which will cause a change in the length of the path, then all of the objects should reposition themselves accordingly. I am sure I am overlooking something obvious, but how can I get all of the object's positions to be updated as the length of the curve is changed by the repositioning of the path's cv's?

Thanks,
Ron

Keilun
03-13-2009, 04:01 PM
If you're planning on remaining in MEL, then you would need to build a scriptJob that would detect when the length of the curve changed, and then rebuild your setup.

Alternately in the API, you would construct a node that would do all of this, which would be able to detect when the curve changed (or if a new object was added to the list), and then subsequently update the placements.

cakesson
03-13-2009, 04:17 PM
I did something similar recently and I solved it by creating a pointOnCurve node for each object attached to the curve and then for each object connect the pointOnCurve nodes ".position X, Y and Z to the objects "translate X, Y and Z.

My only issue with this was that the rotational values were not updated dynamically so I had to write a proc that does that separately on demand.

While I retained this option, the better alternative for me ended up attaching the objects using the motion path (pathAnimation).

ronviers
03-13-2009, 06:13 PM
**** Thanks Keilun,
Hmm. Not sure how to go about this. I guess I could duplicate the path and hide it. Then for the life of the tool, compare the length of the path being edited to the hidden path using the scriptJob. I will give it some thought. Thanks for the assistance.

Thanks cakesson,
I have to write a simple gui so the user can change the vectors for the tangent constraints (not shown) anyway so I will consider adding an on-demand button. The pathAnimation command will not help on this one but I will keep it in mind for the future.

:)

Keilun
03-13-2009, 06:34 PM
You could add a dynamic attribute on the curve to record the last known length of the path. Then when the scriptJob pops, query that value. Might be simpler than duplicating and hiding.

If you don't like dirtying your scene as a result of the process, you could also try building the structure in MEL. Maintaining lists of object to distances. You would need to monitor for other things in this way though (including node renames). This route would probably be easier in Python than MEL.

ronviers
03-14-2009, 02:45 AM
I really liked the idea of monitoring the state of a dynamic length atter with a scriptJob. But now, the only way I have found to get the pointOnCurveInfo nodes to update their positions on the curve, is to rebuild the curve with a different number of spans that's no good.

Does anyone know of a way to force pointOnCurveInfo nodes to reevaluate their positions on a curve?

Thanks,
Ron

Keilun
03-16-2009, 03:38 PM
I think it would probably be best to just monitor the output curve of the curve, rather than the individual pointOnCurveInfo nodes.

Or alternately connect the arcLength node to the curve and monitor that length. Unless I've missed something, I think it should be safe to assume that if the length of the curve changes, each of your points need to be redistributed.

dr.rastaman
03-16-2009, 04:05 PM
What about using the curve as a motion path for your objects? For example:
- create a curve
- create 6 locators
- via 'animate->attach to motion path' stick each of your locators onto the curve. (in the option box turn of 'parametric length')
- then delete the animations on the 'u-value'-parameter
- set the u-values to 0.0, 0.2, 0.4, 0.6, 0.8 and 1.0
- you are done ;)
The locators are now stuck to the curve and reposition themselves when you change your curve. That should be what you wanted or am I missing something?

ronviers
03-16-2009, 06:19 PM
Hi Keilun,

I used an arcLengthDimension node to drive a length atter that I added to the curve. That part worked fine thank you very much. The problem became, once the scriptJob identified a change in the length, how to make my system rebuild itself. I found that I could rebuild the path curve uniform and keeping spans, this causes the pointOnCurveInfo nodes to update their parameter values from the curve, but modifies the shape of the curve - and since this is a modeling tool, that was a problem. I was under pressure to move on to other things, so I did, but since reading dr.rastaman's reply I think I will try again when I get some time this evening.



Thanks dr.rastaman, I am not familiar with motion curves or how to stick things to them so I am really looking forward to trying your method.

I will post back with how it went.

ronviers
03-30-2009, 12:55 AM
I finally got a chance to revisit this little project. All I can say is, wow. Attach to Motion Path and Create Animation Snapshot are excellent tools that will definitely change the way I work. I may have found them myself if they had been named something else. Maya could have made them more shiny by calling them something like Duplicate Along Curve.

Unfortunately, in this case, I think I will still need to use my script because each of the profile curves are different and I have not found a way to distribute a group of curves to a motion path.

I am fine with the way it is working but if there is a way to do it with Attach to Motion Path, then I would like to know how to do it.



Thanks,

Ron


http://picasaweb.google.com/lh/photo/PGR6RvLXGu_S9dL8oHPSNA?feat=directlinkhttp://picasaweb.google.com/lh/photo/PGR6RvLXGu_S9dL8oHPSNA?feat=directlinkhttp://picasaweb.google.com/lh/photo/PGR6RvLXGu_S9dL8oHPSNA?feat=directlink

dr.rastaman
03-30-2009, 02:02 PM
Hi Ron,

it should work with 'attach to motion path'. Let's say you have one path and 5 profile curves. Simply select the first profile curve, shift select the path and click 'attach to motion path'.(uncheck 'parametric' in the option box)
Then select the profile curve again and in the channel box, in the input section, select 'motionPath1'. Select 'U Value', right-click and 'delete selected' to delete the animation on this channel. Repeat these steps for all of your profile curves.
Then set the U-Values of your motion paths according to the number of profile curves you have. (k*(1/n-1))
First one to 0, second to 0.25, third to 0.5, fourth to 0.75 and fifth to 1. That should be exactly what you want...

Cheers ;)

ronviers
03-30-2009, 07:15 PM
Now I see what you mean, unfortunately, even with this method, I still have to rebuild the curve, keeping NumSpans, in order for the profile curve's position information to update. I am probably overlooking something simple, but it's just as well really, because I find it easier to work with the explicit tangent constraints than the controls provided by the Attach to Motion Path. And as long as I build my profiles for the surface loft on z normal and at the origin, it does what I originally intended.
Thanks a lot for sticking with me, I can be very thickheaded at times.


string $selectedTransforms[]=`ls -sl`;
string $selectedShapes[]=`ls -g -dag -sl`;
string $pathTransform=$selectedTransforms[`size $selectedTransforms`-1];
string $pathShape=$selectedShapes[`size $selectedShapes`-1];
int $numCurves=`size $selectedShapes`-1;
string $intervalRange = `createNode multiplyDivide`;
setAttr .operation 2;//divide
setAttr .input1X 100;
setAttr .input2X ($numCurves-1);
string $intervalMd=`createNode multiplyDivide`;
setAttr .operation 2;//divide
connectAttr -f ($intervalRange+".outputX") ($intervalMd+".input1X");
setAttr .input2X 100;
for ($i=0;$i<$numCurves;$i++)
{
string $summateIntervalMd=`createNode multiplyDivide`;
setAttr .operation 1;//multiply
setAttr .input1X $i;
connectAttr -f ($intervalMd+".outputX") ($summateIntervalMd+".input2X");
string $pociName=`createNode pointOnCurveInfo`;
setAttr .turnOnPercentage 1;
connectAttr -f ($pathShape+".worldSpace[0]") ($pociName+".inputCurve");
connectAttr -f ($summateIntervalMd+".outputX") ($pociName+".parameter");
connectAttr -f ($pociName+".position") ($selectedTransforms[$i]+".translate");
}
string $upName[]=`spaceLocator`;
select -cl;
select $selectedTransforms[0];
select - tgl $selectedTransforms[$numCurves-1];
select - tgl $upName[0];
pointConstraint -offset 0 0 0 -weight 1;
for ($i=0;$i<$numCurves;$i++)
{
select -cl ;
select $selectedTransforms[$numCurves];
select -tgl $selectedTransforms[$i];
tangentConstraint -weight 1 -aimVector 0 0 1 -upVector 0 1 0 -worldUpType "object" -worldUpObject $upName[0];
}

CGTalk Moderation
03-30-2009, 07:15 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.