Add compound shape for rigid body simulation

This patch adds a new compound shape entry to the shape selection
dropdown. It also corrects wrong inertia calculation for convex hulls,
that resulted in strange behavior for small objects.

The compound shape take the collision shapes from its object children
and combines them. This makes it possible to create concave shapes from
primitive shapes. Using this instead of the mesh collision shape is
often many times faster.

Reviewed By: Sergey, Sebastian Parborg

Differential Revision: http://developer.blender.org/D5797
This commit is contained in:
David Vogel
2020-07-30 18:35:34 +02:00
committed by Sebastian Parborg
parent d3944940f9
commit 820ca419e0
11 changed files with 284 additions and 40 deletions

View File

@@ -23,10 +23,10 @@ from bpy.types import (
)
def rigid_body_warning(layout):
def rigid_body_warning(layout, text):
row = layout.row(align=True)
row.alignment = 'RIGHT'
row.label(text="Object does not have a Rigid Body")
row.label(text=text, icon='ERROR')
class PHYSICS_PT_rigidbody_panel:
@@ -49,13 +49,24 @@ class PHYSICS_PT_rigid_body(PHYSICS_PT_rigidbody_panel, Panel):
layout.use_property_split = True
ob = context.object
parent = ob.parent
rbo = ob.rigid_body
if rbo is None:
rigid_body_warning(layout)
rigid_body_warning(layout, "Object does not have a Rigid Body")
return
layout.prop(rbo, "type", text="Type")
if parent is not None and parent.rigid_body is not None:
if parent.rigid_body.collision_shape == 'COMPOUND':
row = layout.row(align=True)
row.alignment = 'RIGHT'
row.label(text="This object is part of a compound shape", icon='INFO')
else:
rigid_body_warning(layout, "Rigid Body can't be child of a non compound Rigid Body")
return
if parent is None or parent.rigid_body is None:
layout.prop(rbo, "type", text="Type")
class PHYSICS_PT_rigid_body_settings(PHYSICS_PT_rigidbody_panel, Panel):
@@ -66,6 +77,8 @@ class PHYSICS_PT_rigid_body_settings(PHYSICS_PT_rigidbody_panel, Panel):
@classmethod
def poll(cls, context):
obj = context.object
if obj.parent is not None and obj.parent.rigid_body is not None:
return False
return (obj and obj.rigid_body and (context.engine in cls.COMPAT_ENGINES))
def draw(self, context):
@@ -76,7 +89,7 @@ class PHYSICS_PT_rigid_body_settings(PHYSICS_PT_rigidbody_panel, Panel):
rbo = ob.rigid_body
if rbo is None:
rigid_body_warning(layout)
rigid_body_warning(layout, "Object does not have a Rigid Body")
return
col = layout.column()
@@ -96,17 +109,32 @@ class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel):
@classmethod
def poll(cls, context):
obj = context.object
if obj.parent is not None and obj.parent.rigid_body is not None and not obj.parent.rigid_body.collision_shape == 'COMPOUND':
return False
return (obj and obj.rigid_body and (context.engine in cls.COMPAT_ENGINES))
def draw(self, context):
layout = self.layout
ob = context.object
parent = ob.parent
rbo = ob.rigid_body
layout.use_property_split = True
layout.prop(rbo, "collision_shape", text="Shape")
if rbo.collision_shape == 'COMPOUND':
if parent is not None and parent.rigid_body is not None and parent.rigid_body.collision_shape == 'COMPOUND':
rigid_body_warning(layout, "Sub compound shapes are not allowed")
else:
found = False
for child in ob.children:
if child.rigid_body is not None:
found = True
break
if not found:
rigid_body_warning(layout, "There are no child rigid bodies")
if rbo.collision_shape in {'MESH', 'CONVEX_HULL'}:
layout.prop(rbo, "mesh_source", text="Source")
@@ -123,6 +151,8 @@ class PHYSICS_PT_rigid_body_collisions_surface(PHYSICS_PT_rigidbody_panel, Panel
@classmethod
def poll(cls, context):
obj = context.object
if obj.parent is not None and obj.parent.rigid_body is not None:
return False
return (obj and obj.rigid_body and (context.engine in cls.COMPAT_ENGINES))
def draw(self, context):
@@ -149,6 +179,8 @@ class PHYSICS_PT_rigid_body_collisions_sensitivity(PHYSICS_PT_rigidbody_panel, P
@classmethod
def poll(cls, context):
obj = context.object
if obj.parent is not None and obj.parent.rigid_body is not None and not obj.parent.rigid_body.collision_shape == 'COMPOUND':
return False
return (obj and obj.rigid_body and (context.engine in cls.COMPAT_ENGINES))
def draw(self, context):
@@ -180,6 +212,8 @@ class PHYSICS_PT_rigid_body_collisions_collections(PHYSICS_PT_rigidbody_panel, P
@classmethod
def poll(cls, context):
obj = context.object
if obj.parent is not None and obj.parent.rigid_body is not None:
return False
return (obj and obj.rigid_body and (context.engine in cls.COMPAT_ENGINES))
def draw(self, context):
@@ -200,6 +234,8 @@ class PHYSICS_PT_rigid_body_dynamics(PHYSICS_PT_rigidbody_panel, Panel):
@classmethod
def poll(cls, context):
obj = context.object
if obj.parent is not None and obj.parent.rigid_body is not None:
return False
return (obj and obj.rigid_body and obj.rigid_body.type == 'ACTIVE'
and (context.engine in cls.COMPAT_ENGINES))