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

glTF importer ignores "-colonly" import hint on Blender empty objects #32363

Open
jeffres opened this issue Sep 26, 2019 · 23 comments
Open

glTF importer ignores "-colonly" import hint on Blender empty objects #32363

jeffres opened this issue Sep 26, 2019 · 23 comments

Comments

@jeffres
Copy link
Contributor

jeffres commented Sep 26, 2019

Godot version:

Both 3.1.1 and 202440a

OS/device including version:

Ubuntu 19.10

Issue description:

Documentation on import hints states that:

Option “-colonly” can also be used with Blender’s empty objects. On import, it will create a StaticBody with a collision node as a child.

However, when importing a glTF file with such an empty into Godot, it just turns into a Spatial node as such:

image

A Collada file exported from the same Blender scene shows the expected behavior:

image

where Cube3-TestColonly is a StaticBody and BoxShape is a CollisionShape

Steps to reproduce:

  • Import a glTF file exported from a Blender scene that includes an empty having -colonly appended to its name

  • Observe that the empty has turned into a Spatial node insteal of a StaticBody

Minimal reproduction project:

glTF import test.zip

The project directory also includes the Blender (2.80) file used to export the glb and dae (with Better Collada exporter) files.

The node of interest is Cube3-TestColonly, other ones are here to showcase other kind of import hints.

@jeffres jeffres changed the title glTF importer ignores "-colonly" import hints on empties glTF importer ignores "-colonly" import hint on Blender empty objects Sep 26, 2019
@akien-mga akien-mga added this to the 3.2 milestone Sep 26, 2019
@akien-mga
Copy link
Member

Relevant code:

