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

    MoData's GetFalloffs() returns only 0 while rendering

    Cinema 4D SDK
    python r23
    2
    7
    776
    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.
    • CairynC
      Cairyn
      last edited by Cairyn

      This riddle has stumped me:

      I create a simple Python effector. Here's a trimmed-down version:

      import c4d
      from c4d.modules import mograph as mo
      
      def main() :
          moData = c4d.modules.mograph.GeGetMoData(op)
          if moData is None: return False
      
          hasField = op[c4d.FIELDS].HasContent()
          print ("hasField:", hasField)
          farr = moData.GetFalloffs()
          print ("Falloffs:", farr)
      
          return True
      

      It does nothing to the clones in this case, just shows me the falloffs (the original modifies the clones, but it behaves the same and doesn't add to the question). The scene is also very simple, the effector has a box field that moves over some cube clones.
      6a36c5e4-ce35-48ea-82a3-50b5ae7784f2-image.png

      Now here's the riddle:
      When I animate this scene in the viewport, the console shows me the expected falloffs, changing as the animation runs. All is well with the world.
      When I render the same scene however, the console shows me a constant 0.0 for all falloffs.

      I am not able to find any explanation, any flag to set, any function to call. There are multiple examples for Python effectors, and multiple threads on this forum, none of which mentions any issue with rendering.
      I can put a MoGraph Cache Tag on the cloner, which works fine, and which replays fine (also with the more complicated original scene). But I don't see it mentioned anywhere that a cache is mandatory. The rendering should IMO just work.

      SimplestExample.c4d

      (I tried this on R21 too, with the same results.)

      1 Reply Last reply Reply Quote 0
      • ManuelM
        Manuel
        last edited by

        Hi,

        You don't need to write you own code, just using the default python effector on full control, once you add a field, the effector will not work at render time.
        I've reported the bug a few times ago, but it is still there.

        Cheers,
        Manuel

        MAXON SDK Specialist

        MAXON Registered Developer

        1 Reply Last reply Reply Quote 0
        • CairynC
          Cairyn
          last edited by

          Ouch! In R25 still? Thanks for the confirmation; so I may need to rewrite my effector in Parameter mode (since you mentioned the mode, I suppose it'll work this way?)

          1 Reply Last reply Reply Quote 0
          • CairynC
            Cairyn
            last edited by

            Okay, Parameter Mode is even worse when it comes to falloffs.
            GetFalloffs() results in an actual error raised.
            GetArray(c4d.MODATA_FALLOFF_WGT) results in None.
            GetArray(c4d.MODATA_WEIGHT) returns a proper array, but it's filled with zeroes no matter where the field is.

            Also, the auto-gen sample code (at least in R23) is faulty:
            it uses an attribute data which is undefined, causing an error (I found on the forum that the mode can be read via GetBlendID, though); and it reads the MoData from the gen variable instead of op, which results in GetCurrentIndex always returning 0.

            It doesn't work in the expected way anyhow. The vector returned by the Python code for ID_MG_BASEEFFECTOR_POSITION is not an absolute, but kind of a weight for the value set in the GUI. I'd need to return the final value though, which cannot be expressed as a product. This works in Full Control mode, but as the falloffs will not work there either with a field while rendering, I guess... I lost the game.

            1 Reply Last reply Reply Quote 0
            • ManuelM
              Manuel
              last edited by

              hi,

              I don't remember the version, but we fixed the default script, now it is working in parameter control. I just remember there was no workaround for the python effector to work in full control mode.

              Cheers,
              Manuel

              MAXON SDK Specialist

              MAXON Registered Developer

              CairynC 1 Reply Last reply Reply Quote 0
              • CairynC
                Cairyn @Manuel
                last edited by Cairyn

                @m_magalhaes Meanwhile, I found one (more or less): calculating the falloff myself. I just need to access the field list and perform a SampleList on the clones' positions. This actually works within the render process as well. Looks approx. like this:

                    md = mo.GeGetMoData(op)
                    if not md: return False
                    cnt = md.GetCount()
                    marr = md.GetArray(c4d.MODATA_MATRIX)
                    fieldlist = op[c4d.FIELDS]
                
                    matCloner = gen.GetMg()
                    inputField = c4d.modules.mograph.FieldInput([marr[i].off * matCloner for i in range(cnt)], cnt)
                    info = c4d.modules.mograph.FieldInfo.Create(c4d.FIELDSAMPLE_FLAG_VALUE, None, doc, 0, 1, inputField, gen)
                    outputs = c4d.modules.mograph.FieldOutput.Create(cnt, c4d.FIELDSAMPLE_FLAG_VALUE)
                    fieldlist.SampleList(info, inputField, outputs)
                    # print (outputs.GetValue(0))
                    for i in range(0, cnt):
                        fieldStrength = outputs.GetValue(i)
                        # usw usf
                
                1 Reply Last reply Reply Quote 1
                • CairynC
                  Cairyn
                  last edited by

                  Aaaand of course I forgot a crucial point: After modifying the clone positions in marr, you need to write them back to the MoData, but the last parameter apply_strength must be False:

                  moData.SetArray(c4d.MODATA_MATRIX, marr, False)
                  

                  This is at first glance unintuitive since we want the strength to be present but when looking closely, you can fathom that the function will internally multiply with the falloff strength that it calculated itself, and that probably comes from GetFalloffs() again, so it's 0 and nothing is won. We do not want SetArray to do that at all, because we have already applied the falloffs that we calculated ourselves, and SetArray should keep its buggy hands off it!

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