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 python_inside_maya+unsubscr...@googlegroups.com.
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 -- remi.deletr...@gmail.com",
        "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)

Attachment: rdIntersectExemple.ma
Description: Binary data

Reply via email to