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

Barycentric Coordinates from Raycasting to calculate any Tri-Mesh face's position and rotation for smooth movement on floors, walls, or rollercoaster-like paths, (A.K.A. Anti-Gravity or Wallwalking) #4663

Closed
Corruptinator opened this issue Jun 12, 2022 · 6 comments · Fixed by godotengine/godot#71233
Milestone

Comments

@Corruptinator
Copy link

Corruptinator commented Jun 12, 2022

Describe the project you are working on

This is a side project that I mess around on my free time: "A futuristic driving simulation within Godot that emulates anti-gravity physics such as F-Zero"

Link to demo-project (Currently Broken): https://github.com/Corruptinator/G-Zero [Admittedly I haven't analyzed/looked at this in years]

Describe the problem or limitation you are having in your project

Godot currently has no function to allow objects to optimally rotate/allign the object based on where raycast is colliding on any mesh or tri-mesh's normals.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

I think what will help is the ability to utilize Barycentric Coordinates in any Raycast nodes, which will calculate the position of any Tri-Mesh's point using the Tri-Mesh face's vertices to determine the point of position and rotation:

image

Here are two videos that made me realize that Barycentric Coordinates from raycasting has potential:
https://www.youtube.com/watch?v=Oj_eBEVNZ6o (Low-Poly Mesh driving Example)
https://www.youtube.com/watch?v=UhJUn3vyPx8 (F-Zero Driving Physics using Barycentric Coordinates Unity Example)

Based on the two videos I've ran into and analyzed the way the process works (even on Low-Poly meshes) it uses the vertices from the face normal (Must be triangle/tri) and interpolate them with the barycentric coordinates to calculate the rotation, position, and movement.

This would help overcome the problem of finding a way for movable objects such as flying cars or wall walking characters to move and rotate optimally based on the tri-mesh's normals, even on walls (A.K.A. F-Zero or Super Mario Galaxy).

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

The way I see how it will work is that 3D raycast will utilize an additional function, whether the raycast is colliding against the object or not: raycast.get_barycentric_coordinates(), then it will calculate the tri-face normal using the 3 vertices from their own global_position, and calculate the point through this formula: P = uA + vB + wC

P.S. (Colliding mesh must be "Tri-Mesh"! and the raycast must also determine whether the normal is Triangle, not Quad or N-Gon it is based on the colliding mesh)

Next we can interpolate the normal from the same raycast onto the forumated barycentric coordinates to get the results:

(Pseudo Code):

var raypoint = get_node("raycast").get_collision_point()

func _get_barycentric_coordinates():
     for n in mesh.normals.range():
          if n.get_normal() = get_node("Raycast").get_collision_normal():
               if n.get_normal(). is_tri():
                    var A = Vector3()
                    var B = Vector3()
                    var C = Vector3()
               
               **_var P = A.distance_to(raypoint) + B.distance_to(raypoint) + C.distance_to(raypoint)_**

     return P

var bc = get_node("Raycast").get_barycentric_coordinates()
var nm = get_node("Raycast").get_collision_normal()

if raycast.is_colliding():
     t = delta * 0.4

    **_calculation = nm.linear_interpolate(bc, t)_**
    #or...
    calculation = nm.linear_interpolate(bc, t)

If this enhancement will not be used often, can it be worked around with a few lines of script?

"There is currently no script alternative that will make the Barycentric Coordinate interpolation/calculation work..."

Is there a reason why this should be core and not an add-on in the asset library?

"This would allow users to utilize the ability to allow objects to be capable of traversing/explore around not only on floors but on walls. (As mentioned: Anti-Gravity/ Wallwalking)

@Corruptinator Corruptinator changed the title Barycentric Coordinates from Raycasting to calculate any Tri-Mesh face's position and rotation, (A.K.A. Anti-Gravity or Wallwalking) Barycentric Coordinates from Raycasting to calculate any Tri-Mesh face's position and rotation for smooth movement on floors, walls, or rollercoaster paths, (A.K.A. Anti-Gravity or Wallwalking) Jun 12, 2022
@Corruptinator Corruptinator changed the title Barycentric Coordinates from Raycasting to calculate any Tri-Mesh face's position and rotation for smooth movement on floors, walls, or rollercoaster paths, (A.K.A. Anti-Gravity or Wallwalking) Barycentric Coordinates from Raycasting to calculate any Tri-Mesh face's position and rotation for smooth movement on floors, walls, or rollercoaster-like paths, (A.K.A. Anti-Gravity or Wallwalking) Jun 12, 2022
@Parthmahajan29

This comment was marked as off-topic.

@Zireael07

This comment was marked as off-topic.

@Parthmahajan29

This comment was marked as off-topic.

@Corruptinator

This comment was marked as off-topic.

@Zireael07

This comment was marked as off-topic.

@Corruptinator
Copy link
Author

Been trying to find other ways to calculate the collision Tri-Mesh, but to avail no luck:

extends Spatial


# Declare member variables here. Examples:
# var a = 2
# var b = "text"
var exported = Vector3()



# Called when the node enters the scene tree for the first time.
func _ready():
	get_node("AnimationPlayer").play("New Anim (copy)")
	pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	
	var calc = Vector3.UP.cross($RayCast.get_collision_normal()).normalized()
	#var calc = $RayCast.get_collision_normal()
	var rodn = acos(Vector3.UP.dot($RayCast.get_collision_normal()))
	
	
	print(calc)

	#get_node("../Spatial2").global_rotation = get_node("../Spatial2").global_rotation.linear_interpolate(calc,.2)
	get_node("../Spatial2").global_rotation = calc

	pass

output

You can check out the project file if you like, its mostly the capsule with the green arrow not alligning correctly with the purple sphere moving forth and back in the background that uses a raycast on a rollercoaster-esque track:

Barycentric.zip

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

Successfully merging a pull request may close this issue.

5 participants