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

    Python Volume access

    Cinema 4D SDK
    r20
    2
    6
    1.2k
    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.
    • rsodreR
      rsodre
      last edited by

      Hello,

      I'm trying to read a VolumeObject from Python, just trying to visualize the voxel count for now. When I acces a volume interface, like this...

      	def GetDParameter(self, node, id, flags):
      		paramId = id[0].id
      		if paramId == c4d.UNITY_VOLUME_VoxelCount:
      			volume = self.get_volume_object(node)
      			if volume == None: return False
      			vi = volume.GetVolume()
      			data = vi.GetActiveVoxelCount()
      			return (True, data, flags | c4d.DESCFLAGS_GET_PARAM_GET)
      		return False
      

      It works, but I always hit this debug breakpoint. Removing that code stops the critical stop.
      Do I need to dispose the interface in any way?

      /Volumes/Branches/build_osx/osx-4-release/depot/release/20.0/frameworks/kernel.framework/source/memory/systemallocator.cpp(487): CRITICAL: Stop: Damaged block (or from a different allocator

      Also, how to iterate the volume using a GridIterator?
      There's nothing like the step methods from C++ SDK, how do I do the loop?

      1 Reply Last reply Reply Quote 0
      • M
        m_adam
        last edited by

        Hi @rsodre, there are few examples of volume usage in python in Github repository.

        Especially gridaccessor_read_r20.py which demonstrate how to read data for a given voxel.

        So here on a volume builder, the next script is working as expected, note that it's very important to import maxon and volume from maxon.frameworks.

        import c4d
        import maxon
        from maxon.frameworks import volume
        
        
        def main():
            # Checks if there is an active object
            if op is None:
                raise RuntimeError("Failed to retrieve op.")
        
            # Checks if the active object is a Volume builder
            if not op.IsInstanceOf(c4d.Ovolumebuilder):
                raise TypeError("op is not a c4d.Ovolumebuilder.")
        
            # Gets the C4D Volume Object from the cache
            cache = op.GetCache()
            if cache is None:
                raise RuntimeError("Failed to retrieve the cache of the volume builder.")
        
            # Checks if the cache is a C4D Volume Object
            if not cache.IsInstanceOf(c4d.Ovolume):
                raise TypeError("cache is not a c4d.Ovolume.")
        
            # Gets the Volume object linked to this Ovolume object.
            volume = cache.GetVolume()
            if volume is None:
                raise RuntimeError("Failed to retrieve the maxon.frameworks.volume.VolumeRef.")
        
            print(volume.GetActiveVoxelCount())
        
        if __name__ == '__main__':
            main()
        

        Unfortunately, there is no GridIterator in Python available.

        So even if you import maxon, and the volume module you still have the issue, I would say that maybe your volumeobject is not correctly built, but without more code, it's hard to reproduce your issue.

        Cheers,
        Maxime.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        rsodreR 1 Reply Last reply Reply Quote 0
        • rsodreR
          rsodre
          last edited by rsodre

          I'll devour hat repository, thanks!

          I'm getting the volume from a VolumeBuilder's cache.
          My code so far is here (very early WIP)

          1 Reply Last reply Reply Quote 0
          • rsodreR
            rsodre @m_adam
            last edited by

            Hi @m_adam.

            About the critical stop, it happens even with your code.
            I run C4D R20.059 from XCode 10.3

            What should the coordinate in access.GetValue(vec) be?
            If I try the voxel coordinate, it always returns the same value, testing everything inside volume.GetGetActiveVoxelDim()
            If I try world coordinates, all values are negative (inside and outside) the volume.

            From the docs, volume. GetWorldBoundingBox() should return a maxon.Range, but this type is not documented anywhere. In practice, it returns a type that is unknown...
            UnknownDataType(net.maxon.parametrictype.range<net.maxon.parametrictype.vec<3,float64>>)

            I need to extract a normalized SDF from the volume.
            Pretty basic but I can't figure out how just with api descriptions.

            1 Reply Last reply Reply Quote 0
            • M
              m_adam
              last edited by

              Hi @rsodre, unfortunately, due to a bug solved in R21, it's not possible in R20 to run Cinema 4D as debug mode and call MAXON_CPYTHON_FUNCTION in release mode.

              The issue is that the Python volume framework does use the MAXON_CPYTHON_FUNCTION, so this leads to the behavior that the memory model is not the same.

              So I guess if you try your code in regular Cinema 4D (without Xcode and not running c4d in debug mode), it will work without issue, could you confirm?

              GetValue works in the global space of the volume grid. This grid can be retrieved from a volumeRef with GetGridTransform.
              However, since it's a maxon.Matrix64 this is a bit problematic since maxon.Matrix64 and maxon.Vector doesn't support * operator. So you have to translate them in c4d type (manually) then reconvert it back to a Maxon datatype (this will be done on the fly).

              Correct, maxon.Range is not yet implemented in Python so a UnknownDataType is returned so C++.

              While I'm happy to assist you on Python Maxon API, I have to admit that the Maxon API regarding Python is far from being feature complete, and regarding your knowledge I advise you to do what you want in C++, it will be far way easier with the GridAccessor.

              Cheers,
              Maxime.

              MAXON SDK Specialist

              Development Blog, MAXON Registered Developer

              rsodreR 1 Reply Last reply Reply Quote 0
              • rsodreR
                rsodre @m_adam
                last edited by

                @m_adam got it! it's working now.

                The final code for my float sdf exporter is here.

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