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

Crash when adding CSGBox3D node due to gizmo drawing #60936

Closed
Calinou opened this issue May 10, 2022 · 9 comments · Fixed by #61154
Closed

Crash when adding CSGBox3D node due to gizmo drawing #60936

Calinou opened this issue May 10, 2022 · 9 comments · Fixed by #61154

Comments

@Calinou
Copy link
Member

Calinou commented May 10, 2022

Related to #58284.

Godot version

4.0.alpha (694baff)

System information

Fedora 34, GeForce GTX 1080 (NVIDIA 510.60.02)

Issue description

The editor crashes when adding a CSGBox3D node due to gizmo drawing. This occurs when adding a CSG node, or reopening the editor on a scene that has a CSG node saved. I can consistently reproduce the crash every time I open the editor on such a scene.

This also occurs with other CSG nodes such as CSGSphere3D.

I don't get such a crash on a build from a few days prior (9923179).

Edit: I bisected the regression to aabbb40.

Backtrace

================================================================
handle_crash: Program crashed with signal 4
Engine version: Godot Engine v4.0.alpha.custom_build (694baff233c2efb4675f708389c9ff2bbc00bc03)
Dumping the backtrace. Please include this when reporting the bug on https://github.com/godotengine/godot/issues
[1] /lib64/libc.so.6(+0x3d320) [0x7f1d9d98f320] (??:0)
[2] VectorWriteProxy<Variant>::operator[](int) (/home/hugo/Documents/Git/godotengine/godot/./core/templates/vector.h:52)
[3] Array::operator[](int) (/home/hugo/Documents/Git/godotengine/godot/core/variant/array.cpp:80)
[4] CSGShape3DGizmoPlugin::redraw(EditorNode3DGizmo*) (/home/hugo/Documents/Git/godotengine/godot/modules/csg/editor/csg_gizmos.cpp:352)
[5] EditorNode3DGizmo::redraw() (/home/hugo/Documents/Git/godotengine/godot/editor/plugins/node_3d_editor_gizmos.cpp:118)
[6] Node3D::add_gizmo(Ref<Node3DGizmo>) (/home/hugo/Documents/Git/godotengine/godot/scene/3d/node_3d.cpp:471)
[7] Node3DEditor::_request_gizmo(Object*) (/home/hugo/Documents/Git/godotengine/godot/editor/plugins/node_3d_editor_plugin.cpp:7114)
[8] void call_with_variant_args_helper<__UnexistingClass, Object*, 0ul>(__UnexistingClass*, void (__UnexistingClass::*)(Object*), Variant const**, Callable::CallError&, IndexSequence<0ul>) (/home/hugo/Documents/Git/godotengine/godot/./core/variant/binder_common.h:241)
[9] void call_with_variant_args_dv<__UnexistingClass, Object*>(__UnexistingClass*, void (__UnexistingClass::*)(Object*), Variant const**, int, Callable::CallError&, Vector<Variant> const&) (/home/hugo/Documents/Git/godotengine/godot/./core/variant/binder_common.h:384)
[10] MethodBindT<Object*>::call(Object*, Variant const**, int, Callable::CallError&) (/home/hugo/Documents/Git/godotengine/godot/./core/object/method_bind.h:334)
[11] Object::callp(StringName const&, Variant const**, int, Callable::CallError&) (/home/hugo/Documents/Git/godotengine/godot/core/object/object.cpp:838)
[12] SceneTree::call_group_flagsp(unsigned int, StringName const&, StringName const&, Variant const**, int) (/home/hugo/Documents/Git/godotengine/godot/scene/main/scene_tree.cpp:273)
[13] void SceneTree::call_group_flags<Node3D*>(unsigned int, StringName const&, StringName const&, Node3D*) (/home/hugo/Documents/Git/godotengine/godot/./scene/main/scene_tree.h:260)
[14] Node3D::_notification(int) (/home/hugo/Documents/Git/godotengine/godot/scene/3d/node_3d.cpp:186)
[15] Node3D::_notificationv(int, bool) (/home/hugo/Documents/Git/godotengine/godot/./scene/3d/node_3d.h:52)
[16] VisualInstance3D::_notificationv(int, bool) (/home/hugo/Documents/Git/godotengine/godot/./scene/3d/visual_instance_3d.h:?)
[17] GeometryInstance3D::_notificationv(int, bool) (/home/hugo/Documents/Git/godotengine/godot/./scene/3d/visual_instance_3d.h:?)
[18] CSGShape3D::_notificationv(int, bool) (/home/hugo/Documents/Git/godotengine/godot/modules/csg/csg_shape.h:?)
[19] CSGPrimitive3D::_notificationv(int, bool) (/home/hugo/Documents/Git/godotengine/godot/modules/csg/csg_shape.h:?)
[20] CSGBox3D::_notificationv(int, bool) (/home/hugo/Documents/Git/godotengine/godot/modules/csg/csg_shape.h:?)
[21] Object::notification(int, bool) (/home/hugo/Documents/Git/godotengine/godot/core/object/object.cpp:847)
[22] Node3D::_notification(int) (/home/hugo/Documents/Git/godotengine/godot/scene/3d/node_3d.cpp:148)
[23] Node3D::_notificationv(int, bool) (/home/hugo/Documents/Git/godotengine/godot/./scene/3d/node_3d.h:52)
[24] VisualInstance3D::_notificationv(int, bool) (/home/hugo/Documents/Git/godotengine/godot/./scene/3d/visual_instance_3d.h:?)
[25] GeometryInstance3D::_notificationv(int, bool) (/home/hugo/Documents/Git/godotengine/godot/./scene/3d/visual_instance_3d.h:?)
[26] CSGShape3D::_notificationv(int, bool) (/home/hugo/Documents/Git/godotengine/godot/modules/csg/csg_shape.h:?)
[27] CSGPrimitive3D::_notificationv(int, bool) (/home/hugo/Documents/Git/godotengine/godot/modules/csg/csg_shape.h:?)
[28] CSGBox3D::_notificationv(int, bool) (/home/hugo/Documents/Git/godotengine/godot/modules/csg/csg_shape.h:?)
[29] Object::notification(int, bool) (/home/hugo/Documents/Git/godotengine/godot/core/object/object.cpp:847)
[30] Node::_propagate_enter_tree() (/home/hugo/Documents/Git/godotengine/godot/scene/main/node.cpp:213)
[31] Node::_propagate_enter_tree() (/home/hugo/Documents/Git/godotengine/godot/scene/main/node.cpp:234)
[32] Node::_set_tree(SceneTree*) (/home/hugo/Documents/Git/godotengine/godot/scene/main/node.cpp:2569)
[33] Node::_add_child_nocheck(Node*, StringName const&) (/home/hugo/Documents/Git/godotengine/godot/scene/main/node.cpp:?)
[34] Node::add_child(Node*, bool, Node::InternalMode) (/home/hugo/Documents/Git/godotengine/godot/scene/main/node.cpp:1143)
[35] EditorNode::set_edited_scene(Node*) (/home/hugo/Documents/Git/godotengine/godot/editor/editor_node.cpp:3440)
[36] EditorNode::load_scene(String const&, bool, bool, bool, bool, bool) (/home/hugo/Documents/Git/godotengine/godot/editor/editor_node.cpp:3726)
[37] EditorNode::_load_open_scenes_from_config(Ref<ConfigFile>, String const&) (/home/hugo/Documents/Git/godotengine/godot/editor/editor_node.cpp:4849)
[38] EditorNode::_load_docks() (/home/hugo/Documents/Git/godotengine/godot/editor/editor_node.cpp:4639)
[39] EditorNode::_sources_changed(bool) (/home/hugo/Documents/Git/godotengine/godot/editor/editor_node.cpp:1044)
[40] void call_with_variant_args_helper<EditorNode, bool, 0ul>(EditorNode*, void (EditorNode::*)(bool), Variant const**, Callable::CallError&, IndexSequence<0ul>) (/home/hugo/Documents/Git/godotengine/godot/./core/variant/binder_common.h:241)
[41] void call_with_variant_args<EditorNode, bool>(EditorNode*, void (EditorNode::*)(bool), Variant const**, int, Callable::CallError&) (/home/hugo/Documents/Git/godotengine/godot/./core/variant/binder_common.h:351)
[42] CallableCustomMethodPointer<EditorNode, bool>::call(Variant const**, int, Variant&, Callable::CallError&) const (/home/hugo/Documents/Git/godotengine/godot/./core/object/callable_method_pointer.h:105)
[43] Callable::call(Variant const**, int, Variant&, Callable::CallError&) const (/home/hugo/Documents/Git/godotengine/godot/core/variant/callable.cpp:51)
[44] Object::emit_signalp(StringName const&, Variant const**, int) (/home/hugo/Documents/Git/godotengine/godot/core/object/object.cpp:1119)
[45] Error Object::emit_signal<bool>(StringName const&, bool) (/home/hugo/Documents/Git/godotengine/godot/./core/object/object.h:774)
[46] EditorFileSystem::_notification(int) (/home/hugo/Documents/Git/godotengine/godot/editor/editor_file_system.cpp:1248)
[47] EditorFileSystem::_notificationv(int, bool) (/home/hugo/Documents/Git/godotengine/godot/editor/editor_file_system.h:144)
[48] Object::notification(int, bool) (/home/hugo/Documents/Git/godotengine/godot/core/object/object.cpp:847)
[49] SceneTree::_notify_group_pause(StringName const&, int) (/home/hugo/Documents/Git/godotengine/godot/scene/main/scene_tree.cpp:855)
[50] SceneTree::process(double) (/home/hugo/Documents/Git/godotengine/godot/scene/main/scene_tree.cpp:454)
[51] Main::iteration() (/home/hugo/Documents/Git/godotengine/godot/main/main.cpp:2745)
[52] OS_LinuxBSD::run() (/home/hugo/Documents/Git/godotengine/godot/platform/linuxbsd/os_linuxbsd.cpp:441)
[53] bin/godot.linuxbsd.tools.64.llvm(main+0x1c6) [0x41b0fb6] (/home/hugo/Documents/Git/godotengine/godot/platform/linuxbsd/godot_linuxbsd.cpp:68)
[54] /lib64/libc.so.6(__libc_start_main+0xd5) [0x7f1d9d979b75] (??:0)
[55] bin/godot.linuxbsd.tools.64.llvm(_start+0x2e) [0x41b0d2e] (??:?)
-- END OF BACKTRACE --
================================================================
[1]    28736 IOT instruction (core dumped)  bin/godot.linuxbsd.tools.64.llvm /tmp/4/project.godot

