Rotate coplanar 3D points to XY

Hi,

I have a set of 3d points. All these points are on same plane. I have the Normal of the plane.

Now I need to rotate them in such a way that the Z value of all these points become zero.

I have googled a lot. I got very few results and most of them are very much mathematical. Few are about Projection and few are with solution with OpenGL APIs.

Please help me

Thanks in advance.

Do you want to simply “smush” the points into the XY plane using their projection? Or are you looking to preserve these points relative to their centerpoint, and place them on the XY plane as they would appear if the plane normal pointed towards the camera?

Hi @Drigax,
Thanks for responding.

I think, I did it. Not sure whether it is buggy or not. It would be great if someone reviews this code.
The code is implemented in C#.

private static readonly Vector3D Z_AXIS = new Vector3D(0, 0, -1);

        public static List<Vector2D> RotateCoplanar3DPointsToXY(IEnumerable<Vector3D> vectors, Vector3D planeNormal, out Matrix4x4? matrix)
        {
            if (planeNormal.EqualsWithErrorRange(Z_AXIS, Constants.EPSILON))
            {
                matrix = null;
                return new List<Vector2D>(vectors.Select(p=>new Vector2D(p.X, p.Y)));
            }

            var rotationAxis = Z_AXIS.Cross(planeNormal);
            rotationAxis.Normalize();
            var rotationAngle = (float)Math.Acos(Z_AXIS.Dot(planeNormal));
            matrix = Matrix4x4.FromAngleAxis(rotationAngle, rotationAxis);
            var transform = matrix.Value;
            var result = new List<Vector2D>();

            foreach (var vector in vectors)
            {
                var newVector = new Vector2D(vector.X * transform.A1 + vector.Y * transform.B1 + vector.Z * transform.C1, vector.X * transform.A2 + vector.Y * transform.B2 + vector.Z * transform.C2);
                result.Add(newVector);
            }
            return result;
        }

Wth is a dot product tbh? What is that even for

As the plane is only 4 points why not recreating it from width and height instead ?

This might be more efficient and simpler ?

Is your project going to be one that uses Babylon.js? If so I will create a playground using some Babylon.js tools

My application is a babylonjs game. but some logic and 3d mesh generation I am doing it in server as it has a lot of CSG related stuff. I cannot do such heavy work at client side as the devices might be low end.

1 Like

Just now tested my above code with more data. It is completely buggy.

Hi @sebavan, the plane may contain any number of points n where n>2.

You need to compute the plane matrix, invert it and multiply each position with it.
To compute the matrix, you have the normal, an origin (let’s say point[0]), vector A which is the difference between point[1] and origin, normalized, vector B (cross product of A and Normal).
The matrix will look like:
A.x, A.y, A.z, 0
Normal.x, Normal.y, normal.z, 0
B.x, B.y, B.z, 0
origin.x, origin.y, origin.z, 1
Invert that matrix, transform each point with it

1 Like

Old thread, but it seems there is not a proper answer to this yet :confused:

I tried to reproduce @Cedric answer in this playground and also tried alternative approaches, so far no luck:

the black version is correct, but not properly aligned. I would still like to align it by xAxis.

I am really surprised how difficult this task seems to be… any recommendations?

Here is my version:

Compute normal of set of points then compute the quaternion that ttransform the normal direction into (0,0,1). transform all points using that quaterion.

This is smooth, but my screenshot is not communicating well, what I wanted to achieve :roll_eyes:. The white and black rectangel should be on the same xz-plane, the white rectangle should align with the first line to the Forward vector.
My option would be, to create a second rotation, but I am still curious how to achieve this with one rotation only…

Did you check affine matrix transform?

1 Like

Hm there should be no sheering or reflection, the only thing I need is a proper quaternion.
If I compose a matrix, i only need a scale vector (1,1,1), translation vector (origin) and the quaternion.

What suprises me, is that none of Quaternion.FromLookDirectionLH, Quaternion.RotationQuaternionFromAxis, Matrix.FromXYZAxesToRef(…) give me proper results.

This is what I am aiming for, I would like to have the green result (white arrow), not the red result (black arrow)

woah -.- sorry for wasting your time!
my normal had y and z coordinates flipped, i think. Used your normal approach.
Now here is the playground with some additional helpers:

The blue line looks great: https://playground.babylonjs.com/#5LGNNK#4

2 Likes

I’m glad it works now :slight_smile:

2 Likes