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

    Faster way of converting dict of Vector3 to Vector4

    Cinema 4D SDK
    python
    2
    3
    557
    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.
    • orestiskonO
      orestiskon
      last edited by orestiskon

      Hello,

      I'm converting UVs to Vertex Colors and vice versa, and I'm trying to see if there's a faster way of converting a dictionary of Vector3 values to a dictionary of Vector4 values.

      The UVs give a value like:

      uvPolygon = {'a': c4d.Vector(), 'b': c4d.Vector(), 'c': c4d.Vector(), 'd': c4d.Vector()}
      

      The Vertex Color is very similar but with Vector4D:

      colorPolygon = {'a': c4d.Vector4d(), 'b': c4d.Vector4d(), 'c': c4d.Vector4d(), 'd': c4d.Vector4d()}
      

      Despite being so similar, there doesn't seem to be a method to convert the two dictionaries, so I have to iterate through each item and convert it individually.

      That means not only do I iterate through all the polygons with python, but I have to do it 4 times as much, one for each polygon point, which is wildly inefficient. Twice to go back and forth.

      I was wondering if there's a better, faster way of achieving this.

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

        Unfortually there is none, your only way would be to use C++. Moreover in C++ you can directly have access to the internal UV polygons array pointer and same for the VertexColor preventing a lot of copies that needs to be performed by the python bindings itself.

        Here some snippets used for benchmarking. Theorically List comprehension should be slightly faster, but seems not.
        Also did try a weird approach using string, but seems to not work neither.

        # Take care this will freeze c4d for some minutes.
        import c4d
        import time
        
        # Main function
        def main():
            
            for x in range(1, 50000, 1000):
                uvs = [{
                    "a": c4d.Vector(1, 1, 1),
                    "b": c4d.Vector(0.6, 1, 1),
                    "c": c4d.Vector(0.6, 0, 1),
                    "d": c4d.Vector(1, 0, 1)
                }]*x
            
                # plain loop
                init_time = time.time()
                final_data_loop = []
                for uv in uvs:
                    buffer_dict = {}
                    for k, pos in uv.items():
                        buffer_dict[k] = c4d.Vector4d(pos.x, pos.y, pos.z, 0)
                    final_data_loop.append(buffer_dict)
                t_loop = time.time() - init_time
            
                # list/dict comprehension
                init_time = time.time()
                final_data_compr = [{k: c4d.Vector4d(v.x, v.y, v.z, 0) for k, v in uv.items()} for uv in uvs]
                t_compr = time.time() - init_time
            
                # str
                init_time = time.time()
                exec(f'final_data_str = {str(uvs).replace("Vector", "c4d.Vector4d").replace(")", ", 0)")}', globals())
                t_str = time.time() - init_time
            
                print(f"Data equals: {final_data_loop == final_data_compr == final_data_str}")
                print(f"{x*4} pts, {x} polys, loop: {t_loop}s, compr: {t_compr}s, str: {t_str}s")
        
        # Execute main()
        if __name__=='__main__':
            main()
        

        Cheers,
        Maxime.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        orestiskonO 1 Reply Last reply Reply Quote 1
        • orestiskonO
          orestiskon @m_adam
          last edited by

          @m_adam Thanks a lot for the benchmarking Maxime. I was planning to go for the string method, I'm surprised it's not faster.

          I wasn't planning to use this for a plugin, not to mention C++, but it's good information to have.

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