Steps to reproduce

  • Add a CSGBox3D node.

Minimal reproduction project

test_csg_crash.zip

@Mathis-Z
Copy link

Mathis-Z commented May 12, 2022

The crash happens here in line 352. If you delete this code section the crash goes away.

if (cs->is_root_shape()) {
Array csg_meshes = cs->get_meshes();
Ref<Mesh> csg_mesh = csg_meshes[1];
if (csg_mesh.is_valid()) {
p_gizmo->add_collision_triangles(csg_mesh->generate_triangle_mesh());
}
}

The problem is that the cs object has no root_mesh when cs->get_meshes() is called which makes cs->get_meshes() return an empty array and then the program crashes when it tries to access index 1.
The crash also disappears if you change this code to update the shape if necessary.
Array CSGShape3D::get_meshes() const {
if (root_mesh.is_valid()) {
Array arr;
arr.resize(2);
arr[0] = Transform3D();
arr[1] = root_mesh;
return arr;
}
return Array();
}

changed to:

Array CSGShape3D::get_meshes() {
	if(!root_mesh.is_valid())
		_update_shape();
	if (root_mesh.is_valid()) {
		Array arr;
		arr.resize(2);
		arr[0] = Transform3D();
		arr[1] = root_mesh;
		return arr;
	}

	return Array();
}

This is because _update_shape() creates the missing root_mesh.

@Mathis-Z
Copy link

This might be a stupid question but what exactly is a gizmo? I thought the gizmo was the little handle you use to move/rotate objects in the editor but when I remove all functions related to updating/redrawing the gizmo apparently nothing happens.

@Calinou
Copy link
Member Author

Calinou commented May 12, 2022

This might be a stupid question but what exactly is a gizmo? I thought the gizmo was the little handle you use to move/rotate objects in the editor but when I remove all functions related to updating/redrawing the gizmo apparently nothing happens.

A gizmo is a helper that is drawn only in the editor. It can use any material, although shadeless lines and transparent planes are typically used. It can have manipulation handles (displayed in red), but it's not a strict requirement.

@KoBeWi
Copy link
Member

KoBeWi commented May 13, 2022

If the crash is really caused by aabbb40 then the fix is simply changing from 0 to SceneTree::GROUP_CALL_DEFERRED here

get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this);

There might be more calls that expect deferred mode.

@KoBeWi KoBeWi moved this to To Assess in 4.x Priority Issues May 13, 2022
@KoBeWi KoBeWi moved this from To Assess to In Progress in 4.x Priority Issues May 13, 2022
@Mathis-Z
Copy link

Or you can change this code:

if (cs->is_root_shape()) {
Array csg_meshes = cs->get_meshes();
Ref<Mesh> csg_mesh = csg_meshes[1];
if (csg_mesh.is_valid()) {
p_gizmo->add_collision_triangles(csg_mesh->generate_triangle_mesh());
}
}

to check whether there are csg_meshes:

if (cs->is_root_shape()) {
		Array csg_meshes = cs->get_meshes();
		if (csg_meshes.is_empty() == false) {
			Ref<Mesh> csg_mesh = csg_meshes[1];
			if (csg_mesh.is_valid()) {
				p_gizmo->add_collision_triangles(csg_mesh->generate_triangle_mesh());
			}
		}
	}

I checked how many times csg_meshes is empty by printing to the console and it is only once so this is just a problem with the gizmo not yet updated or something. Apparently the necessary update happens between the first and second call to CSGShape3DGizmoPlugin::redraw and after that everything is fine.

@adamscott
Copy link
Member

adamscott commented May 18, 2022

Or you can change this code:

@Mathis-Z Can you create a PR? It's pretty simple to do and you could become a contributor to the Godot source code.

@adamscott
Copy link
Member

There might be more calls that expect deferred mode.

Namely:

  • get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this);
  • get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_set_subgizmo_selection, this, p_gizmo, p_id, p_transform);
  • get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_clear_subgizmo_selection, this);

@KoBeWi This seems to fix too the issue with CSG nodes. Could you create a PR too?

@KoBeWi
Copy link
Member

KoBeWi commented May 18, 2022

Opened a PR: #61154
@Mathis-Z Feel free to open one too, if you have a better fix.

EDIT:
Well, it was merged...

@PetBom
Copy link

PetBom commented May 23, 2022

I can confirm this issue in Godot 3.5 rc1. Should I report a bug for 3.5 rc1 or is this backported/merged to the 3.5 branch?

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

Successfully merging a pull request may close this issue.

5 participants