godotengine / godot

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

vulkan - 4.0 dev - SoftBodies are broken #33485

Closed TheMoye closed 3 years ago

TheMoye commented 5 years ago

Godot version: Godot Engine v4.0.devel.custom_build.d6abb52db (updated on 08-11-2019)

OS/device including version: Windows 10 64bits

Issue description: Adding a mesh to a SoftBody in scene returns errors :

ERROR: set_soft_mesh: Condition ' !(soft_mesh->surface_get_format(0) & VisualServer::ARRAY_FORMAT_INDEX) ' is true. At: modules\bullet\soft_body_bullet.cpp:132

Sometimes followed by the following error :

ERROR: clean_up_dependencies: Condition ' !F ' is true. Continuing..: At: ./servers/visual/rasterizer.h:177

And by this for QuadMesh and PlaneMesh :

ERROR: invert: Condition ' det == 0 ' is true. At: core\math\basis.cpp:69

Avoids the scene from starting returns the following errors :

ERROR: Size of data provided (768) does not match expected (864) At: servers\visual\rasterizer_rd\rasterizer_storage_rd.cpp:1872 ERROR: mesh_get_surface: Index (uint32_t)p_surface=0 out of size (mesh->surface_count=0) At: servers\visual\rasterizer_rd\rasterizer_storage_rd.cpp:1990 ERROR: mesh_create_arrays_from_surface_data: Condition ' vertex_data.size() == 0 ' is true. returned: Array() At: servers\visual_server.cpp:1561 ERROR: operator[]: FATAL: Index p_index=0 out of size (((Vector<T> *)(this))->_cowdata.size()=0) At: ./core/vector.h:49 ERROR: _get_socket_error: Socket error: 10054 At: drivers\unix\net_socket_posix.cpp:198

Steps to reproduce: Add a SoftBody to a scene and assign it a Mesh

Minimal reproduction project:

jedStevens commented 4 years ago

I am also getting this on 3.2 with a mesh from blender. I am guessing that Godot's internal meshes are generated with a different index format than the GLTF exporter/importer does; this is because when I replace my character's cape with a plane, it works fine. The softbody code should be able to handle other index formats.

I was taking a look into this and it comes down to the function set_trimesh_body_shape in the file modules/bullet/soft_body_bullet.cpp which needs to be passed indices and positions. I'm not to familiar with how meshes get formatted on import, but is there some way to do this for all mesh formats? I'm not entirely sure why there was an ERR_COND_FAIL there to catch for this.

Here is a snippet of code I'm talking about.

modules/bullet/soft_body_bullet.cpp:118

void SoftBodyBullet::set_soft_mesh(const Ref<Mesh> &p_mesh) {

    if (p_mesh.is_null())
        soft_mesh.unref();
    else
        soft_mesh = p_mesh;

    if (soft_mesh.is_null()) {

        destroy_soft_body();
        return;
    }

    Array arrays = soft_mesh->surface_get_arrays(0);
    ERR_FAIL_COND(!(soft_mesh->surface_get_format(0) & VS::ARRAY_FORMAT_INDEX));
    set_trimesh_body_shape(arrays[VS::ARRAY_INDEX], arrays[VS::ARRAY_VERTEX]);
}

The code seems reasonable except for I'm not sure why there is this error catch here. Is there not a way around this?

EDIT: I'm using the current 3.2 branch

AdamRatai commented 4 years ago

Same problem on Windows 10 3.2 / 3.2.1. I can use internal godot meshes, but it's not working with anything imported.

jedStevens commented 4 years ago

I think I have a solution for this and I'm writing it here to take note while I'm at work.

Since there seems to be two cases, one where mesh indices are in the generated surface arrays and one where they are not.

Since the is already handling the case of indices being there, the second case could just be an array from 0..n where n is the size of the vertex array.

From my understanding, the faces of a mesh are defined using vertex indices, which would make sense for generated meshes, meaning you could have an algorithm for point generation and create triangles using some derived function for faces based on the indices, meaning they don't map up directly.

Because of the above, I imagine blender is giving us meshes that have their data in order and thus lack the indices array. This is why I think we could generate an array which is a sequence of ints from 0 to n on the fly and not create errors.

I'll try this later tonight but I have hopes that should fix this issue.

If any of my assumptions are wrong feel free to correct me.

jedStevens commented 4 years ago

Ok, I'm working on a solution, I've got passed the breaking and now I just need to figure out why its producing strange results in the simulation. What I mentioned in the last comment works, but for some reason gravity has reversed.

I will investigate further and open a PR when it is ready.

EDIT ----------------------- I just found that the solution I have currently is just not applying the transform to the mesh; it is simulating in local space. I'm not sure why the indices would cause this issue....

pouleyKetchoupp commented 3 years ago

Fixed in #46937