Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Register
    • Login

    Deformer_not_work

    PYTHON Development
    0
    5
    816
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 22/06/2018 at 22:19, xxxxxxxx wrote:

      Hi folks,
      I try to write a deformable plugin. He uses the PSR information of another object to control the position of the point of the deformed object, and the weight of a MAP control point. I have written ----op.Message (c4d.MSG_UPDATE). Why do I have to press "A (redraw)" to see the deformed object?
      My code:

      class test(plugins.ObjectData) :  
        """Spherify Modifier"""  
        def __init__(self) :  
            self.SetOptimizeCache(True)  
        def ModifyObject(self, mod, doc, op, op_mg, mod_mg, lod, flags, thread) :  
            marr = op.GetAllPoints()  
            cl = mod[c4d.OBJECT]  
            clp = cl.GetUp()  
            clm = cl.GetRelMl()  
            clpm = clp.GetMg()  
            vex = mod[c4d.MAP].GetAllHighlevelData()  
            cnt = len(vex)  
            for i in xrange(cnt ) :  
                if vex _:  
                    pos = ~clpm * op_mg * marr              pos += (clm * pos - pos) * vex _  
                     pos *= clpm  
                    marr _= ~op_mg * pos  
                    op.SetPoint(i,marr _)  
                      
            op.Message(c4d.MSG_UPDATE)  
            return True____
       _ _ _
      



      _ _ Any help appreciated.__


      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 26/06/2018 at 06:24, xxxxxxxx wrote:

        Hi Faxwang,

        Regarding your issue, the main problem is that you use a link to another object.
        So that means you have to listen for a change in this object to be able to say to your modifier to update. But you also need to listen for the current matrix of the modified object.
        And that's the perfect purpose of CheckDirty.

        Another thing, self.SetOptimizeCache(True) is only used for Generator, and not a modifier.
        Another good practise is to make sure to define your constants (c4d.OBJECT / MAP) with a custom prefix in order to be sure there is no ID collision.

        I also rework your algorithm in order to not need an Up object.

        class test(plugins.ObjectData) :
            targetObj = None
            targetObjLastMg = None
            currentObj = None
            currentObjLastMg = None
          
            def CheckDirty(self, op, doc) :
                # Check if modified object is not already define (aka first execution of the Modifier)
                if self.currentObj is None:
                    op.SetDirty(c4d.DIRTYFLAGS_DATA)
                    return
          
                # Check if the matrice of the modified object is dirty or not, in order to update the modifier
                if self.currentObj.GetMg() != self.currentObjLastMg:
                    # We tell to our Modifier something has change which will trigger the call of ModifyObject
                    op.SetDirty(c4d.DIRTYFLAGS_DATA)
                    return
          
                # Check if targetObj exist
                if self.targetObj:
                    # Check if targetObj is still alive, and the Position we have store is changed.
                    if self.targetObj.IsAlive() and self.targetObj.GetMg() != self.targetObjLastMg:
          
                        # We tell to our Modifier something has change which will trigger the call of ModifyObject
                        op.SetDirty(c4d.DIRTYFLAGS_DATA)
                        return
          
                return
          
          
            def ModifyObject(self, mod, doc, op, op_mg, mod_mg, lod, flags, thread) :
                if not mod[1000] or not mod[1001]:
                    return True
          
                pts = op.GetAllPoints()
                self.currentObj = mod
                self.currentObjLastMg = mod.GetMg()
                self.targetObj = mod[1000]
          
                self.targetObjLastMg = self.targetObj.GetMg()
                targetGlobalPos = self.targetObjLastMg.off
          
                vex = mod[1001].GetAllHighlevelData()
                cnt = len(vex)
                for i in xrange(cnt) :
                    if vex[i]:
                        currentGlobalPos = pts[i] * op.GetMg()
                        distancePosWeighted = (targetGlobalPos - currentGlobalPos) * vex[i]
                        finalLocalPos = pts[i] + distancePosWeighted
                        op.SetPoint(i, finalLocalPos)
                        
                op.Message(c4d.MSG_UPDATE)
                return True
        

        Another thing, please use [ code] and [ /code] when you post code on the forum which makes it easier to read 🙂

        If you have any questions, feel free to ask.
        Cheers,
        Maxime

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 27/06/2018 at 03:27, xxxxxxxx wrote:

          Thanks for your help, MaximeA!
          I'm glad you've helped me optimize the algorithm.
          I finally understand how to use CheckDirty(), but I have the same problem with "ctrl z" targert object. So I changed

          self.targetObj.IsAlive() and self.targetObj.GetMg() != self.targetObjLastMg:
          

          and changed "and" to "or". Should it be safe?
          I have another problem, that is, I'm going to write this plugin as this way of operation.
          A poly object has 3,000 points. I only want to deform 50 points. So there will be a vertex map. Suppose I store the index of the 50 points in the first setup. This guarantees that there is no need to judge 1000 times, directly through the point index to find point and then calculate. In theory this can speed up the calculation, I want to know if this is feasible, because it is going to read something stored. (I'm still confused about how to store this information, like Mesh defomer, set an Initialize button).

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 28/06/2018 at 02:24, xxxxxxxx wrote:

            Hi faxwang,

            If you still check for self.targetObj is not None (which will be the case for the first execution of the modifier) then it should be ok. Since None object doesn't have an IsAlive() function it will prompt an error in the console, so it's why you need to check, but after that is up to you to do whatever you want.

            Of course what you can do in ModifyObject is to get the DirtyCount of the vertexMap, so you will be able to know when a change happens to the map.

                    tagMap = mod[1001]
                    dirtyCnt = tagMap.GetDirty(c4d.DIRTYFLAGS_0)
                    if dirtyCnt != self.previousDirtyCnt:
                        self.previousDirtyCnt = dirtyCnt
                        # Rebuild Your List
            

            If you really want to go to the button way, you can catch the user click as shown in the documentation.

            If you have any question, again feel free to ask!
            Cheers,
            Maxime

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 28/06/2018 at 06:18, xxxxxxxx wrote:

              😉Thank you for your help and patient explanation,MaximeA! It really helped me a great deal!

              1 Reply Last reply Reply Quote 0
              • First post
                Last post