1

I have a plane between 3 points and want to get a transformation matrix which allows conversion of other points in the plane to 2D coordinates. What might be of influence is that the plane that points A B and C form does not go through the coordinate system's origin.

I have tried adapting the following answer https://stackoverflow.com/a/49771112/13620003 into the following code:

private static Matrix4x4 Get3DPoint3DPlaneAs2DPointProjectionMatrix(Vector3 pointA, Vector3 pointB, Vector3 pointC)
        {
            // Adapted from https://stackoverflow.com/questions/49769459/convert-points-on-a-3d-plane-to-2d-coordinates

            var vectorAB = pointB - pointA;
            var vectorAC = pointC - pointA;

            var vectoruN = Vector3.Cross(vectorAB, vectorAC).normalized;
            var vectorU = vectorAB.normalized;
            var vectorV = Vector3.Cross(vectorU, vectoruN);

            var vectoru = pointA + vectorU;
            var vectorv = pointA + vectorV;
            var vectorn = pointA + vectoruN;

            var matrixS = new Matrix4x4(
                new Vector4(pointA.x, pointA.y, pointA.z, 1),
                new Vector4(vectoru.x, vectoru.y, vectoru.z, 1),
                new Vector4(vectorv.x, vectorv.y, vectorv.z, 1),
                new Vector4(vectorn.x, vectorn.y, vectorn.z, 1)
            );


            var matrixD = new Matrix4x4(
                new Vector4(0, 0, 0, 1),
                new Vector4(1, 0, 0, 1),
                new Vector4(0, 1, 0, 1),
                new Vector4(0, 0, 1, 1)
            );

            var matrixM = matrixD * matrixS.inverse;

            return matrixM;

        }

However unlike https://stackoverflow.com/a/49771112/13620003 states, if I apply the matrix to a point in the plane the z component of the resulting point is not 0, and still denotes the original height(z) of the point. If anyone can spot the error, or suggest Unity specific improvements it would be much appreciated.

Ken White
  • 123,280
  • 14
  • 225
  • 444
mmjr-x
  • 51
  • 3
  • When you add the Unity tag, it is not necessary to repeat Unity in the post title or body. The tag clearly tells everyone that your question is about Unity. The tag system here is very efficient, and doesn't need any help. Repeating the information over and over again is just repetitive noise. – Ken White Jul 24 '21 at 01:27
  • So what is supposed to be the plane "origin" position? A plane is an infinite mathematical construct ... It also has no information about rotation or scale .. so not sure if a Matrix is actually useful here – derHugo Jul 24 '21 at 02:44
  • @derHugo The 3 points that you provide are supposed to provide that information. They define the plane, translation of the coordinate system and the rotation of the coordinate system in such a way matrixM * pointA = (0,0,0) and matrixM * pointB = (vectorAB.magnitude,0,0) or at-least they are supposed to if I understand https://stackoverflow.com/a/49771112/13620003 correctly. – mmjr-x Jul 24 '21 at 11:09

1 Answers1

2

Figured it out, I was able to adapt the first part of this answer https://stackoverflow.com/a/52163563/13620003 (major credit to @Spektre for his excellent answer) into the following implementation (could use some optimization tough):

private static Matrix4x4 Get3DPoint3DPlaneAs2DPointProjectionMatrix2(Vector3 point0, Vector3 point1, Vector3 point2)
        {
            // Adapted from https://stackoverflow.com/a/52163563/13620003

            var x = point1 - point0;
            x.Normalize();
            var y = point2 - point0;
            var z = Vector3.Cross(x, y);
            z.Normalize();
            y = Vector3.Cross(z, x);
            y.Normalize();
            var o = point0;

            return new Matrix4x4(
                new Vector4(x.x, x.y, x.z, 0),
                new Vector4(y.x, y.y, y.z, 0),
                new Vector4(z.x, z.y, z.z, 0),
                new Vector4(o.x, o.y, o.z, 1)
            );

        }

When inputting the global coordinates of points A B and C (as point0, point1 and point2) into the method, the resulting matrix matrixM can be used to convert coordinates in the global coordinate system to the local coordinate system using var localCoordinate = matrixM.inverse.MultiplyPoint3x4(globalCoordinate).

If the globalCoordinate resides in the plane described by points A B and C global coordinates the resulting localCoordinate will have a z component of 0.

You can also convert local back to global coordinates using var globalCoordinate = matrixM.MultiplyPoint3x4(localCoordinate)

mmjr-x
  • 51
  • 3