MFnNurbsCurve closestPoint issue C++

223 views
Skip to first unread message

Emre Tekinalp

unread,
Apr 20, 2015, 4:33:30 AM4/20/15
to python_in...@googlegroups.com
Hello everybody,

I know this is mostly a Python forum, but I'm currently writing in C++ a deformer,
dealing with curves yaay, hopefully it is ok nonetheless, otherwise I come up with a python api example...
I have also looked through the forum and could find just a MFnMesh.closestPoint issue, which does not really help me unfortunately.

My maya setup is as follows:
- I have an ep curve degree=3
- I want to affect a polyCylinder with the curve, like the wireTool
- As a current idea, one of the steps to achieve that is to get the closestPoint and param on the curve for each Vertex on my polyCylinder.
- For that I use MFnNurbsCurve closestPoint, but when I'm cout position and param values,
  they are mostly zeroed out and when I'm in component mode selecting the vertices of the mesh and move them down in ty
  I get a bunch of value changes, but only when I'm less then 0, everything above stays 0 (position and param values)
- Here is the code:


// Inside the deform method

   
//Get the closestPoint and param on the curve from each vertex
   
MFnNurbsCurve fnCurve(oCurve); //Assume we have the MObject of the curve already
   
double param;
   
MPoint position;

   
for (;! iter.isDone(); iter.next())
   
{
       
//Helper method to retrieve/store the position and param value on the curve
        getClosestPoint
(fnCurve, iter.position(), position, param);
        cout
<< "index: " << iter.index() << " point: " << position.x << " " << position.y << " " << position.z << " param: " << param << endl;
   
}

void Curve::getClosestPoint(MFnNurbsCurve& fnCurve, MPoint inPosition, MPoint& position, double& param)
{
    position
= fnCurve.closestPoint(inPosition, &param, 0.0, MSpace::kWorld);
}




This is basically a part from the closestPoint/TangentAndDistance.cpp source file.
But for any kind of reason, I don't get proper values... am I missing something?

Thanks in advance!
Emre

Justin Israel

unread,
Apr 20, 2015, 6:04:48 AM4/20/15
to python_in...@googlegroups.com
Could it be a problem that you are getting the kObject position as the default return value, from the iterator, and using it in a kWorld operation in the closestPoint() call?


Does it help if you call it like:

    iter.position(MSpace::kWorld)

That is just a guess, as it is the only thing standing out to me. Maybe someone who does more plugin dev will spot something more specific. 

Justin


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/ca5a52a6-b4a0-47d0-ae65-675112ece94a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Janos Hunyadi

unread,
Apr 20, 2015, 7:33:03 AM4/20/15
to python_in...@googlegroups.com
Lets say I want 10 equally spaced out points on the curve, this is how I usually do it:

int m_numDup = 10;

MFnNurbsCurve fnCurve(oCurve);
double length = fnCurve.length();
MPoint p;
for (int i=0; i <= m_numDup; i++){
MPoint p;
double param = fnCurve.findParamFromLength(i* ( (1.0 / float(m_numDup))*length) );
fnCurve.getPointAtParam(param, p, MSpace::kWorld );

sivanny.s...@gmail.com

unread,
Apr 20, 2015, 5:38:21 PM4/20/15
to python_in...@googlegroups.com
I ran into a very similar problem with MFnMesh:: getPointAtUV a few months ago.

The solution in my case was to use the MDagPath constructor instead of the MObject one for your MFn* class. Apparently, functions that require a dag path won't actually return an error if you used the other constructor to build your MFn* object. They just fail silently.

I logged a bug for the getPointAtUV issue. If this turns out to be a similar thing, I think you should log it. Autodesk needs to know how painful this is for customers. Maya's API should either return an error, or use the first path to an object under the covers. In fact, pretty much anything other than failing silently would have been nice.

Sivanny

Emre Tekinalp

unread,
Apr 21, 2015, 3:53:27 PM4/21/15
to python_in...@googlegroups.com
Hello Justin,

thank you for the feedback. I have already checked that out, unfortunately I received the same results.
When I was checking the docs, it was written that an iter.position(MSpace::kWorld) specification is
giving you an invalidParameter. Under status code -> MS::kInvalidParameter Cannot do world space transform.

But yeah it is strange, what I did was creating 3 position inputAttributes as doubles.
And when I'm populating/storing the inputValues of them in a MPoint, it is giving me the correct parameter value from the closestPoint, so it's working...
But this will not really help me, because I want to grab the vertex position of the mesh, otherwise I would need
to create an array of inputAttributes storing the vertex positions of the mesh, but that it is ridiculous...

I will have to do more tests and researches how to solve that.

Well nonetheless, thanks for the help Sirrrrr! :)

