Struggle in single ray tracer in MAYA, need help!

40 views
Skip to first unread message

徐一雄

unread,
Jan 3, 2019, 11:46:39 PM1/3/19
to Python Programming for Autodesk Maya
Hello everyone, i'm a newbee to maya python API.
Recently, I'm struggle in the single ray tracer.
I build a custom MPxNode to compute the hitPoint when the ray hit the sphere. 
The ray is build by 2 locators in space.
If the sphere is at the origin point of the world space, everything seems OK.
But here is the problem:
When I transform the sphere object, e.x translate a little distance. The hitPoint should translate on the sphere but now it doesn't .
I know that when I transform the sphere, the input values of the custom node have't change and compute function doesn't be called.
I have tried that to add a transform attribute to call the compute function but it doesn't work. I think the hitPoint should be calculate by multiply a matrix.
So how can I achieve that when I transform the sphere, the hit point on the sphere also change by the direction of the ray.
Thank you very much.

Here is the code:

import maya.OpenMaya as om
import maya.OpenMayaMPx as ompx

nodeName = 'RayTracer'
nodeID = om.MTypeId(0X100fff)


class MeshIntersectionNode(ompx.MPxNode):
# Class Attrs
# INPUT
Loc_1_Pos = om.MObject()
Loc_2_Pos = om.MObject()

inMesh = om.MObject()

# OUTPUT
Loc_3_Pos = om.MObject()

def __init__(self):
ompx.MPxNode.__init__(self)

def compute(self, plug, dataBlock):
if plug != MeshIntersectionNode.Loc_3_Pos:
return om.kUnknownParameter

locator1Vector = om.MVector(dataBlock.inputValue(MeshIntersectionNode.Loc_1_Pos).asFloatVector())
locator2Vector = om.MVector(dataBlock.inputValue(MeshIntersectionNode.Loc_2_Pos).asFloatVector())
inputMeshObj = dataBlock.inputValue(MeshIntersectionNode.inMesh).asMesh()

direction = om.MFloatVector(locator2Vector - locator1Vector)

sourcePoint = om.MFloatPoint(dataBlock.inputValue(MeshIntersectionNode.Loc_1_Pos).asFloatVector())

inputMeshMFn = om.MFnMesh(inputMeshObj)

hitPoints = om.MFloatPoint()

tolerance = float(0.0)

inputMeshMFn.closestIntersection(sourcePoint, direction, None, None, False, om.MSpace.kWorld,
10000.0, False, None, hitPoints, None, None, None, None, None, tolerance)

outputPoint = dataBlock.outputValue(MeshIntersectionNode.Loc_3_Pos)

if hitPoints[0]:
outputVector = om.MFloatVector(hitPoints.x, hitPoints.y, hitPoints.z)
else:
outputVector = om.MFloatVector(0.0, 0.0, 0.0)

outputPoint.setMFloatVector(outputVector)

dataBlock.setClean(plug)


def nodeCreator():
return ompx.asMPxPtr(MeshIntersectionNode())


def nodeInitializer():
MFnNumericAttr = om.MFnNumericAttribute()
MFnMeshAttribute = om.MFnTypedAttribute()

# create attribute
# input
MeshIntersectionNode.Loc_1_Pos = MFnNumericAttr.createPoint('Locator1Position', 'Loc1Pos')
MFnNumericAttr.setWritable(1)
MFnNumericAttr.setKeyable(1)
MeshIntersectionNode.addAttribute(MeshIntersectionNode.Loc_1_Pos)

MeshIntersectionNode.Loc_2_Pos = MFnNumericAttr.createPoint('Locator2Position', 'Loc2Pos')
MFnNumericAttr.setWritable(1)
MFnNumericAttr.setKeyable(1)
MeshIntersectionNode.addAttribute(MeshIntersectionNode.Loc_2_Pos)

MeshIntersectionNode.inMesh = MFnMeshAttribute.create('inMesh', 'im', om.MFnData.kMesh)
MFnMeshAttribute.setWritable(1)
MFnMeshAttribute.setKeyable(1)
MeshIntersectionNode.addAttribute(MeshIntersectionNode.inMesh)

