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

Ray-casts do not support face_index #702

Open
mihe opened this issue Dec 1, 2023 · 5 comments
Open

Ray-casts do not support face_index #702

mihe opened this issue Dec 1, 2023 · 5 comments
Labels
enhancement New feature or request external Involving an external party topic:runtime Concerning runtime behavior (or its source code)

Comments

@mihe
Copy link
Contributor

mihe commented Dec 1, 2023

This extension does not currently support the face_index field found in the result dictionary of intersect_ray, as seen in its documentation.

This was something introduced in Godot 4.2 (godotengine/godot#71233) which lets you get the index of any face/triangle of a ConcavePolygonShape3D that the ray-cast hit.

While Jolt does have support for getting the vertices of a particular face, there's no public interface for getting the actual triangle index of it. Even if there was, the process of "indexifying" the triangles that happens as part of creating Jolt's JPH::MeshShape means that any index you return from Jolt won't map to the actual list of faces originally set on the ConcavePolygonShape3D anyway, which this face_index thing relies entirely upon.

This is unlikely to ever be supported by this extension in its current form.

@github-actions github-actions bot added the needs triage Something that needs investigation label Dec 1, 2023
@mihe mihe added enhancement New feature or request topic:runtime Concerning runtime behavior (or its source code) external Involving an external party and removed needs triage Something that needs investigation labels Dec 1, 2023
@MarioBossReal
Copy link

MarioBossReal commented Apr 7, 2024

I'm wondering if this feature is still not planned to be supported, since this is an important feature to have especially if you have a surface property index per mesh triangle.

Even if there was, the process of "indexifying" the triangles that happens as part of creating Jolt's JPH::MeshShape means that any index you return from Jolt won't map to the actual list of faces originally set on the ConcavePolygonShape3D anyway, which this face_index thing relies entirely upon.

Assuming that the actual vertex count/positions remain the same, would it not be possible to create a mapping between the original vertices and the indexed vertices? I don't really see how the input mesh could differ from the (optimised?) mesh apart from re-indexed vertices.

The triangle index of a godot physics mesh is (roughly, this function probably has issues) int(index/3), since the whole mesh is just a 1D buffer of vertices. I think the easiest solution would be to create a new buffer alongside the vertex buffer (when it gets indexified) that stores the original face index (or vertex index if its easier) from the godot mesh, indexed ofcourse by the same index buffer. Then getting the original face would be as simple as FaceBuffer[index].

Actually that probably wouldnt work since the vertex buffer could be any size. Wouldn't the offset value of the current index correspond to the original index though? As far as I understand, if a mesh has n vertices (before indexing), there has to be n indices after it gets indexified. Even though the value stored at Index[i] corresponds to a position from a shrunken vertex buffer, the actual position [i] should match the original vertex's index so long as no weird swapping/reordering etc occurs?

@mihe
Copy link
Contributor Author

mihe commented Apr 7, 2024

so long as no weird swapping/reordering etc occurs?

While I believe Jolt's indexing currently preserves the same order as the input list of triangles (which is an assumption I would be hesitant about relying on since it could presumably change at any time) the thing that does throw a wrench into this is the fact that Jolt culls degenerate faces, which will obviously offset all subsequent indices.

It might be that I could do the culling of degenerate faces on my end, and hang on to their indices in order to undo any such offset, but that's frankly making a lot of assumptions about Jolt's indexing, which again could presumably change at any point.

In any case, this is moot so long as Jolt doesn't hang on to the actual triangle index in its MeshShape, which to me seems quite fundamental to its design not to do. Its SubShapeID (which is provided as part of its RayCastResult) is already meant to serve the purpose of getting things like the face normal as well as any per-face material index, but this ID doesn't really map to the input geometry in any way.

The only fix I can see, without changing how this works on the Godot side of things, would be to fork/change Jolt and either repurpose/extend its existing 5-bit Triangle::mMaterialIndex (which is unused by this extension) to hold the triangle index instead, or adding another index alongside that's similarly preserved through the indexing process. Either one strikes me as quite a scary (and potentially costly) change though, and is not something I'm eager to do right now.

The change I've had in mind is to instead make a PR to Godot to add the face vertices as part of its ray-cast results. While this would largely make face_index redundant for the purposes it was originally meant for, it obviously wouldn't do much to help your situation if you're keeping some list of per-face materials separately on your end.

@MarioBossReal
Copy link

Its SubShapeID (which is provided as part of its RayCastResult) is already meant to serve the purpose of getting things like the face normal as well as any per-face material index, but this ID doesn't really map to the input geometry in any way.

Would it make sense or be possible to have custom data channels within the physics mesh that get baked alongside the indexing process, similar to how ArrayMeshes have various buffers like position, color, custom0/1/2 etc? This might be more of a general Godot PR type deal rather than jolt specifically. Are face normals for physics meshes baked into a buffer or are they calculated at runtime?

The change I've had in mind is to instead make a PR to Godot to add the face vertices as part of its ray-cast results. While this would largely make face_index redundant for the purposes it was originally meant for, it obviously wouldn't do much to help your situation if you're keeping some list of per-face materials separately on your end.

Do you mean only returning the position values of the vertices, or the actual indices themselves which could be used to index into various buffers? There's a bit of a gap here because as far as I know Godot physics meshes aren't indexed and don't really store any data besides position data. Maybe behind the scenes Godot bakes some data like face normals etc but I'm not sure.

I think what this problem is bringing up however is a solid reason to be able to store different channels in physics meshes just as you would in a render mesh. If returning a face index which corresponds to the input mesh isn't possible, I think that's okay as long as there is a way to add in more data, which is something that Godot itself will have to support.

@mihe
Copy link
Contributor Author

mihe commented Apr 8, 2024

Would it make sense or be possible to have custom data channels within the physics mesh that get baked alongside the indexing process, similar to how ArrayMeshes have various buffers like position, color, custom0/1/2 etc? This might be more of a general Godot PR type deal rather than jolt specifically.

It doesn't really matter what you add on the Godot side of things. The only per-face properties I can provide as part of the ray-cast results is the normal, vertex positions and material index (which again is not used by this extension). Anything else I will have no choice but to leave at its default value.

Are face normals for physics meshes baked into a buffer or are they calculated at runtime?

They're calculated at runtime.

(triangle_idx seen there is not in fact the triangle index, but an index into the acceleration structure used by Jolt.)

Do you mean only returning the position values of the vertices, or the actual indices themselves which could be used to index into various buffers?

Only the position values, yes.

There's a bit of a gap here because as far as I know Godot physics meshes aren't indexed and don't really store any data besides position data. Maybe behind the scenes Godot bakes some data like face normals etc but I'm not sure.

They do calculate it behind the scenes, yes.

@MarioBossReal
Copy link

Thanks for your replies. I guess it's probably much more effort than it's worth at this stage to support getting (godot) face indices. For now I've decided to just split up my multi-material physics meshes into separate meshes by collecting all tris with the same surface property index and building a new mesh shape out of them. It seems to work well, and might even improve performance a little by cutting up very large map meshes into smaller ones.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request external Involving an external party topic:runtime Concerning runtime behavior (or its source code)
Projects
None yet
Development

No branches or pull requests

2 participants