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
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    My CheckDirty() override is driving me crazy!

    PYTHON Development
    0
    2
    683
    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 04/05/2018 at 16:10, xxxxxxxx wrote:

      As mentioned in the subject, I've got a CheckDirty() override that is giving me a headache.  I could really use some help thinking through this one!

      My ObjectData plugin uses GetContour() to return a SplineObject.  The generated spline represents a light ray reflecting and refracting through objects.  The objects to reflect from are on an In/Exclude list and the objects to refract through are on a separate In/Exclude list.

      In order to simplify the reflection/refraction calculations I am creating a single triangulated polygonal object from the objects on the reflection list, and a separate single triangulated polygonal object from the objects on the refraction list.

      Now, on to the actual problem. I need my spline to re-generate whenever any object on either In/Exclude list is changed (i.e. when it is moved, scaled, rotated, deformed).  So the brilliant idea I had was: I'll generate my own checksum from the positions of every point in the monolithic objects I'm creating for the ray tracing.

      This works beautifully in most cases.  However, it does not work when a symmetric object is rotated or scaled. It seems that the point position values of my monolithic object are still, somehow, in the rotated/scaled object's local coordinates.  That doesn't make sense, though, as then a translation would should not change the checksum either.

      For reference here are the questionable methods:

          def CheckDirty(self, op, doc) :
              if  op.GetMg() != self.mg:
                  self.mg = op.GetMg()
                  op.SetDirty(c4d.DIRTYFLAGS_DATA)
              else:
                  CHECKSUM_ID = 1041080
                  bc = op.GetDataInstance()
        
                  #Lists of the BaseObjects on the In/Exclude lists
                  reflList, refrList = self.GetObjLists(bc, doc)
        
                  #Two triangulated PolygonObjects built from the lowest level cache (i.e. Cache() or DeformCache() if it exists)
                  reflPolys, refrPolys = self.BuildObjects(doc, reflList, refrList) 
        
                  dirtysum = bc.GetContainer(CHECKSUM_ID)
        
                  if reflPolys.GetPointCount() :
                      reflChecksum = abs(utils.VectorSum(sum(reflPolys.GetAllPoints())))
                  else:
                      reflChecksum = 0
                  if refrPolys.GetPointCount() :
                      refrChecksum = abs(utils.VectorSum(sum(refrPolys.GetAllPoints())))
                  else:
                      refrChecksum = 0
        
                  checksum = long(reflChecksum + refrChecksum) % 2**63
        
                  if dirtysum.GetInt64(0) != checksum:
                      dirtysum.SetInt64(0, checksum)
                      bc.SetData(CHECKSUM_ID, dirtysum)
                      op.SetDirty(c4d.DIRTYFLAGS_DATA)
        
          def BuildObjects(self, doc, reflList, refrList) :
              reflGroup = c4d.BaseObject(c4d.Onull)
              refrGroup = c4d.BaseObject(c4d.Onull)
        
              for obj in reflList:
                  mg = obj.GetMg()
                  deform_cache = None
        
                  cache = obj.GetCache()
                  if cache:
                      deform_cache = cache.GetDeformCache()
                  obj = [obj for obj in (obj, cache, deform_cache) if obj][-1]
        
                  source = obj.GetClone()
                  source.InsertUnder(reflGroup)
                  source.SetMg(mg)
        
              reflPolys = utils.SendModelingCommand(command = c4d.MCOMMAND_JOIN,
                                              list = [reflGroup],
                                              mode = c4d.MODELINGCOMMANDMODE_ALL,
                                              doc = doc)[0]
              
              for obj in refrList:
                  mg = obj.GetMg()
                  deform_cache = None
                  
                  cache = obj.GetCache()
                  if cache:
                      deform_cache = cache.GetDeformCache()
                  obj = [obj for obj in (obj, cache, deform_cache) if obj][-1]
                  
                  source = obj.GetClone()
                  source.InsertUnder(refrGroup)
                  source.SetMg(mg)
          
              refrPolys = utils.SendModelingCommand(command = c4d.MCOMMAND_JOIN,
                                                      list = [refrGroup],
                                                      mode = c4d.MODELINGCOMMANDMODE_ALL,
                                                      doc = doc)[0]
          
              utils.SendModelingCommand(command = c4d.MCOMMAND_TRIANGULATE,
                                          list = [reflPolys, refrPolys],
                                          mode = c4d.MODELINGCOMMANDMODE_ALL)
        
              return (reflPolys, refrPolys)
      
      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 04/05/2018 at 16:46, xxxxxxxx wrote:

        Well, I've figured out a solution that runs faster and works in every test case I've thrown at it.  Let this be a lesson for everyone: if there's a solution in the standard library, USE IT!

        Here's what I changed in the CheckDirty() function to make things work:

                    pt_array = array.array('l')
          
                    if reflPolys.GetPointCount() :
                        pt_ints = [long(utils.VectorSum(v)) for v in reflPolys.GetAllPoints()]
                        pt_array.extend(pt_ints)
          
                    if refrPolys.GetPointCount() :
                        pt_ints = [long(utils.VectorSum(v)) for v in refrPolys.GetAllPoints()]
                        pt_array.extend(pt_ints)
          
                    checksum = zlib.adler32(pt_array)
        

        This builds the checksum from a real-honest-to-goodness-checksum-function.

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