# output
MeshIntersectionNode.Loc_3_Pos = MFnNumericAttr.createPoint('Locator3Position', 'Loc3Pos')
MFnNumericAttr.setWritable(0)
MFnNumericAttr.setReadable(1)
MeshIntersectionNode.addAttribute(MeshIntersectionNode.Loc_3_Pos)

# make influence
MeshIntersectionNode.attributeAffects(MeshIntersectionNode.Loc_1_Pos, MeshIntersectionNode.Loc_3_Pos)
MeshIntersectionNode.attributeAffects(MeshIntersectionNode.Loc_2_Pos, MeshIntersectionNode.Loc_3_Pos)
MeshIntersectionNode.attributeAffects(MeshIntersectionNode.inMesh, MeshIntersectionNode.Loc_3_Pos)


def initializePlugin(mObj):
mPlugin = ompx.MFnPlugin(mObj, 'Yixiong Xu', '1.0')

try:
mPlugin.registerNode(nodeName, nodeID, nodeCreator, nodeInitializer)
except:
raise RuntimeError
print 'Failed to register node.'


def uninitializePlugin(mObj):
mPlugin = ompx.MFnPlugin(mObj)

try:
mPlugin.deregisterNode(nodeID)
except:
raise RuntimeError
print 'Failed to deregister node.'

Serguei Kalentchouk

unread,
Jan 4, 2019, 10:55:03 AM1/4/19
to python_in...@googlegroups.com
Hi Yixiong,
Are you connecting worldMesh[0] as input for inMesh?

--
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/9002b2ca-1d44-43d7-9f76-b8dcce2455f6%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Message has been deleted

徐一雄

unread,
Jan 4, 2019, 10:33:26 PM1/4/19
to Python Programming for Autodesk Maya
Hello Sir,
I used to connect the 'Out Mesh' to the inMesh.
Just as you said, I change it to worldMesh[0], and it works !!! But I don't know why...
Can you tell me the difference between worldMesh and Out Mesh?
Thank you very much
Yixiong Xu
2019.01.05

在 2019年1月4日星期五 UTC+8下午11:55:03,serguei.k...@gmail.com写道:
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

Serguei Kalentchouk

unread,
Jan 5, 2019, 10:55:58 AM1/5/19
to python_in...@googlegroups.com
Glad to hear that it's working now!

outMesh returns a mesh with vertex coordinates in local space, as if the mesh never moves from the world origin.
wordMesh returns a mesh with vertex coordinates in world coordinates, taking the movement of mesh shape parent transform node (per instance) into account.

Hope that helps understand it.


To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

--
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/c30a5d56-923b-4edc-a361-67bfa721b8a3%40googlegroups.com.

Marcus Ottosson

unread,
Jan 5, 2019, 11:52:56 AM1/5/19
to python_in...@googlegroups.com

wordMesh returns a mesh with vertex coordinates in world coordinates, taking the movement of mesh shape parent transform node (per instance) into account

But does it really?

That seems the logical conclusion, but I’ve never seen that actually be the case.

Here’s an example.

from maya import cmds

transform, generator = cmds.polyCube()
shape = cmds.listRelatives(transform, shapes=True)[0]

clone = cmds.createNode("transform", name="Clone")
mesh = cmds.createNode("mesh", parent=clone)

cmds.connectAttr(shape + ".worldMesh[0]", mesh + ".inMesh")
cmds.move(0, 2, 0, transform)

Apparently, the “clone” (wireframe) isn’t getting the worldspace positions of those vertices.

image.png


Serguei Kalentchouk

unread,
Jan 5, 2019, 12:57:01 PM1/5/19
to python_in...@googlegroups.com
Yes.

You are assuming to know what mesh shape does internally when it reads the data from the inMesh plug.
It might very well be that it gets the mesh points and then transfroms them by the MDataHandle::geometryTransformMatrix() to get the local coordinates.

Another test you can make is constrain a locator to the moved cube in your example using the Point on Poly Constraint.
Note that it uses the worldMesh[0] as input to target, now replace the connection with outMesh instead and observe the difference.

Cheers!


Reply all
Reply to author
Forward
0 new messages