BlenderProc
BlenderProc copied to clipboard
[BUG]: enable_rigidbody() for convex decomposition takes extremely long
Describe the bug
When using MeshObjectUtility.build_convex_decomposition_collision_shape() the runtime for any simulation increases exponentially.
General Information
-
2.3.0, updated 27/07/22 - branch: https://github.com/DLR-RM/BlenderProc/tree/test_decompose_with_caching
-
On which operating system are you? Linux
-
Have you checked the issue tracker to see if a similar issue has been opened? Yes
-
Have you changed BlenderProc in any way besides the config file? If yes, are you sure that this change does not affect the problem you are having? Added custom modules to Blenderproc, didn't change anything in blenderproc itself.
To Reproduce Steps to reproduce the behavior:
- Provide the full command you used to run BlenderProc:
blenderproc run script.py
- Provide the full python file, you used:
import blenderproc as bproc
import time
start=time.time()
obj_list=[]
cached_objects={}
##generating objects
for i in range(50):
obj=bproc.loader.load_obj(("MUG.obj"),cached_objects)
obj_list.append(obj[0])
##do convex_decomposition for objects
for i in range(50):
obj_list[i].build_convex_decomposition_collision_shape("convex_decomposition",cached_objects=cached_objects)
print(time.time()-start)
- Provide a link to all 3D models you used, if they are from one of the publicly available supported datasets, provide the name or path so that it is possible to reproduce the error. happens for all .obj files (MUG.obj is attached)
Expected behavior Using enable_rigidbody() shouldn't increase the runtime of the script by 30 times. ( See Additional context )
Additional context While trying to figure out what slows my simulation down to 1000 sec(with convex decomposition) from about 30 sec(without convex decomposition) i found out that it is the line part.enable_rigidbody in MeshObjectUtility.build_convex_decomposition_collision_shape(). Unexpectedly this mostly comes from the line 241 in MeshObjectUtility.py, which calls:
part.enable_rigidbody(True,"CONVEX_HULL")
If i comment this line out my script runtime goes from 1000sec to 30 sec. But the convex shapes become useless obviously... ;-)
Hey,
@cornerfarmer what do you think if we change the duplicate function to include the children as well, this should be fixed, right?
Best, Max
It seems that its more the fault of the rigid body component. I am gonna take a look at it, if it can be included in the duplication or what exactly is taking so long when enabling it.
So the rigid body component is already duplicated when duplicating its object. So, @themasterlink, you are right, duplicating children inside the duplicate function should solve this issue.
Hey @Sodek93,
could you check whether #633 helps you? When now duplicating the object after loading and enabling the rigid body element, the whole code only takes about 2.6s for me:
import blenderproc as bproc
import time
start=time.time()
obj = bproc.loader.load_obj(("examples/basics/basic/MUG.obj"))[0]
obj.enable_rigidbody(active=False, collision_shape="COMPOUND")
obj.build_convex_decomposition_collision_shape("convex_decomposition")
obj_list=[obj]
for i in range(50):
obj_list.append(obj.duplicate())
print(time.time()-start)
Looks perfect :) Thanks @cornerfarmer
Hey @Sodek93,
could you check whether #633 helps you? When now duplicating the object after loading and enabling the rigid body element, the whole code only takes about 2.6s for me:
import blenderproc as bproc import time start=time.time() obj = bproc.loader.load_obj(("examples/basics/basic/MUG.obj"))[0] obj.enable_rigidbody(active=False, collision_shape="COMPOUND") obj.build_convex_decomposition_collision_shape("convex_decomposition") obj_list=[obj] for i in range(50): obj_list.append(obj.duplicate()) print(time.time()-start)
I'll test right right away! Thank you guys :-)
This helped a lot and it is working as expected. Got my script runtime (more complex script) from about 1000 s to 300 s, which is obviously a huge step :-)
I'll investigate why my runtime goes down to 25s if i comment out following lines which are called in the for loop:
if [obj] in list(cached_objects.values()): #only do if object isn't a copy of already existing objects
obj.enable_rigidbody(active=True, collision_shape="COMPOUND")
obj.blend_obj.build_convex_decomposition_collision_shape("convex_decomposition")
Hey,
can't you do this before you copy the object?
Best, Max
Yes i can.
Testing need some time. I now have the problem that my object and its convex parts are not at the same position. This could be an issue of my code, and not the solution you provided.
I need to use this command to clear parent of object but keep the position as [0,0,0]:
bpy.ops.object.parent_clear(type="CLEAR_KEEP_TRANSFORM")
If i rotate the object before using that command the convex decomposition parts are not alligned with die object itself. If i do it afterwards i have the problem that i have to rotate all parts of the convex decomposition after duplication.
Can you please post a complete code example, so we can reproduce that?
I'll write a code that reproduces that.
nvm: i got the issue fixed with just rotation and position of the duplicated convex decompositions and the new Part to [0,0,0] before doing anything else with them.
This could be added into the duplicate() function but maybe won't be used by most other users.
def duplicate(self, duplicate_children: bool = True) -> "MeshObject":
""" Duplicates the object.
:param duplicate_children: If True, also all children objects are recursively duplicated.
:return: A new mesh object, which is a duplicate of this object.
"""
new_entity = self.blender_obj.copy()
new_entity.data = self.blender_obj.data.copy()
bpy.context.collection.objects.link(new_entity)
duplicate_obj = MeshObject(new_entity)
duplicate_obj.set_location([0,0,0])
duplicate_obj.set_rotation_euler([0,0,0])
if duplicate_children:
for child in self.get_children():
duplicate_child = child.duplicate(duplicate_children=duplicate_children)
duplicate_child.set_parent(duplicate_obj)
return duplicate_obj
Is there a way to use bpy in the script i run with blenderproc cli? I cant give you a code that reproduces the issue without it.
Hey @Sodek93,
could you check whether #633 helps you? When now duplicating the object after loading and enabling the rigid body element, the whole code only takes about 2.6s for me:
import blenderproc as bproc import time start=time.time() obj = bproc.loader.load_obj(("examples/basics/basic/MUG.obj"))[0] obj.enable_rigidbody(active=False, collision_shape="COMPOUND") obj.build_convex_decomposition_collision_shape("convex_decomposition") obj_list=[obj] for i in range(50): obj_list.append(obj.duplicate()) print(time.time()-start)
The example upside works fine for me too,also takes 2.6 sec with 50 Objects, 36 sec for 200.
I realized that runtime still exponentially increases the more objects i have in scene... But it's now down to 500 sec (with about 50 mugs) after fixing the positioning issue. I'll check whats the difference between my code and the provided solution.
I'll provide an reproducing example tomorrow. If i skip copying the childs (convex parts) i am still down to 26 sec.
I can't reproduce the issue for now... Can you keep this open so if i found a solution / can reproduce it i can post here? Otherwise i can start a new discussion if i found out what slows my runtime down so much more then in the given example.
Hey @Sodek93,
I think i was able to reproduce the misalignment problem you describe. The convex child objects seemed to be misaligned, if the object's pose is changed after its convex decomposition and before duplicating it.
I updated the #633 PR respectively, so now it should work in all cases.
Regarding your still persisting performance issue: For now I will keep this issue open, so let us know if you can reproduce it.
I assume this has been resolved.