if (_teststr(name, "colonly") || _teststr(name, "convcolonly")) {
if (isroot)
return p_node;
MeshInstance *mi = Object::cast_to<MeshInstance>(p_node);
if (mi) {
Ref<Mesh> mesh = mi->get_mesh();
if (mesh.is_valid()) {
List<Ref<Shape> > shapes;
String fixed_name;
if (collision_map.has(mesh)) {
shapes = collision_map[mesh];
} else if (_teststr(name, "colonly")) {
_gen_shape_list(mesh, shapes, false);
collision_map[mesh] = shapes;
} else if (_teststr(name, "convcolonly")) {
_gen_shape_list(mesh, shapes, true);
collision_map[mesh] = shapes;
}
if (_teststr(name, "colonly")) {
fixed_name = _fixstr(name, "colonly");
} else if (_teststr(name, "convcolonly")) {
fixed_name = _fixstr(name, "convcolonly");
}
ERR_FAIL_COND_V(fixed_name == String(), NULL);
if (shapes.size()) {
StaticBody *col = memnew(StaticBody);
col->set_transform(mi->get_transform());
col->set_name(fixed_name);
p_node->replace_by(col);
memdelete(p_node);
p_node = col;
int idx = 0;
for (List<Ref<Shape> >::Element *E = shapes.front(); E; E = E->next()) {
CollisionShape *cshape = memnew(CollisionShape);
cshape->set_shape(E->get());
col->add_child(cshape);
cshape->set_name("shape" + itos(idx));
cshape->set_owner(col->get_owner());
idx++;
}
}
}
} else if (p_node->has_meta("empty_draw_type")) {
String empty_draw_type = String(p_node->get_meta("empty_draw_type"));
StaticBody *sb = memnew(StaticBody);
sb->set_name(_fixstr(name, "colonly"));
Object::cast_to<Spatial>(sb)->set_transform(Object::cast_to<Spatial>(p_node)->get_transform());
p_node->replace_by(sb);
memdelete(p_node);
p_node = NULL;
CollisionShape *colshape = memnew(CollisionShape);
if (empty_draw_type == "CUBE") {
BoxShape *boxShape = memnew(BoxShape);
boxShape->set_extents(Vector3(1, 1, 1));
colshape->set_shape(boxShape);
colshape->set_name("BoxShape");
} else if (empty_draw_type == "SINGLE_ARROW") {
RayShape *rayShape = memnew(RayShape);
rayShape->set_length(1);
colshape->set_shape(rayShape);
colshape->set_name("RayShape");
Object::cast_to<Spatial>(sb)->rotate_x(Math_PI / 2);
} else if (empty_draw_type == "IMAGE") {
PlaneShape *planeShape = memnew(PlaneShape);
colshape->set_shape(planeShape);
colshape->set_name("PlaneShape");
} else {
SphereShape *sphereShape = memnew(SphereShape);
sphereShape->set_radius(1);
colshape->set_shape(sphereShape);
colshape->set_name("SphereShape");
}
sb->add_child(colshape);
colshape->set_owner(sb->get_owner());
}
} else if (_teststr(name, "rigid") && Object::cast_to<MeshInstance>(p_node)) {

CC @marstaik @fire

@jeffres
Copy link
Contributor Author

jeffres commented Sep 26, 2019

@akien-mga: thanks, I'll let you know if I have any clue.

@jeffres
Copy link
Contributor Author

jeffres commented Sep 26, 2019

It clearly seems to come from the "empty_draw_type" meta data not being set in the node at glTF import time.

If I force it with this patch (very quick and dirty of course), Cube3-TestColonly gets converted to a StaticBody as expected.

But I don't know how to identify empties at import time yet. When exporting the Blender scene to a plain text gltf file, it doesn't really differ from other objects (expect that it has no mesh attached but so does a light).

I'm trying to have a look at glTF exporter documentation for more info.

@marstaik
Copy link
Contributor

In the gltf importer, all the empty node candidates are the spatial nodes. Spatial nodes only get created when neither mesh, camera, skin, joint, etc is flagged on an import node. Basically, it's the end case for no mesh/camera.

What I do not know however, is what is considered an empty_draw_type. Is it just a spatial node? Or is it any node with no render body? Or is it the above + no renderable children?

@reduz might have insight

@jeffres
Copy link
Contributor Author

jeffres commented Sep 26, 2019

Ok thanks, that's interesting.

Which leads me to notice that, on the Collada side, empties are taken explicitly in charge by the Better Collada exporter that adds some extra information in the dae file, which are then handled by the importer:

<node id="Cube3-TestColonly-colonly" name="Cube3-TestColonly-colonly" type="NODE">
	<matrix sid="transform"> 1.0 0.0 0.0 3.5 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0  </matrix>
		<extra>
			<technique profile="GODOT">
				<empty_draw_type>CUBE</empty_draw_type>
			</technique>
		</extra>
</node>

When exporting with Blender default Collada exporter, those extra information are missing, which leads to the same behavior as with glTF (no StaticBody created at import time).

@Klowner
Copy link
Contributor

Klowner commented Oct 19, 2019

Might be good to attack this issue from both ends? Seems there's been some effort put forward to add rigid body info to glTF but the discussion seems to have stalled.
KhronosGroup/glTF#1307

@fire
Copy link
Member

fire commented Jan 9, 2020

@akien-mga akien-mga modified the milestones: 3.2, 4.0 Jan 22, 2020
@aclave1
Copy link

aclave1 commented Feb 23, 2020

In 3.2, i'm only noticing this issue when the exported object is parented to an armature. I've attached a glb which demonstrates the issue.
chest.zip

@fire
Copy link
Member

fire commented Feb 23, 2020

Try gltf master from blender, this is why the release notes mention blender 2.83.

@aclave1
Copy link

aclave1 commented Feb 23, 2020

What do you mean gltf master from blender? I should try to run from blender's master branch? I'm new to the project, where are the release notes that mention blender 2.83?

@KoBeWi
Copy link
Member

KoBeWi commented Dec 25, 2020

Seems still valid in 3.2.4 beta4

@babak-karimi-asl
Copy link

problem still exists with blender-3.0.0 and godot-3.4, are there any quick workarounds ?

@william-lohan
Copy link

I'm still running into this issue with Godot 3.4.4 and Blender 3.1.2

@wenqiangwang
Copy link

Godot 4.0 b1 have the same issue. '-col' works but '-colonly' on empty objects not working.

@fire
Copy link
Member

fire commented Sep 26, 2022

I wonder why it's wrong, need to get the godot-tests to the godot master and do a look https://github.com/godotengine/godot-tests

@mrkdji
Copy link

mrkdji commented Oct 12, 2022

I believe this should be mentioned in the docs

@portaloffreedom
Copy link

portaloffreedom commented Jan 18, 2023

I just tested this on both godot4 (compiled from master) and godot3.5.1 with GLTF, .escn (godot-blender-exporter) and the default collada .dae exporter in blender.
-colonly on empties works only on .escn files in godot3.5.1
-col on a mesh works everywhere except .escn in godot4

so, godot4 has .escn file reading completely ignoring all suffixes I've tried
.dae and .gltf ignore empties on both versions of godot.
.escn on godot3.5.1 is the only one working correctly

it could be that better-collada-exporter changes something, but I was not able to install it easily.

edit:
inspecting the .escn file there doesn't seem to be any reference to godot3 specific classes, the empties get written this way:

[node name="column-collision016-colonly" type="Spatial" parent="column007"]

transform = Transform(0.35, 0.0, 0.0, 0.0, 10.3, 0.0, 0.0, 0.0, 0.35, 0.0, 10.0, 0.0)
__meta__ = { "empty_draw_type": "CUBE" }

edit:
The Better Collada Exporter seem to work correctly.

@warcanin
Copy link

warcanin commented Feb 14, 2023

Maybe instead of complicating the process we could just add different hints like -boxcol -spherecol -cylindercol etc...
The must for blender import would obviously be that the rigid body settings and it's collision shape are transfered automatically but that would be harder than just fixing the hint problem.
edit: It seems that the checkbox
image
doesn't work at all, the only option to not import meshes is to add the -noimp hint at the end of the object

@Alastor01
Copy link

Godot 4.0 RC2, Blender 3.4

The issues is not limited to GLTF importer (which includes both direct Blend import as well as exported GLTF). It also affects Collada exports, so I assume all file types are affected.

The issue is not limited to Empties of Cube type either - it affects all shapes of Empty - that is none work.

Col / colonly makes no difference - neither work.

Exporting Empty collision shapes by themselves, without mesh parent, doesn't work either.

Polygonal shapes work as expected.

@lyuma
Copy link
Contributor

lyuma commented Feb 23, 2023

I would appreciate an example file from someone encountering this issue on Godot 4

To be clear, this is a feature where specific collision shapes can be added to empty nodes, but only when coming from Blender? If so, I believe this feature is not fully implemented in Godot 4 due to the new blend -> gltf import pipeline. It relies on something called get_meta which requires the importer to fill it out.

As an alternative to blend->gltf import, there is ESCN which does technically function in Godot 4. However, due to the version upgrade and the fact that most exporters are designed for Godot 3, we cannot fully support ESCN workflow in Godot 4.0 until the tooling is updated (chicken/egg problem). Renaming a .tscn to .escn is the only fully supported usage of ESCN import at this time. Correct me if I'm wrong, @fire

Having an actual example (blend or gltf) would help us triage this specific issue, but otherwise the clock has run out for 4.0, and due to the implementation complexity of supporting node metadata not standardized in gltf, I'm not sure it's trivial to fix. We may look into this in a future 4.x release.

@lyuma lyuma modified the milestones: 4.0, 4.x Feb 23, 2023
@lyuma
Copy link
Contributor

lyuma commented Feb 23, 2023

Okay I see the other usecase is convering a node into a sort of placeholder StaticBody3D with no known collision shape attached. is that correct? That might be possible to get working for 4.0 by removing the check for if (shapes.size()) in resource_importer_scene.cpp.

I might be in favor of this. It means imported scenes will not be fully functional since they will be missing collision shapes, but it will provide a space to add your own. Is this what you all are expecting?

@Alastor01
Copy link

Import_Bug.zip

Very simple example, two meshes - one which generates polygonal collision shape, the other should generate primitive box collider - but does not.

@miskatonicstudio
Copy link

Hi! I just checked Empty export from Blender (v3.6.5) to Godot (v4.1.1) and it still doesn't work (tested with sphere and cube). It seems like a great option to have, allowing us to use primitive shapes instead of complex ones for collisions ;) It seems that this issue hasn't been fixed in a while, do you think that's going to change anytime soon? If not, perhaps the documentation could be updated?

https://docs.godotengine.org/en/stable/tutorials/assets_pipeline/importing_scenes.html#create-collisions-col-convcol-colonly-convcolonly

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