Collision mesh from loaded model for built-in collision system

Hi all,

This code snippet creates a collision mesh from a loaded model, suitable for the built-in collision detection and handling system:

from panda3d.core import *
from direct.showbase.ShowBase import ShowBase


base = ShowBase()

# set up a light source
p_light = PointLight("point_light")
p_light.set_color((1., 1., 1., 1.))
base.light = base.camera.attach_new_node(p_light)
base.light.set_pos(5., -100., 7.)
base.render.set_light(base.light)

# load model(s)
path_to_model = "smiley"
model_root = base.loader.load_model(path_to_model)
model_root.reparent_to(base.render)

# create a temporary copy to generate the collision meshes from
model_copy = model_root.copy_to(base.render)
model_copy.detach_node()

# create root node to attach collision nodes to
collision_root = NodePath("collision_root")
collision_root.reparent_to(model_root)
# offset the collision meshes from the model so they're easier to see
collision_root.set_x(1.)

# create a collision mesh for each of the loaded models
for model in model_copy.find_all_matches("**/+GeomNode"):

    model_node = model.node()
    collision_node = CollisionNode(model_node.name)
    collision_mesh = collision_root.attach_new_node(collision_node)
    collision_mesh.set_mat(model.get_mat())
    # collision nodes are hidden by default
    collision_mesh.show()

    for geom in model_node.modify_geoms():

        geom.decompose_in_place()
        vertex_data = geom.modify_vertex_data()
        vertex_data.format = GeomVertexFormat.get_v3()
        view = memoryview(vertex_data.arrays[0]).cast("B").cast("f")
        index_list = geom.primitives[0].get_vertex_list()
        index_count = len(index_list)

        for indices in (index_list[i:i+3] for i in range(0, index_count, 3)):
            points = [Point3(*view[index*3:index*3+3]) for index in indices]
            coll_poly = CollisionPolygon(*points)
            collision_node.add_solid(coll_poly)


base.run()

Please note that this is far from efficient, especially for models with complex geometry!
It is meant to be used in cases where exact collisions take priority over performance and for testing purposes.
In other cases, a simpler collision shape approximating the model geometry is strongly recommended.

Hopefully some of you will find it useful :slight_smile: .

3 Likes

Does this create a collision solid around any object in a model?

It creates a solid for each GeomNode in the model with the exact same shape as that GeomNode.

This is very neat! :slight_smile:

I would like to note one caveat–unless I’ve missed something obviating it, or am mistaken: If the source-model has rather detailed geometry, this may have performance implications when the geometry is used for collision purposes.

Where feasible, I do still urge the use of dedicated, simplified geometry for the purposes of collision.

That said, this remains a technique that could potentially be useful in a number of cases, indeed! :slight_smile:

1 Like

And you are right, of course! In my hurry to post the snippet, I totally forgot to mention this :grin: . The first post has now been amended to include this advice. Thanks :slight_smile: !

1 Like

When I am trying it with “models/smiley”, It is not working