MMeshIntersector: Getting world position / matrix of point in object space

Visto 1.131 veces
Saltar al primer mensaje no leído

igo rov

no leída,
31 jul 2018, 3:53:1931/7/18
a Python Programming for Autodesk Maya
Hi,

I utilized the MMeshintersector.getClosestPoint()  to get closest point on a cube. my problem is, that I can`t make use of it (e.g.  set the world position of a locator) because its in local space.

- MMeshIntersector.getClosestPoint gives me a MPointOnMesh
- MPointOnMesh.point gives me a MFloatPoint

I have less knowledge of Matrix, I guess if i would have a child matrix I could multiply with the parent. Her is the full code:


import maya.api.OpenMaya as om2

selList
= om2.MGlobal.getActiveSelectionList()
dag
= selList.getDagPath(0)

matr
= dag.inclusiveMatrix()

mesh
= dag.child(0)
meshIntersect
= om2.MMeshIntersector()
meshIntersect
.create(mesh)  # documentation says, mesh and matrix as parametres, ...
                           
# but matrix throws me an error, without Matrix it works I guess

selLoc
= om2.MSelectionList()
selLoc
.add("locator1")
dagLoc
= selLoc.getDagPath(0)
trLoc
= om2.MFnTransform(dagLoc)
vec
= trLoc.translation(4)

point
= om2.MPoint(vec)
pOnMesh
= meshIntersect.getClosestPoint(point,1000)
pos3d
= pOnMesh.point #this gives the local translation of the mesh`s transform as MFloatPoint()

# the following is kind of a mess... trying to get the world position of the point in object space. But it gives me wrong results

XVal = pos3d.x
YVal = pos3d.y
ZVal = pos3d.z

childMatr
= om2.MMatrix()
childMatr
.setToIdentity()
childMatr
.setElement(3,0,XVal)
childMatr
.setElement(3,1,YVal)
childMatr
.setElement(3,2,ZVal)
worldM
= childMatr * matr

targetX
= worldM.getElement(3,0)
targetY
= worldM.getElement(3,1)
targetZ
= worldM.getElement(3,2)
newVec
= om2.MVector(targetX, targetY, targetZ)


selLoc2
= om2.MSelectionList()
selLoc2
.add("locator2")
dagLoc2
= selLoc2.getDagPath(0)
trLoc2
= om2.MFnTransform(dagLoc2)
trLoc2
.setTranslation(newVec, 4)



Michael Boon

no leída,
31 jul 2018, 20:46:3231/7/18
a Python Programming for Autodesk Maya
I haven't tested this code, but I think it should be a simple matter of multiplying the point by the mesh's transform. Something like:
node = om.MFnDagNode(dag)
nodeTransform = loc.transformationMatrix()
worldPos = pos3d * nodeTransform

igo rov

no leída,
1 ago 2018, 8:01:141/8/18
a python_in...@googlegroups.com
hi thanks,

I thought I did this with "worldM = childMatr * matr". But I first tried to construct a matrix from "pos3d"  in order to multiply the matrix.

The code I posted, works somehow, but not what I expect: the locator jumps to a exposed point on the cube, but not on the nearest point to locator2

--
You received this message because you are subscribed to a topic in the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/python_inside_maya/zGdhBD6SuUE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to python_inside_maya+unsub...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/4c11c70e-d13b-4931-9a21-ca1262cbd6f7%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

mmeshIntersector.PNG

Luiz Amaral

no leída,
1 ago 2018, 18:35:051/8/18
a Python Programming for Autodesk Maya
Hey there,

“ ‘Point’ Specifies the location for which to evaluate the closest point on the mesh. `point' is transformed using the matrix parameter passed to the create() method, so for example if your matrix maps world to object space, then `point' should be specified in world space.”

You should either pass the cube’s world matrix on creation or pass the point localized to the cube’s space on get closest point.

Since you created the MMeshIntercector without passing a matrix to it the get closest point function expects a localized position.

That’s why you are getting a “random” point instead of the closest point to locator2.

If you pass the cube’s world matrix to the create just multiply the result of the get closest point by the same matrix and your locator will snap to the expected place.

Or you can keep create the way it is and multiply the point by the inverse of the cube’s world matrix before passing it to the get closest point and then multiply the result by the world matrix again.

Cheers,

Luiz

igo rov

no leída,
1 ago 2018, 18:44:531/8/18
a python_in...@googlegroups.com
Hi,
as for the missing Matrix parameter, there is this thread: https://groups.google.com/forum/#!topic/python_inside_maya/axX7W8imeEU

I have the same problems as described there, if I pass the matrix I will get this error: More keyword list entries (4) than format specifiers (2)

But you are right, there has to be a Matrix parameter as the documentation says:.....
then the matrix passed to create() should provide the mapping
from world space to the mesh's object space.

So for me the MMeshIntersector is not working....

--
You received this message because you are subscribed to a topic in the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/python_inside_maya/zGdhBD6SuUE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to python_inside_maya+unsub...@googlegroups.com.

igo rov

no leída,
1 ago 2018, 19:20:221/8/18
a python_in...@googlegroups.com
...I tried what you wrote in your last sentence with inverse matrix, but may be its to late, I'm getting wrong results. I will try again tomorow, thanks

2018-08-02 0:44 GMT+02:00 igo rov <igor...@gmail.com>:
Hi,
as for the missing Matrix parameter, there is this thread: https://groups.google.com/forum/#!topic/python_inside_maya/axX7W8imeEU

I have the same problems as described there, if I pass the matrix I will get this error: More keyword list entries (4) than format specifiers (2)

But you are right, there has to be a Matrix parameter as the documentation says:.....
then the matrix passed to create() should provide the mapping
from world space to the mesh's object space.

So for me the MMeshIntersector is not working....
2018-08-01 23:47 GMT+02:00 Luiz Amaral <amara...@gmail.com>:
Hey there,

“ ‘Point’ Specifies the location for which to evaluate the closest point on the mesh. `point' is transformed using the matrix parameter passed to the create() method, so for example if your matrix maps world to object space, then `point' should be specified in world space.”

You should either pass the cube’s world matrix on creation or pass the point localized to the cube’s space on get closest point.

Since you created the MMeshIntercector without passing a matrix to it the get closest point function expects a localized position.

That’s why you are getting a “random” point instead of the closest point to locator2.

If you pass the cube’s world matrix to the create just multiply the result of the get closest point by the same matrix and your locator will snap to the expected place.

Or you can keep create the way it is and multiply the point by the inverse of the cube’s world matrix before passing it to the get closest point and then multiply the result by the world matrix again.

Cheers,

Luiz

--
You received this message because you are subscribed to a topic in the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/python_inside_maya/zGdhBD6SuUE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to python_inside_maya+unsubscribe@googlegroups.com.

Luiz Amaral

no leída,
1 ago 2018, 20:13:271/8/18
a Python Programming for Autodesk Maya
Try this

matr = om2.MMatrix(dag.inclusiveMatrix())
meshIntersect.create(mesh, matr)

Luiz Amaral

no leída,
1 ago 2018, 20:19:201/8/18
a Python Programming for Autodesk Maya
You should at least pass the identity matrix like this

meshIntersect.create(mesh, om2.MMatrix.identity)

igo rov

no leída,
2 ago 2018, 2:35:522/8/18
a Python Programming for Autodesk Maya
Can you execute this:

import maya.api.OpenMaya as om2

selList
= om2.MGlobal.getActiveSelectionList()
dag
= selList.getDagPath(0)
matr
= dag.inclusiveMatrix()
mesh
= dag.child(0)
meshIntersect
= om2.MMeshIntersector()

meshIntersect
.create(mesh, matr)


