- Home /
Problem with transform.InverseTransformDirection and non-uniform scale
I made the plane to work with mesh vertices
var plane = new Plane(
hit.transform.InverseTransformDirection(normal),
hit.transform.InverseTransformPoint(position)
);
If the object has the uniform scale then all looks good
but otherwise the plane normal has weird angle and I don't understand why.
with.InverseTransformVector even worser. The angle goes 2 times bigger
Blue line - my plane
Green spheres - plane intersections
white sphere - plane center
UPDATE
There is code to reproduce
Place component to default cube in zero position, rotate it with Y != 0, scale ONE horizontal dimesion. You will see onesided plane.
using UnityEngine;
public class PlaceOnCube : MonoBehaviour
{
public Vector3 PlaneOrigin = new Vector3(0, 0, 0);
public Vector3 PlaneNormal = new Vector3(1, 0, 0);
private void OnDrawGizmos()
{
Gizmos.DrawSphere(PlaneOrigin, .03f);
var plane = new Plane(
transform.InverseTransformDirection(PlaneNormal),
transform.InverseTransformPoint(PlaneOrigin)
);
ReGeneratePlane(plane);
}
private void ReGeneratePlane(Plane plane)
{
var meshfilter = transform.GetComponent<MeshFilter>();
var mesh = meshfilter.mesh;
var tris = mesh.triangles;
var verts = mesh.vertices;
var newTris = new int[36 + 6];
var newVerts = new Vector3[24 + 4];
for (int j = 0; j < verts.Length; j++)
newVerts[j] = verts[j];
newVerts[24] = plane.ClosestPointOnPlane(new Vector3(-2, -1, 0));
newVerts[25] = plane.ClosestPointOnPlane(new Vector3(2, -1, 0));
newVerts[26] = plane.ClosestPointOnPlane(new Vector3(-2, 1, 0));
newVerts[27] = plane.ClosestPointOnPlane(new Vector3(2, 1, 0));
for (int j = 0; j < tris.Length; j++)
newTris[j] = tris[j];
newTris[36] = 24;
newTris[37] = 26;
newTris[38] = 25;
newTris[39] = 26;
newTris[40] = 27;
newTris[41] = 25;
mesh.vertices = newVerts;
mesh.triangles = newTris;
meshfilter.mesh = mesh;
}
}
re:
transform.GetComponent<MeshFilter>();
off-topic, but GetComponent() is a member of Component, which is a baseclass of MonoBehavior, which your own class is, so you can just do GetComponent() without the transform.
regarding your question, it's unclear to me what your goal is. ie, given this cube, what do you want to achieve ?
I know about GetComponent, it's just fast copypasted dirty test code. Problem with plane, it sholud stay still on cube rotation, like in first gif.
Answer by Namey5 · Mar 05, 2021 at 07:28 AM
What's happening is that your plane's normal vector is being scaled with the object's transformation. In this case vector magnitude doesn't matter, however if it was you would also notice that the vector grows and shrinks. The solution for this is to essentially 'invert' the scale that's being applied.
Your line
transform.InverseTransformDirection(PlaneNormal)
is doing this behind the scenes;
transform.worldToLocalMatrix.MultiplyVector (PlaneNormal)
To fix the scaling, we instead need to transform the vector by the inverse-transpose of the same matrix;
transform.worldToLocalMatrix.inverse.transpose.MultiplyVector (PlaneNormal)
The inverse of the worldToLocalMatrix is just the opposite transformation, so we can use this instead;
transform.localToWorldMatrix.transpose.MultiplyVector (PlaneNormal)
If you want to read more, this article has a good explanation;
https://paroj.github.io/gltut/Illumination/Tut09%20Normal%20Transformation.html
Where do you found info worldToLocalMatrix.MultiplyVector? In github in unity source code method InverseTransformDirection is external and hidden.
It's an industry-standard implementation - I don't work for Unity nor can I see their source code, but that's just how these transformations are done.
Your answer
Follow this Question
Related Questions
Looking at a target in 2D 0 Answers
[MATH] Vectors, magnitudes, and bears; Oh My! -Solved 2 Answers
Quick Math Help with Normalized numbers 2 Answers
Unity thinks that 14 = 15? 1 Answer
Move an object to a specific distance 0 Answers