Open levidavidmurray opened 7 months ago
I made some changes to align_with_normal
. Seems to align as expected now.
func align_with_normal(xform: Transform3D, n2: Vector3) -> Transform3D:
var n1 = xform.basis.y.normalized()
var cosa = n1.dot(n2)
if cosa >= 0.99:
return xform
var alpha = acos(cosa)
var axis = n1.cross(n2).normalized()
if axis == Vector3.ZERO:
axis = Vector3.FORWARD # normals are in opposite directions
return xform.rotated(axis, alpha)
To any future googlers: make sure to set the object's position again after calling align_with_normal
to prevent the object being out of place for a single frame.
There's always some level of approximation expected in physics engines for performance reasons, so some values being returned as near-zero when they should technically be zero sounds expected to me.
I searched for a solution to this for hours now. This worked in the end, but the position is mostly not correct afterwards. Just move the object after alignment and you're dandy.
Tested versions
Reproducible in 4.2.stable and 4.1.1.stable
System information
Godot v4.2.stable - Windows 10.0.22621 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1070 (NVIDIA; 31.0.15.3713) - AMD Ryzen 7 2700X Eight-Core Processor (16 Threads)
Issue description
Aligning object's Y-axis with collision normal results in scale (0, 0, 0) for specific normals
https://github.com/godotengine/godot/assets/46084870/74521573-962c-4ddd-a9fb-fbedcc6a2b40
Grey mesh (GM) contains the problematic "back wall" face. Red mesh (RM) works. Blue mesh (BM) works.
Expected Changing the object's alignment from GM "floor" face normal to GM "back wall" face normal should rotate the object as expected and maintain scale of 1.
Actual Changing the object's alignment from GM "floor" face normal to GM "back wall" face normal results in scale of
Vector3.ZERO
.Worth Mentioning
Vector3.ONE
after alignment reveals the transform is aligned with initial rotationVector3.ZERO
.(0, -0, 1)
, while the non-working GM "back wall" normal shows as(0, 0, 1)
IMPORTANT: While typing that last point, I came to the realization that the
y
value float in(0, -0, 1)
is truncated. Printing they
-value for the "back wall" normals that align properly results in-0.0000000437114
for BM and-0.00000005960464
for RM. GM is simply0
. All meshes are perfectly aligned in both Blender and Godot, so it seems this discrepancy is occurring elsewhere.I initially thought the alignment code I'm relying on fails when attempting to align to a perfectly aligned normal, but some of the other normals that alignment works with are perfectly aligned normals 🤔
Steps to reproduce
The grey mesh (GM) contains the seemingly problematic normals. It was created in blender by scaling a cube, deleting the front face, recalculating normals inside, applying all transforms, and exporting as gltf/glb (collider autogenerated with
-col
suffix). Generating collider separately within Godot makes no difference. Solidifying makes no difference.The red mesh (RM), while seemingly similar, doesn't contain any problematic normals. It was created in blender by rotating a plane 90 degrees on x-axis, extruding front face, deleting front face, recalculating normals inside, applying all transforms, and exporting as gltf/glb (collider auto-generated with
-col
suffix).The blue mesh (BM) is a primitive PlaneMesh made within Godot, collider generated via Mesh > Create Trimesh Static Body.
I'm attempting to align an object to a collision normal with the following function:
Example usage:
Minimal reproduction project (MRP)
normal_alignment_bug.zip