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

Add ability to get face index and barycentric coordinates from raycast #71233

Merged
merged 1 commit into from
Aug 3, 2023

Conversation

PrecisionRender
Copy link
Contributor

@PrecisionRender PrecisionRender commented Jan 11, 2023

Implements godotengine/godot-proposals#4663, #684, #1903, portion of #17665

Closes godotengine/godot-proposals#4663

This PR implements a way to get the barycentric coordinates of a collision object from a ray. To do this, we return the intersected face index from a ConcaveCollisionShape3D and expose a barycentric coordinate function. This allows for the user to get much more detail from a ray than simply the collision point and normal. Check the surface alignment example below.

Alignment using RayCast normal:

wo_bary_coords.mp4

Alignment using barycentric coordinate interpolation:

w_bary_coords.mp4

Test project: Barycentric Coords Test.zip

@thismarty
Copy link

thismarty commented Feb 8, 2023

Is this implemented in Godot 4 RC1?

Calls to 'get_triangle_barycentric_coords' stills don't appear to work.

@thismarty
Copy link

Darn, I just noticed that it is still pending review before merging.

Sure hope it gets merged soon. But I guess it's going to have to wait for Godot 4.1 now?

@PrecisionRender
Copy link
Contributor Author

@thismarty I can't find a related/similar feature in the RC1 release notes. The barycentric coordinate function still works for me.

@PrecisionRender
Copy link
Contributor Author

PrecisionRender commented Feb 8, 2023

Sure hope it gets merged soon. But I guess it's going to have to wait for Godot 4.1 now?

Unfortunately so, I guess. Kind of a shame, though. This has been open and ready to merge for a while now. But I did open this after the feature freeze.

@thismarty
Copy link

Dangit. Oh well, thanks a bunch for implementing it - it will be very useful once merged!

adamscott
adamscott previously approved these changes Mar 5, 2023
Copy link
Member

@adamscott adamscott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks fine to me. Can you rebase and test just to make sure it works with the latest code?

@PrecisionRender PrecisionRender requested review from a team as code owners March 5, 2023 21:59
Copy link
Member

@AThousandShips AThousandShips left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, haven't tested so TIWAGOS but looks correct

Comment on lines +76 to +86
<method name="get_triangle_barycentric_coords">
<return type="Vector3" />
<param index="0" name="point" type="Vector3" />
<param index="1" name="a" type="Vector3" />
<param index="2" name="b" type="Vector3" />
<param index="3" name="c" type="Vector3" />
<description>
Returns a [Vector3] containing weights based on how close a 3D position ([param point]) is to a triangle's different vertices ([param a], [param b] and [param c]). This is useful for interpolating between the data of different vertices in a triangle. One example use case is using this to smoothly rotate over a mesh instead of relying solely on face normals.
[url=https://en.wikipedia.org/wiki/Barycentric_coordinate_system]Here is a more detailed explanation of barycentric coordinates.[/url]
</description>
</method>
Copy link
Member

@kleonc kleonc Aug 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should likely mention:

  • what's a valid input (a, b, c forming a triangle and point being coplanar with the abc triangle),
  • what's the behavior for an invalid input (a, b, c not forming a valid triangle, or point being not coplanar with the abc triangle).

(But it's a non-blocker, can be improved later, separately)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's delegate this to a follow-up. This has been cooking long enough :)

Copy link
Contributor Author

@PrecisionRender PrecisionRender Aug 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can open a new PR for this. Does an issue need to be created?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PrecisionRender No, just link back to this comment discussion and the PR

@YuriSizov YuriSizov merged commit a56e960 into godotengine:master Aug 3, 2023
@YuriSizov
Copy link
Contributor

Thanks a lot!

@PrecisionRender PrecisionRender deleted the barycentric-coords branch August 3, 2023 22:56
@Zireael07
Copy link
Contributor

Yay I can already see uses for this <3

@Corruptinator
Copy link
Contributor

Corruptinator commented Aug 6, 2023

AWESOME! Can't wait so see this feature implemented in Godot. Now it's just a matter of time before someone recreates an F-Zero style game in Godot.

@Zireael07
Copy link
Contributor

I am rather thinking of doing shadow detection this way (instead of raycasting towards the sun) :)

@PrecisionRender
Copy link
Contributor Author

AWESOME! Can't wait so see this feature implemented in Godot. Now it's just a matter of time before someone recreates an F-Zero style game in Godot.

@Corruptinator Already implemented. It should be fully ready for the 4.2 release. 😁

@Corruptinator
Copy link
Contributor

I am rather thinking of doing shadow detection this way (instead of raycasting towards the sun) :)

Oh, that is a good point @Zireael07. You're right. So many uses for Barycentric Coordinates.

@mihe
Copy link
Contributor

mihe commented Aug 8, 2023

@YuriSizov

This PR seems to have introduced a breaking change to GDExtension without anyone realizing.

Any changes to PhysicsDirectSpaceState3D::RayResult needs to have the same change made to the struct bindings in register_server_types.cpp:

struct RayResult {
Vector3 position;
Vector3 normal;
int face_index = -1;
RID rid;
ObjectID collider_id;
Object *collider = nullptr;
int shape = 0;
};

GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionRayResult, "Vector3 position;Vector3 normal;RID rid;ObjectID collider_id;Object *collider;int shape");

... which would likely trigger a --validate-extension-api failure with how RayResult is laid out right now.

I'm not sure there's a perfect way to solve this, since you're changing the format/size of the struct no matter which way you turn it, which will likely upset --validate-extension-api, but moving face_index to the end of RayResult would at least preserve backwards compatibility as far as intersect_ray is concerned I guess.

@YuriSizov
Copy link
Contributor

YuriSizov commented Aug 8, 2023

@mihe Are you saying that GDExtension API is sensitive to the order of elements we return in Dictionary? Or is this exposed in some other way to GDExtension? And if so, how come it's not validated on the CI right now, how does it fall through the cracks? I don't quite understand.

@mihe
Copy link
Contributor

mihe commented Aug 8, 2023

There is no Dictionary involved. RayResult is a struct on both ends, but called PhysicsServer3DExtensionRayResult in GDExtension, and its binary layout is described through GDREGISTER_NATIVE_STRUCT.

As of right now, the RayResult struct layout differs from the struct layout of PhysicsServer3DExtensionRayResult after the normal field, leading to anyone writing to (for example) the rid field from GDExtension to unknowingly write over face_index instead, and so forth.

And if so, how come it's not validated on the CI right now, how does it fall through the cracks?

It is, but only if you actually make the corresponding change to the GDREGISTER_NATIVE_STRUCT binding mentioned previously, in which case you'll be met with:

Validate extension JSON: Error: Field 'native_structures/PhysicsServer3DExtensionRayResult': format changed value in new API, from "Vector3 position;Vector3 normal;RID rid;ObjectID collider_id;Object *collider;int shape" to "Vector3 position;Vector3 normal;int face_index;RID rid;ObjectID collider_id;Object *collider;int shape".

This should obviously/ideally be dealt with in a less brittle and error-prone way, maybe using some macro magic, as opposed to typing in the layout into a string somewhere. It's not the first time this has happened, and probably won't be the last, unless this is changed.

@YuriSizov
Copy link
Contributor

@mihe Could you create an issue for this so we don't lose track of it?

@mihe
Copy link
Contributor

mihe commented Aug 9, 2023

Issue created, with MRP: #80444

@Corruptinator

This comment was marked as off-topic.

@Calinou

This comment was marked as off-topic.

@rburing

This comment was marked as off-topic.

@Corruptinator
Copy link
Contributor

Understood. Sorry for the non-related message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet