This addon allows you to create collider meshes more easily. It provides different operators to generate primitve colliders or convex mesh colliders out of a selection.
bl_info = {
"name": "Bounding Capsule",
"author": "Your Name",
"version": (1, 0),
"blender": (2, 80, 0),
"location": "View3D > Object",
"description": "Generate a bounding capsule for a selected object",
"category": "Object"
}
import bpy
import math
# Function to calculate the distance between two points
def distance(p1, p2):
return math.sqrt(sum((p1[i] - p2[i]) ** 2 for i in range(len(p1))))
# Function to calculate the distance between a point and a line segment
def point_line_segment_distance(p, p1, p2):
v = [p2[i] - p1[i] for i in range(len(p1))]
w = [p[i] - p1[i] for i in range(len(p1))]
t = max(0, min(1, sum(w[i] * v[i] for i in range(len(v))) / sum(v[i] * v[i] for i in range(len(v)))))
closest_point = [p1[i] + t * v[i] for i in range(len(p1))]
return distance(p, closest_point)
# Function to calculate the radius and height of the bounding capsule
def calculate_radius_height(points):
max_distance = 0
for i in range(len(points)):
for j in range(i + 1, len(points)):
d = distance(points[i], points[j])
if d > max_distance:
max_distance = d
radius = max_distance / 2
height = max_distance - radius
return radius, height
# Operator to generate the bounding capsule
class OBJECT_OT_generate_bounding_capsule(bpy.types.Operator):
bl_idname = "object.generate_bounding_capsule"
bl_label = "Generate Bounding Capsule"
bl_description = "Generate a bounding capsule for the selected object"
def execute(self, context):
# Check if there is an active object and it's selected
if bpy.context.active_object and bpy.context.active_object.select_get():
selected_object = bpy.context.active_object
# Get the object's vertices
vertices = [selected_object.matrix_world @ v.co for v in selected_object.data.vertices]
points = [list(vertex) for vertex in vertices]
# Calculate the radius and height of the bounding capsule
radius, height = calculate_radius_height(points)
# Create a new mesh object for the cylinder
bpy.ops.mesh.primitive_cylinder_add(radius=radius, depth=height)
cylinder = bpy.context.object
# Create a new mesh object for the top hemisphere
bpy.ops.mesh.primitive_uv_sphere_add(radius=radius, location=(0, 0, height/2))
top_hemisphere = bpy.context.object
# Create a new mesh object for the bottom hemisphere
bpy.ops.mesh.primitive_uv_sphere_add(radius=radius, location=(0, 0, -height/2))
bottom_hemisphere = bpy.context.object
# Combine the objects into a single object
bpy.ops.object.select_all(action='DESELECT')
cylinder.select_set(True)
top_hemisphere.select_set(True)
bottom_hemisphere.select_set(True)
bpy.context.view_layer.objects.active = cylinder
bpy.ops.object.join()
# Get the combined object
bounding_capsule = bpy.context.object
# Move the bounding capsule to the same location as the original object
bounding_capsule.location = selected_object.location
# Align the bounding capsule with the original object's rotation
bounding_capsule.rotation_euler = selected_object.rotation_euler
# Set the bounding capsule as the parent of the original object
selected_object.parent = bounding_capsule
else:
self.report({'ERROR'}, "No selected object found.")
return {'FINISHED'}
# Panel to display the Generate Bounding Capsule button
class OBJECT_PT_bounding_capsule_panel(bpy.types.Panel):
bl_idname = "OBJECT_PT_bounding_capsule_panel"
bl_label = "Bounding Capsule"
bl_category = "Tool"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
def draw(self, context):
layout = self.layout
row = layout.row()
row.operator("object.generate_bounding_capsule", text="Generate Bounding Capsule")
# Register the addon
def register():
bpy.utils.register_class(OBJECT_OT_generate_bounding_capsule)
bpy.utils.register_class(OBJECT_PT_bounding_capsule_panel)
def unregister():
bpy.utils.unregister_class(OBJECT_OT_generate_bounding_capsule)
bpy.utils.unregister_class(OBJECT_PT_bounding_capsule_panel)
if __name__ == "__main__":
register()
ChatGPT code: