Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Importing .glb with parent as RigidBody, cannot import a child CollisionShape3D #79086

Open
wilfredjonathanjames opened this issue Jul 6, 2023 · 11 comments

Comments

@wilfredjonathanjames
Copy link

wilfredjonathanjames commented Jul 6, 2023

Godot version

4.0.3

System information

MacOS 12.3

Issue description

The Godot 3D import features are impressive and easy to use, but I think I've found an edgecase.

When a user wants to import a 3D model and have the resulting node be a Body3D, they can change this in the import settings as Root Type. However Body3Ds expect collider shapes to be direct children.

The only way I can see to create a collider shape on import is to use the -col, -convcol, colonly and -convcolonly object prefixes defined here.

The problem is that these all create a Body3D parent node with the collision shape as a child. This is the correct behaviour in any case other than the intended Body3D being the object root node.

E.g.:
In blender:
image
In import settings:
image
Import preview tree:
image

The ChocolateBarCollider collision shape is put inside a StaticBody3D, when I need it to be placed directly under the parent node.

My work around has been to use the New Inherited Scene option and add a BoxCollider3D manually, which works fine in this instance but may not be so straightforward with more complex meshes that are updated frequently.
image

It would be great to know if I've just missed something

Steps to reproduce

  1. Make a simple object in blender and an overlapping shape to be the collider. Give the collider the -convcolonly prefix
  2. Export as .glb
  3. Import into Godot after changing the Root Type import setting to a RigidBody3D
  4. In a separate scene, place your object over a StaticBody3D with a large box collider
  5. Place a camera pointing at both objects
  6. Run the scene

The object will fall through the StaticBody3D collider

Minimal reproduction project

Repro repo here

@fire
Copy link
Member

fire commented Jul 6, 2023

@aaronfranke We've talked at length about this issue. Do we have a summary of the discussion.

@aaronfranke
Copy link
Member

This will be easy to support after #77937 is merged.

@capnm
Copy link
Contributor

capnm commented Jul 6, 2023

This will be easy to support after #77937 is merged.

I personally don't think that this is the right approach for Godot's tree based scenes. The collision shape node should always remain a child of the corresponding body.
The importer should be able to correctly detect the object relations and only attach the -convcolonly shape as a collision object to the parent body:

image

@wilfredjonathanjames
Copy link
Author

Hi guys, what does #77937 do that would solve this problem @aaronfranke, and why is it not the right approach @capnm?

@aaronfranke
Copy link
Member

#77937 would allow us to generate the collision shape node anywhere in the node hierarchy, and the shape will search upwards arbitrarily far for a body (static, rigid, etc). Then we would change the importer to import only the shape instead of a bunch of static bodies, which would cause the shapes to apply to the rigid body.

@wilfredjonathanjames
Copy link
Author

It does seem to partly solve my problem, but I'm not clear on how it allows us to define specific Body parents on import. For context, I use import hints.

What I have

If I have this blender scene, with a lowpoly collider and a higher poly mesh
image

It imports as
image

Like I said in the original post, I can change the root node in import settings, but the ColliderShape3Ds are still parented to other import-generated colliders.

What I want

image

That seems like an important primitive, so maybe I'm just missing how to do this with import hints.

What currently kind of works

If I do this in blender
image

And turn off the visibility of the additional MeshInstance3D created on the -rigid node, I get this
image

It's not ideal that the Body isn't the scene parent, and it creates an additional MeshInstance3D that needs to be disabled.

Solutions

I would suggest either of the following:

  • Solution 1
    • If Godot finds a single root node on importing a model, don't wrap it in a new root node
    • Add new import hints
      • -colonlyrigid - Like -colonly but uses a RigidBody3D instead of a StaticBody3D
      • -convcolonlyrigid - You get the idea
  • Solution 2
    • Implement Allow CollisionShape nodes to be indirect children of bodies #77937
    • Add new import hints
      • -colshape - a concave CollisionShape3D without the parent Body, follows the -col and -colonly naming convention
      • -convcolshape
      • Some new hints that allow the user to tell Godot to import a node as a RigidBody. Only makes sense on parent empties. Without which we won't be able to make use of this anywhere other than on the root node if it's changed to a Body on import.

I prefer Solution 1. Seems cleaner.

@aaronfranke
Copy link
Member

@wjagodfrey For "Add new import hints", note that special node names are kind of a hacky solution, and they are not very flexible (for example, it only works with mesh-based shapes, no way to specify a box collider for your crate). Long-term, the solution is to make Blender export explicit physics information like OMI_physics_shape.

@wilfredjonathanjames
Copy link
Author

@aaronfranke it is hacky, but it's the solution we've got. It's incomplete, and it would be great to plug the gap.

@capnm
Copy link
Contributor

capnm commented Oct 11, 2023

@wjagodfrey The situation seems to be improving :) this could plug the gap.
https://github.com/eoineoineoin/glTF_Physics

@aaronfranke
Copy link
Member

@samsface
Copy link
Contributor

samsface commented Feb 24, 2024

Workaround import script if anyone else is stuck with this.
Set the import node type of the .glb to rigid body.
Then in blender, name your object "yourobject-rigid" in the tree view.

This script will sneakily re-parent the mesh and phys model to the root node and you should end up with something like this:
image

@tool
extends EditorScenePostImport

func _post_import(scene):
    if scene.get_child_count() == 0:
        return
        
    var rigid_body:RigidBody3D = scene.get_child(0)
    if not rigid_body:
        return

    for child in rigid_body.get_children():
        rigid_body.remove_child(child)
        scene.add_child(child)
    
    scene.remove_child(rigid_body)
    
    return scene

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants