godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91k stars 21.17k forks source link

Crash in Bullet assert when using MeshInstance3D with create_convex_collision() #40505

Closed qarmin closed 4 years ago

qarmin commented 4 years ago

Godot version: 4.0.dev.custom_build. 9e34ba485

OS/device including version: Ubuntu 20.04

Issue description: Assert message

godot4: thirdparty/bullet/LinearMath/btVector3.h:305: btVector3& btVector3::normalize(): Assertion `!fuzzyZero()' failed.

Steps to reproduce:

  1. Run project

Minimal reproduction project: QQ.zip

qarmin commented 4 years ago

MeshInstance3D code

extends MeshInstance3D

func _process(delta) -> void:

    if randi() % 2 == 1:
        self.orthonormalize()
    if randi() % 2 == 1:
        self.rotate(get_vector3(), get_float())
    if randi() % 2 == 1:
        self.create_convex_collision()

    if randi() % 2 == 1:
        for i in self.get_children():
            i.queue_free()

const RANGE : int = 100

func get_float() -> float:
    return randf() * RANGE - RANGE / 2

func get_vector3() -> Vector3:
    return Vector3(get_float(),get_float(),get_float())
madmiraal commented 4 years ago

This is not actually a Bullet specific problem. It occurs in Godot physics too. Godot physics is (and Bullet physics before we applied the assert checks was) quite happy applying a Transform with zero values!

The problem arises when getting the new Node's global Transform: https://github.com/godotengine/godot/blob/513b39882ae44a5ee0ff0d9bb0c4ddf700449422/scene/3d/node_3d.cpp#L256-L278 The local Transform is valid, but it multiplies it by the parent's Transform here: https://github.com/godotengine/godot/blob/513b39882ae44a5ee0ff0d9bb0c4ddf700449422/scene/3d/node_3d.cpp#L265 It's the parent's local Transform that is invalid and returns zeros, which then cascades until the assert catches it.

What I can't work out yet, is why the parent sometimes has a Transform of zeros, because the default is not: https://github.com/godotengine/godot/blob/27d12092821df77a6186d2fd54055c54beefbea0/core/math/basis.h#L257-L267

qarmin commented 4 years ago

Local transform equal to zero is set it minimal project here by t.basis.rotate(p_axis, p_angle); https://github.com/godotengine/godot/blob/b2096ba53eb422ae2fbf8b49cf1f4806878127fb/scene/3d/node_3d.cpp#L573-L577