My CheckDirty() override is driving me crazy!



  • 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)
    


  • 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.


Log in to reply