Convex hull data from Blender

Creating Convex Hull in Blender

This small script is tested with Blender 4.1.1. It might not work any older versions.
You can find the example Blender project and Python Scripts in the blender folder of the repo.
Defold project contains example Convex hull shapes.

https://github.com/selimanac/defold-blender-convex-hull

Create Convex Hull in Blender:

  • Load your model and prepare it for importing Defold.
  • If you want to match the transform of your model and convex hull, disable the +Y Up option in the Transform section of the export window.

+Y Up

  • Select the model/object and switch to Edit Mode (Tab).

Edit Mode

  • Select all vertices (A).

Select all vertices

  • Use the “Convex Hull” operation (press F3, search for “Convex Hull”) or select “Mesh” → “Convex Hull” from menu.

Convex Hull

Export Convex Hull Points Using Python Script:

  • Go to the Scripting tab or open a new Text Editor in Blender.

Text Editor

  • Copy and paste the script into the scripting editor.
  • Adjust the export_path variable to the desired file path where you want to save the exported convex hull data.
  • Ensure the correct object is selected.
  • Click the Run Script button in the scripting editor.

Run Scrip

This should correctly export the convex hull data to the specified file.

import bpy
import bmesh
import os

def export_convex_hull_points(obj, filepath):
    # Create a new bmesh and fill it with the object's mesh data
    bm = bmesh.new()
    bm.from_mesh(obj.data)

    # Create the convex hull
    bmesh.ops.convex_hull(bm, input=bm.verts)

    # Extract vertices from the convex hull
    vertices = [v.co.copy() for v in bm.verts]

    # Write to file
    with open(filepath, 'w') as f:
        f.write(f"shape_type: TYPE_HULL\n")
        for v in vertices:
            f.write(f"data: {v.x}\n")
            f.write(f"data: {v.y}\n")
            f.write(f"data: {v.z}\n")

    # Free the bmesh
    bm.free()

# Ensure the correct object is selected
obj = bpy.context.object

# Specify the export path
# Default is .blender file's folder
export_path =  os.path.join(bpy.path.abspath("//"), "file_name.convexshape")

# Export the convex hull points
export_convex_hull_points(obj, export_path)

print(f"Convex hull points exported to {export_path}")

17 Likes

Thank you. I’ll try this when I get back next week.

Does this script allow to create convex shape which is precise to the initial mesh of the model? I see that the convexhull Blender creates, is a very rough low poly blob.
What if my model is a low-poly house of three floors, doorways and stairs, all as one mesh. Can it just wrap that house mesh with a simplified convex shape based on vertices?

This script doesn’t create convex shape . Blender does with its own algorithm. Script just gets the data and export it as Defold compatible file.

This is what convex hull is!?

Then it is a single mesh

I don’t know. convex hull cant handle holes etc… you have to separate the convex hull or mesh for that.

2 Likes

Hello! Thank you for sharing the script! I just put together a more automated version using ChatGPT.
Blender Export to GLB + ConvexShape

This Blender script automates exporting selected objects to GLB format and generates corresponding Convex Hull shape files.
It is useful for game engines such as Defold, Unity, Godot, or any workflow where both mesh and convex collision data are required.

based on: https://github.com/selimanac/defold-blender-convex-hull

Features

  1. Apply Transforms
    For each selected object, Apply All Transforms (location, rotation, scale) is executed.

  2. Export to GLB

    • Each object is exported as a separate .glb file.

    • Export options:

      • GLB → single binary file (default, recommended).

      • GLTF_SEPARATE → .gltf + .bin (if you want text-based .gltf).

    • File name matches the object name in Blender.

    • +Y Up is disabled (export_yup=False).

    • All transforms are applied during export (export_apply=True).

  3. Generate Convex Hull

    • For each object, a convex hull is calculated from its vertices.

    • The data is saved in a .convexshape file next to the .glb.

    • File format example:

      shape_type: TYPE_HULL data: 1.0 data: 2.0 data: 3.0 …

  4. Multiple Object Support

    • All selected objects are processed one by one.

    • Errors with a single object do not stop the script.

  5. Usage

Copy and paste the script below into Blender Scripting. Specify the export path in the script. Select the objects to export and run the script.

Script tested on versions 4.5.3

import bpy
import bmesh
import os

# === Export folder path ===
# Change this to your export folder
export_path = "/"

if not os.path.exists(export_path):
    raise FileNotFoundError(f"Export folder {export_path} does not exist")

# Get all selected objects
selected_objects = bpy.context.selected_objects
if not selected_objects:
    raise ValueError("No objects selected!")

# Apply transforms for all selected objects
for obj in selected_objects:
    bpy.context.view_layer.objects.active = obj
    obj.select_set(True)
    bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
    obj.select_set(False)


