How to multiple a 2D point with a 4D Matrix

2.1k views Asked by At

How can I convert a 2D point (or 3D with Z=0) to 2D point(where Z is ignored) with a 4D matrix ?

I am using Microsofts Silverlight to project a 2D control as pseudo 3D using a Matrix3D definition of Matrix3D

I know the initial 2D coordinate of a point in the untransformed control and I want the 2D position of the point after the transform.

The silverlight API is sparse regarding 3D methods.

Please suggest basic math to perform the calculation.

This is a follow on from a silverlight specific question

Edit further details

its not working. I am using

x = x0 * matrix[0][0] + y0 * matrix[1][0] + z0 * matrix[2][0] +
    w0 * matrix[3][0];

y = x0 * matrix[0][1] + y0 * matrix[1][1] + z0 * matrix[2][1] +
    w0 * matrix[3][1];

z = x0 * matrix[0][2] + y0 * matrix[1][2] + z0 * matrix[2][2] +
    w0 * matrix[3][2];

and the input x and y are 0,0 and the result x,y are 0, 58.5786 the matrix is

HasInverse  true    bool
IsIdentity  false   bool
M11 1.0 double
M12 0.0 double
M13 0.0 double
M14 0.0 double
M21 0.0 double
M22 0.70710676908493042 double
M23 0.70710676908493042 double
M24 0.0 double
M31 0.0 double
M32 -0.70710676908493042    double
M33 0.70710676908493042 double
M34 0.0 double
M44 1.0 double
OffsetX 0.0 double
OffsetY 58.578643798828125  double
OffsetZ -141.42135620117187 double

that produces a 45 degree angle rotation in Z where the rotation point is the bottom of the plane.

all the M1n values including OffsetX is 0.0 resulting in x always being the original value.

What am I doing wrong ?

Here are my four example values with the results of the above math

0, 0, 0, 1 -> 0, 58.5786437988281, -141.421356201172, 1
50, 0, 0, 1 -> 50, 58.5786437988281, -141.421356201172, 1
0, 100, 0, 1 -> 0, 129.289320707321, -70.7106792926788, 1
100, 100, 0, 1 -> 100, 129.289320707321, -70.7106792926788, 1

looking at the resulting image the 400x400 plane has a top left of 45,135 and top right of 355,135, bottom left is 0,400 and bottom right is 400,400

so for the test value of 0,0,0,1.0 I would expect x and y to 45,135

2

There are 2 answers

5
Jackson Pope On

I'm not sure if there's a shortcut for this but what you want is:

newX = oldx * mat.M11 + oldY * mat.M21 + mat.OffsetX;
newX = oldx * mat.M12 + oldY * mat.M22 + mat.OffsetY;

(assuming that your oldZ is zero and you're going to ignore the newZ value).

Edit: A better way to do it is:

Vector3D oldPos(oldx, oldy, 0.0f);
Vector3D newPos = oldPos * matrix;

Your new coordinates are: newPos.X and newPos.Y;

0
Stefan Dragnev On

Expand your 2D vector to a 4D vector - (X, Y, 0, 1); this is a 3D vector specified in homogeneous coordinates. Multiply the 4D vector by the 4D matrix thus getting a new 4D vector, from which you take the first 2 components.

If the matrix specifies some kind of perspective projection, then you'll need to divide by the last component, i.e. if your resulting vector is (x, y, z, w), then the final coordinates are (x/w, y/w, z/w). If the matrix doesn't have a perspective projection, then w = 1 and the final vector is just (x, y, z)