It's not possible to give you my node because is a property of QuanticDream. But it's possible to give you an exemple. :)
-- 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 [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/130fb12f-ee46-4d61-8ef3-d5549408cd87%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
# ========================================================
# Import Modules
# ========================================================
from maya import OpenMaya, OpenMayaMPx
# ========================================================
# Math Utils Node
# ========================================================
class RDIntersect(OpenMayaMPx.MPxNode):
"""
!@Brief Basic implementation of maya intersection for mesh (MFnMesh)
My NodeId definition for maya plugin
# # 1 -- 18 -- R
# # 2 -- 4 -- D
# # 3 -- Type -- 0 | DependNode - 1 | LocatorNode - 2 | DeformNode
# # 4 -- Serie -- NN
# # ex: 0x184001
"""
# Static Variables
kPluginNode = "rdIntersect"
kPluginNodeID = OpenMaya.MTypeId(0x185134)
kPluginNodeType = OpenMayaMPx.MPxNode.kDependNode
INPUT_GEO = OpenMaya.MObject()
RAY_ORIGIN = OpenMaya.MObject()
RAY_DIR = OpenMaya.MObject()
BOTH_SIDE = OpenMaya.MObject()
MAX_DIST = OpenMaya.MObject()
NO_INTERSECT = OpenMaya.MObject()
HIT_POINT = OpenMaya.MObject()
class _Hit(object):
mfp_hit_point = OpenMaya.MFloatPoint()
f_distance = 0.0
i_hit_face = 0
b_hit = False
# ====================================================
# Init
# ====================================================
@classmethod
def creator(cls):
return OpenMayaMPx.asMPxPtr(cls())
def __init__(self):
super(RDIntersect, self).__init__()
# Store last hit point, last distance and last direction of last hit
# If you have intersect and next frame not
# You keep this data for create arbitrary point position
self._mfp_last_hit_point = OpenMaya.MFloatPoint()
self._mv_last_ray_dir = OpenMaya.MFloatVector()
self._f_last_distance = 0.0
self._i_last_hit_face = 0
@classmethod
def initializer(cls):
a_in_attributes = list()
a_out_attributes = list()
# ================================================
# Input attributes
# Shape input
input_geo_attr = OpenMaya.MFnGenericAttribute()
cls.INPUT_GEO = input_geo_attr.create("inputGeom", "ing")
input_geo_attr.setKeyable(False)
input_geo_attr.setStorable(True)
input_geo_attr.addDataAccept(OpenMaya.MFnData.kMesh)
input_geo_attr.addDataAccept(OpenMaya.MFnData.kNurbsSurface)
a_in_attributes.append(cls.INPUT_GEO)
# Ray data
# WARNING: createPoint of MFnNumericAttribute create MFloatVector
# for create MVector use this prototype of MFnNumericAttribute
# create (
# const MString &fullName, const MString &briefName,
# const MObject &child1, const MObject &child2, const MObject &child3=MObject::kNullObj,
# MStatus *ReturnStatus=NULL
# )
ray_origin_attr = OpenMaya.MFnNumericAttribute()
cls.RAY_ORIGIN = ray_origin_attr.createPoint("rayOrigin", "ro")
ray_origin_attr.setKeyable(True)
ray_origin_attr.setStorable(True)
a_in_attributes.append(cls.RAY_ORIGIN)
ray_origin_attr = OpenMaya.MFnNumericAttribute()
cls.RAY_DIR = ray_origin_attr.createPoint("rayDirection", "rd")
ray_origin_attr.setKeyable(True)
ray_origin_attr.setStorable(True)
a_in_attributes.append(cls.RAY_DIR)
# Intersect Options
both_side_attr = OpenMaya.MFnNumericAttribute()
cls.BOTH_SIDE = both_side_attr.create("bothSide", "bs", OpenMaya.MFnNumericData.kBoolean, True)
both_side_attr.setKeyable(True)
both_side_attr.setStorable(True)
a_in_attributes.append(cls.BOTH_SIDE)
max_dist_attr = OpenMaya.MFnNumericAttribute()
cls.MAX_DIST = max_dist_attr.create("maxDistance", "md", OpenMaya.MFnNumericData.kDouble, 1000.0)
max_dist_attr.setMin(1e-12)
max_dist_attr.setKeyable(True)
max_dist_attr.setStorable(True)
a_in_attributes.append(cls.MAX_DIST)
no_intersect_attr = OpenMaya.MFnEnumAttribute()
cls.NO_INTERSECT = no_intersect_attr.create("noIntersect", "ni", 1)
no_intersect_attr.setKeyable(True)
no_intersect_attr.setStorable(True)
no_intersect_attr.addField("Nothing", 0)
no_intersect_attr.addField("KeepLastPos", 1)
no_intersect_attr.addField("KeppLastDist", 2)
a_in_attributes.append(cls.NO_INTERSECT)
# ================================================
# Output attributes
hit_point_attr = OpenMaya.MFnNumericAttribute()
cls.HIT_POINT = hit_point_attr.createPoint("hitPoint", "hp")
hit_point_attr.setKeyable(False)
hit_point_attr.setStorable(False)
a_out_attributes.append(cls.HIT_POINT)
# ToDo
# If you want to calculate hit rotation create rotation attribute or Matrix attribute
# ================================================
# Add attributes
for mo_attribute in (a_in_attributes + a_out_attributes):
cls.addAttribute(mo_attribute)
# ================================================
# Set the attribute dependencies
# https://help.autodesk.com/view/MAYAUL/2018/ENU/?guid=__cpp_ref_class_m_px_node_html
# This method specifies that a particular input attribute affects a specific output attribute.
for mo_out_attr in a_out_attributes:
for mo_in_attr in a_in_attributes:
cls.attributeAffects(mo_in_attr, mo_out_attr)
# ====================================================
# Compute
# ====================================================
def compute(self, plug, data):
# Compute only if plug is output attribute
if plug != self.HIT_POINT:
return
# Get input datas
h_input_geom = data.inputValue(self.INPUT_GEO)
mfv_ray_origin = data.inputValue(self.RAY_ORIGIN).asFloatVector()
mfv_ray_dir = data.inputValue(self.RAY_DIR).asFloatVector()
b_both_side = data.inputValue(self.BOTH_SIDE).asBool()
f_max_distance = data.inputValue(self.MAX_DIST).asDouble()
i_no_intersect = data.inputValue(self.NO_INTERSECT).asShort()
# Get Shape
if h_input_geom.type() not in [OpenMaya.MFnData.kMesh, OpenMaya.MFnData.kNurbsSurface]:
raise Exception("Invalid shape data given. Accepted shape: Mesh, NurbsSurface.")
if h_input_geom.type() == OpenMaya.MFnData.kNurbsSurface:
raise Exception("NurbsSurface intersect not implemented yet.")
mfn_mesh = OpenMaya.MFnMesh(h_input_geom.asMesh())
hit = self._mesh_intersection(mfn_mesh, mfv_ray_origin, mfv_ray_dir, b_both_side, f_max_distance)
# Intersection found
# Store data
if hit.b_hit is True:
self._mfp_last_hit_point = hit.mfp_hit_point
self._mv_last_ray_dir = mfv_ray_dir
self._f_last_distance = hit.f_distance
self._i_last_hit_face = hit.i_hit_face
# No intersect found
# Get last data stored
else:
# Keep last position
if i_no_intersect == 1:
hit.mfp_hit_point = self._mfp_last_hit_point
hit.f_distance = self._f_last_distance
hit.i_hit_face = self._i_last_hit_face
# Keep last distance and calculate new position from distance
if i_no_intersect == 2:
hit.mfp_hit_point = mfv_ray_origin + mfv_ray_dir.normal() * self._f_last_distance
hit.f_distance = self._f_last_distance
hit.i_hit_face = self._i_last_hit_face
# Get output Position
mfv_hit_point = OpenMaya.MFloatVector(hit.mfp_hit_point)
# ToDo
# Get orientation with normal and tangent of polygon from hitFace ID
# ToDo:
# Smooth interpollation between hit point and ray origin if no intersect found
# Output Value
h_hit_point = data.outputValue(self.HIT_POINT)
h_hit_point.setMFloatVector(mfv_hit_point)
h_hit_point.setClean()
# Clean
data.setClean(plug)
# ====================================================
# Misc
# ====================================================
@staticmethod
def _mesh_intersection(mfn_mesh, mfv_ray_origin, mfv_ray_dir, b_both_side, f_max_distance):
"""
!@Brief Get mesh intersection
@type mfn_mesh: OpenMaya.MFnMesh
@param mfn_mesh: MFnMesh for get intersection
@type mfv_ray_origin: OpenMaya.MFloatPoint
@param mfv_ray_origin: Origin of ray intersection
@type mfv_ray_dir: OpenMaya.MFloatVector
@param mfv_ray_dir: Ray direction for intersection
@type b_both_side: bool
@param b_both_side: Set True if you want to check both side of rayDir.
@type f_max_distance: float
@param f_max_distance: Intersection distance tolerence.
@rtype: MFloatPoint, int
@return: Point and face id of intersection. None if no intersection found
"""
hit = RDIntersect._Hit()
# Hit point pointer
mfp_hit_point = OpenMaya.MFloatPoint()
# Face ID pointer
hit_face_su = OpenMaya.MScriptUtil()
hit_face_su.createFromInt(0)
ptr_hit_face = hit_face_su.asIntPtr()
# Other options
f_tolerence = 1e-6
a_face_ids = None
a_tril_ids = None
b_ids_sorted = False
f_hit_ray_param = None
i_hit_triangle = None
f_hit_bary_1 = None
f_hit_bary_2 = None
ms_space = OpenMaya.MSpace.kWorld
# Intersection acceleration by voxelization
# Auto generation of grid
map_accel_param = mfn_mesh.autoUniformGridParams()
# Intersect
b_hit = mfn_mesh.closestIntersection(
OpenMaya.MFloatPoint(mfv_ray_origin),
mfv_ray_dir.normal(),
a_face_ids,
a_tril_ids,
b_ids_sorted,
ms_space,
f_max_distance,
b_both_side,
map_accel_param,
mfp_hit_point,
f_hit_ray_param,
ptr_hit_face,
i_hit_triangle,
f_hit_bary_1,
f_hit_bary_2,
f_tolerence
)
if b_hit is True:
hit.b_hit = True
hit.mfp_hit_point = mfp_hit_point
hit.f_distance = (OpenMaya.MFloatVector(mfp_hit_point) - mfv_ray_origin).length()
hit.i_hit_face = hit_face_su.getInt(ptr_hit_face)
return hit
# ========================================================
# Initialize Plugin
# ========================================================
# load
def initializePlugin(m_object):
plugin = OpenMayaMPx.MFnPlugin(
m_object,
"Intersect Exemple\n\tRemi Deletrain -- [email protected]",
"1.0",
"Any"
)
try:
plugin.registerNode(
RDIntersect.kPluginNode,
RDIntersect.kPluginNodeID,
RDIntersect.creator,
RDIntersect.initializer,
RDIntersect.kPluginNodeType
)
except Exception, err:
print err.message
raise RuntimeError("Failed to register command: %s\n" % RDIntersect.kPluginNode)
# Unload
def uninitializePlugin(m_object):
plugin = OpenMayaMPx.MFnPlugin(m_object)
try:
plugin.deregisterNode(RDIntersect.kPluginNodeID)
except Exception, err:
print err.message
raise RuntimeError("Failed to unregister node: %s\n" % RDIntersect.kPluginNode)
rdIntersectExemple.ma
Description: Binary data