Cheerio
Emre

Emre Tekinalp

unread,
Apr 21, 2015, 4:03:25 PM4/21/15
to python_in...@googlegroups.com
Hello Janos,

thanks for the feedback, I have to check it out tonight when I'm home honestly, if this could work, but I assume (correct me if I'm wrong),
the point you are retrieving the param from needs to be on the curve right? As you've said it 'equally spaced points ON the curve'?
Would it not otherwise return you a null or something if it's not on the curve?

I'm not 100% sure, I have to check it out.

Thanks Sirrrr
Emre

Emre Tekinalp

unread,
Apr 21, 2015, 4:13:50 PM4/21/15
to python_in...@googlegroups.com
Hello Sivanny,

it is interesting I thought that this could be a solution as well,
so I tried out the MDagPath constructor instead of the MObject.
Turned out that it is giving me still wrong values.

The interesting part of that is, that I was basically using the same code as in the maya api examples,
because in one of those closePointOnCurve.cpp files they are using the MDagPath constructor instead of the MObject.

But as I responded to Justin in the previous note, I created the 3 inputAttributes as doubles and when playing around
with those values and printing them out, I retrieved the correct param values along the curve.

I have to do more investigations about that.
Thanks Sivanny!

Cheerio
Emre

Janos Hunyadi

unread,
Apr 22, 2015, 2:41:23 PM4/22/15
to python_in...@googlegroups.com
That`s why I'm dividing 1.0 with the length of the curve. So I'll get a value between 1-0 param on the curve. So its always on the curve. 0 will be the start and 1 will be the end of the curve.
At least that's how I usually do it.

Greets,
J

Emre Tekinalp

unread,
Apr 23, 2015, 4:06:20 AM4/23/15
to python_in...@googlegroups.com
Hello everybody,

thanks for your answer Janos that's how I'm calculating as well.
But in this case my issue was a little bit different.

Finally, I found the solution, I want to share with you guys and it is so easy (I realize that it has been a long time ago since I was dealing with deformers XD).

Due to the fact that iter.position() does not like MSpace::kWorld, we have to make sure of course to multiply with the worldMatrix of the deformed mesh's transform...
That explains why I got weird values when translating the mesh in ty. The iter.position() gave me objectspace related values...

So now everything works as it should. As a recap here is the code from above with the proper fix:


// Inside the deform method

   
//Get the closestPoint and param on the curve from each vertex

    //Get inMatrix attribute value as matrix
    MMatrix mMatrix = data.inputValue(aInMatrix, &status).asMatrix();
    CHECK_MSTATUS_AND_RETURN_IT(status);

   
MFnNurbsCurve fnCurve(oCurve); //Assume we have the MObject of the curve already

   
double param;
   
MPoint position;

   
for (;! iter.isDone(); iter.next())
   
{
       
//Helper method to retrieve/store the position and param value on the curve

        getClosestPoint
(fnCurve, iter.position() * mMatrix, position, param);

        cout
<< "index: " << iter.index() << " point: " << position.x << " " << position.y << " " << position.z << " param: " << param << endl;
   
}

void Curve::getClosestPoint(MFnNurbsCurve& fnCurve, MPoint inPosition, MPoint& position, double& param)
{
    position
= fnCurve.closestPoint(inPosition, &param, 0.0, MSpace::kWorld);
}



Thanks guys for the thoughts and help, much appreciated!

Cheerio
Emre
Reply all
Reply to author
Forward
0 new messages