I get an error, because it won`t accept the "matr" argument

Luiz Amaral

no leída,
2 ago 2018, 12:29:152/8/18
a Python Programming for Autodesk Maya
Try this

meshIntersect.create(mesh, om2.MMatrix(matr))

igo rov

no leída,
2 ago 2018, 13:26:502/8/18
a Python Programming for Autodesk Maya
I get the same error

Luiz Amaral

no leída,
2 ago 2018, 15:34:562/8/18
a Python Programming for Autodesk Maya
OK I’m out of ideas now :/

Cedric Bazillou

no leída,
2 ago 2018, 19:33:082/8/18
a Python Programming for Autodesk Maya
Hi guys ,
normally by design the closest point value returned by the intersector is in object space

in the function closestPointCmd::createDisplay( MPointOnMesh& info, MMatrix& matrix )
we go from local to worldspace by applying the mesh parent transform ( and its what is used as well for the matrix initialization.) is quite horrible that they labelled a local point as world point though..

i would as well stay as far as possible from the OpenMaya 2 layer if i can as you will soon see some hidden bugs and only 30 percent of the function are exposed ( dont concern yourself with pythonic argument as you will need to convert your code to c++ if your are serious about your work)

Luiz Amaral

no leída,
3 ago 2018, 9:30:253/8/18
a Python Programming for Autodesk Maya
Yeah good one! Try with the api 1.0

Luiz Amaral

no leída,
3 ago 2018, 9:33:233/8/18
a Python Programming for Autodesk Maya

import maya.openmaya as om

igo rov

no leída,
3 ago 2018, 16:22:313/8/18
a Python Programming for Autodesk Maya
Hi again,

I don`t know how much sense this code still makes, however for me its for learning purposes and for me its one step towards my goal to learn c++ api. Especially converting between vectors, MFloatPoint and Matrix type might be horrible code...but I didn*t find a more direct way.....at least it works for me.
If you have some hints for me, how to do things more clever, please don`t hesitate

import maya.OpenMaya as om

selList
= om.MSelectionList()
selList
.add("pCube1")
dagCube
= om.MDagPath()
selList
.getDagPath(0, dagCube)
mesh
= dagCube.child(0)
trFn
= om.MFnTransform(dagCube)
matrCube
= trFn.transformationMatrix()
######
mesh
.apiTypeStr() # should be kMesh
######
intersector
= om.MMeshIntersector()
intersector
.create(mesh, matrCube) # no error in API 1.0...Yeah ;)

selListLoc1
= om.MSelectionList()
selListLoc1
.add("locator1")
dagLoc1
= om.MDagPath()
selListLoc1
.getDagPath(0, dagLoc1)
trFnLoc1
= om.MFnTransform(dagLoc1)
vecLoc1
= trFnLoc1.translation(4)
pointLoc1
= om.MPoint(vecLoc1.x, vecLoc1.y, vecLoc1.z)
mPointOnMesh
= om.MPointOnMesh()
intersector
.getClosestPoint(pointLoc1,mPointOnMesh, 1000)
resultPoint
= mPointOnMesh.getPoint()

# first I create vector
resultVector
= om.MVector(resultPoint.x, resultPoint.y,resultPoint.z)

# then I convert to matrix
matrTrans
= om.MTransformationMatrix()
matrTrans
.setTranslation(resultVector,4)
localMatrix
= matrTrans.asMatrix(1)
# this is the important step to get the world matrix, multiply child/local with the parent Matrix
worldMatr
= localMatrix*matrCube
worldMatrTrans
= om.MTransformationMatrix(worldMatr)

selListLoc2
= om.MSelectionList()
selListLoc2
.add("locator2")
dagLoc2
= om.MDagPath()
selListLoc2
.getDagPath(0, dagLoc2)
trFnLoc2
= om.MFnTransform(dagLoc2)
trFnLoc2
.set(worldMatrTrans)

Luiz Amaral

no leída,
4 ago 2018, 12:08:174/8/18
a Python Programming for Autodesk Maya
Hey igo, happy to see you solved the puzzle! Its such a great feeling to have our tools working. Specially after some struggle ;)

Maya API can be tricky sometimes.

I highly recomend Chad Vernon’s courses on cgcircuit for learning c++ API

https://www.cgcircuit.com/

http://www.chadvernon.com/blog/resources/maya-api-programming/

Good luck and enjoy the ride :D

igo rov

no leída,
4 ago 2018, 14:37:484/8/18
a python_in...@googlegroups.com
...yes thats true, and I wasnt`t expecting that there could be a bug in the API :)  Deciding for api 1.0 or 2.0 ist not too easy.
I know the courses of cgcircuit, but for python. Hopefully taking the next step to c++ won`t bee too hard for somebody coming more from the artist side of maya. Though I will stick with python also, and defintely come back here soon.

--
You received this message because you are subscribed to a topic in the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/python_inside_maya/zGdhBD6SuUE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to python_inside_maya+unsub...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/02874409-af3c-4fc9-afa2-083f3cf40a95%40googlegroups.com.

Cedric Bazillou

no leída,
4 ago 2018, 16:38:274/8/18
a Python Programming for Autodesk Maya
tips wise maybe just put your code into a function so the garbage collector can clean up intermediate elements?
Responder a todos
Responder al autor
Reenviar
0 mensajes nuevos