def export_convex_hull_points(obj, filepath):
    """Generate convex hull for the object and save vertices to file."""
    bm = bmesh.new()
    bm.from_mesh(obj.data)

    # Build convex hull
    bmesh.ops.convex_hull(bm, input=bm.verts)

    # Extract vertices
    vertices = [v.co.copy() for v in bm.verts]

    # Write to file
    with open(filepath, 'w') as f:
        f.write("shape_type: TYPE_HULL\n")
        for v in vertices:
            f.write(f"data: {v.x}\n")
            f.write(f"data: {v.y}\n")
            f.write(f"data: {v.z}\n")

    bm.free()


# Export each selected object
for obj in selected_objects:
    try:
        obj.select_set(True)
        bpy.context.view_layer.objects.active = obj

        # File names
        glb_file = os.path.join(export_path, f"{obj.name}.glb")
        convex_file = os.path.join(export_path, f"{obj.name}.convexshape")

        # Export GLB (one file per object)
        print(f"Exporting object: {obj.name} -> {glb_file}")
        bpy.ops.export_scene.gltf(
            filepath=glb_file,
            export_format='GLB',  # Single binary file
            use_selection=True,
            export_yup=False,     # Disable +Y Up
            export_apply=True
        )

        # Export convex hull points
        print(f"Generating convex hull for {obj.name} -> {convex_file}")
        export_convex_hull_points(obj, convex_file)

        obj.select_set(False)

    except Exception as e:
        print(f"Error processing {obj.name}: {e}")
        obj.select_set(False)
        continue

print("Export finished!")

4 Likes

Nice work, thanks for sharing

2 Likes

Can I use the data I get from the model to create collision shape in Defold?

Yes! Why not? :grin:

meteor

4 Likes

Thank you for the answer and demonstration!

Tried using it to create collision for my complex scene (using primitive types would take too long) but I guess this is not the intended way of doing it?

1 Like

Yes, if it is a single model, then Convex hull will not work. In this case, you need to use Concave hull, which, as far as I know, is not supported in Defold, but you can split Convex hull into parts using composite models.

1 Like

Yes thats curently a hassle. Concave shapes are currently not supported unfortunately, so in complex shapes that are not convex, you would have to either subdivide mesh into convex parts or use convex decomposition algorithm to do so.

This thread is good to track I guess

https://github.com/defold/defold/issues/9267

So currently after you choose either manual split or convex decomposition algorithm you can use libraries like dae2collision which is editor script that you can use to create collision shapes from. And then attach them to game objects.

But still its a work-around and would be awesome if Defold supported concave shapes out-of-the-box. As currently with the approach I described downside is you would need 1000s of separate collision objects, each with their own settings, which in complex levels becomes a mess to deal with

4 Likes

There are a couple of scripts/addons available for Blender to decompose meshes into convex hulls. Here are 2 of those:

The simplest seems to be this script. According to the author, it does not work well for ngons, round meshes, meshes with openings.
Blender 2.91 Script for Convex Hull Decomposition into Separate Shapes Using Blender’s Convex using “Split Concave Faces” · GitHub
For the latter, he suggests trying this addon:
GitHub - olitheolix/blender-convex-decomposition

I can’t comment on any though - I do my splitting by hand.

2 Likes

Thank you for the detailed answer. I guess I will stick to using primitive shapes for collisions

It is a bit disappointing tbh. I am creating a project for an extensive 3D tutorial on Defold and explaining that you have to use hundreds of primitive shapes for a large map (so it will have collisions) will not exactly make Defold appealing to new developers..

Hope concave shapes will be added soon as well as proper/full gltf support

1 Like

Thank you for the links!

How do you use the convex shapes after they are created? How is the implementation of it is done on Defold’s side? Still needs multiple collision shapes and placing on the correct world position?

As I said, I never used those. But I assume you’d end up with meshes that are already convex hulls in Blender.
The next step is to get the vertices of the hull and write the string for Defold’s .convexshape file.
For that you could use one one of the scripts presented above.

Ah sorry, I think I misunderstood.

Yes, you still need multiple collision objects, each using one of the hull files created.

1 Like

I guess I will stick to the primitive shapes till we have concave shape support. It seems to suit my needs better. Thank you again :slight_smile:

1 Like

Your tutorials are great! Keep them coming:)

And regarding managing collision shapes yes that’s a headache, and concave shapes should solve it, best if we can have a feature of attaching a completely arbitrary shape to the CO or literally ability to infer from Gltf files. But one trick you can use for now is have an editor script that reads all decomposed meshes from the directory and write new collision objects into a new directory. Still messy but it can kinda work.. :sweat_smile:

Hope amazing Defold team will have a chance too look into it soon, because that thing would be a game-changer. As right now most 3D examples are literally flat ground.

1 Like

Did you have to convex decompose ground also Alex?

I made ground in trenchbroom and used the defold-trenchfold extension, which creates a convex hull on its own.

1 Like