Faster way of converting dict of Vector3 to Vector4
-
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.
-
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. -
@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.