Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python 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
    • Recent
    • Tags
    • Users
    • Register
    • Login

    Using SetWeightMap() multiple times can lead to inexplicable changes in weight values

    Scheduled Pinned Locked Moved Cinema 4D SDK
    python2026
    5 Posts 4 Posters 57 Views 3 Watching
    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.
    • chuanzhenC Offline
      chuanzhen
      last edited by

      Hi,
      Previously, I had been using the SetWeight() method to set weight values, and it worked very stably. However, after seeing the deprecation notice for SetWeight() in the python api documentation, I switched to using SetWeightMap() instead. However, there were some issues with this function. When I used SetWeightMap() multiple times to set values, its values would gradually change.

      Below is a simple example of my video, using a standard cube (with 8 points), where each point is equally influenced by all bones.

      However, when I repeatedly obtain the weight values using GetWeightMap()without making any changes, and then set the weights using SetWeightMap() again, I can see that the weight values have undergone slight changes, with the sum of weights changing from 1 --> 0.998

      相信我,可以的!

      ThomasBT 1 Reply Last reply Reply Quote 0
      • ThomasBT Offline
        ThomasB @chuanzhen
        last edited by

        @chuanzhen
        Well, could it perhaps stem from rounding errors involving floating-point values?

        Thanks,
        T.B

        1 Reply Last reply Reply Quote 0
        • AnlvA Offline
          Anlv
          last edited by Anlv

          This appears to be a Float32-to-quantized-weight conversion or rounding issue in SetWeightMap(), rather than ordinary floating-point noise.

          Cinema 4D version: 2026.3.4
          Expected: unchanged values after every round-trip.
          Round  0: weight=0.14285496299687189 (14.28549630%), total=0.99998474097810308 (99.99847410%)
          Round  1: weight=0.1428397039749752 (14.28397040%), total=0.99987792782482621 (99.98779278%)
          Round 10: weight=0.14270237277790493 (14.27023728%), total=0.99891660944533434 (99.89166094%)
          Round 19: weight=0.14256504158083466 (14.25650416%), total=0.99795529106584246 (99.79552911%)
          Round 20: weight=0.14256504158083466 (14.25650416%), total=0.99795529106584246 (99.79552911%)
          Round 25: weight=0.14256504158083466 (14.25650416%), total=0.99795529106584246 (99.79552911%)
          
          ferdinandF 1 Reply Last reply Reply Quote 0
          • ferdinandF Offline
            ferdinand @Anlv
            last edited by ferdinand

            Hey @chuanzhen,

            thank you for reaching out to us. Please provide a code example and scene file to reproduce the issue, without it is hard to give a concrete answer.

            @Anlv and @ThomasB are correct in bringing forward that floating point precision could be an issue in principle. But IEEE 754 corresponds to roughly 17 significant digits in the interval [0, 1] without loss of precision for the data type Float64, a change in the third significant digit as you report is somewhat unlikely in the interval [0, 1] (but not impossible).

            And more importantly, all integer values, e.g., 1.0, are exactly representable up to 2^53 in IEEE 754-64, so you should never see a loss for the value 1.0. More over, round trips should mean no accumulated loss when you do not do additional computations with the value. So, you first write the value X which might or might not be representable as IEEE 754 -64 because you entered it as some kind of literal in your code or via a GUI. Once written X will be X', i.e., the closest value of X which is representable in IEEE 754-64. Further read and write events will not change that value, unless you do some arithmetic operations with it.

            Overall this sounds all bit like the weight tag is somehow post processing the passed data, and you therefore encounter some error creep. But I can only say anything concrete with code and a scene.

            Cheers,
            Ferdinand

            MAXON SDK Specialist
            developers.maxon.net

            chuanzhenC 1 Reply Last reply Reply Quote 0
            • chuanzhenC Offline
              chuanzhen @ferdinand
              last edited by chuanzhen

              @ferdinand
              Hi,The simple demo I made:
              1:Create a standard cube (with 8 vertices),
              2:Create 8 joint (point_id 1 -> joint 1 ),bind it,then offset all joints (x:10000,y:10000,z:10000 cm)
              3:Each point is 100% bound to a bone,
              4: Then, apply smooth 1-2 times to all bones and points to obtain a result where each point is influenced by all bones (facilitating the observation of the code execution results)
              5: normalize weights
              6:Then execute the code 2-3 times, and you can clearly see the result

              code:

              import c4d
              
              doc: c4d.documents.BaseDocument  # The currently active document.
              op: c4d.BaseObject | None  # The primary selected object in `doc`. Can be `None`.
              
              def main() -> None:
                  tag = op.GetTag(c4d.Tweights)
                  if not tag:
                      return
                  j_cnt = tag.GetJointCount()
                  p_cnt = op.GetPointCount()
              
                  for i in range(10):
                      weights = [tag.GetWeightMap(j_id,p_cnt) for j_id in range(j_cnt)]
                      for j_id in range(j_cnt):
                          tag.SetWeightMap(j_id,weights[j_id])
                      tag.WeightDirty()
                  
                  
                  c4d.EventAdd()
              
              
              if __name__ == '__main__':
                  main()
              

              01aff503-a8c0-4521-8b99-3c094189c490-image.png
              video:

              相信我,可以的!

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