How to ensure that the vector in homogeneous coordinates is still a vector after transformation

Viewed 92

I performed an MVP transformation on the vertices of the model. In theory, I must apply the inverse transpose matrix of the MVP transformation to the normal.

This is the derivation process:

(A, B, C) is the normal of the plane where the point (x, y, z) lies enter image description here

For a vector, such as (x0, y0, z0), it is (x0, y0, z0, 0) in homogeneous coordinates. After transformation, it should still be a vector, like (x1, y1, z1, 0), This requires that the last row of the 4 * 4 transformation matrix is all 0 except for the elements in the last column, otherwise it will become (x1, y1, z1, n) after the transformation.

In fact, my MVP transformation matrix cannot satisfy this point after undergoing inverse transpose transformation.

Code:

Mat<4, 4> View(const Vec3& pos){
    Mat<4, 4> pan{1, 0, 0, -pos.x,
                0, 1, 0, -pos.y,
                0, 0, 1, -pos.z,
                0, 0, 0, 1};
    Vec3 v = Cross(camera.lookAt, camera.upDirection).Normalize();
    Mat<4, 4> rotate{v.x, v.y, v.z, 0,
                     camera.upDirection.x, camera.upDirection.y, camera.upDirection.z, 0,
                     -camera.lookAt.x, -camera.lookAt.y, -camera.lookAt.z, 0,
                     0, 0, 0, 1};
    return rotate * pan;
}

Mat<4, 4> Projection(double near, double far, double fov, double aspectRatio){
    double angle = fov * PI / 180;

    double t = -near * tan(angle / 2);
    double b = -t;
    double r = t * aspectRatio;
    double l = -r;

    Mat<4, 4> zoom{2 / (r - l), 0, 0, 0,
                    0, 2 / (t - b), 0, 0,
                    0, 0, 2 / (near - far), 0,
                    0, 0, 0, 1};
    Mat<4, 4> pan{1, 0, 0, -(l + r) / 2,
                    0, 1, 0, -(t + b) / 2,
                    0, 0, 1, -(near + far) / 2,
                    0, 0, 0, 1};
    Mat<4, 4> extrusion{near, 0, 0, 0,
                        0, near, 0, 0,
                        0, 0, near + far, -near * far,
                        0, 0, 1, 0};

    Mat<4, 4> ret = zoom * pan * extrusion;
    return ret;
}
Mat<4, 4> modelMatrix = Mat<4, 4>::identity();
Mat<4, 4> viewMatrix = View(camera.position);
Mat<4, 4> projectionMatrix = Projection(-0.1, -50, camera.fov, camera.aspectRatio);
Mat<4, 4> mvp = projectionMatrix * viewMatrix * modelMatrix;
Mat<4, 4> mvpInverseTranspose = mvp.Inverse().Transpose();

mvp:

-2.29032  0        0.763441   -2.68032e-16 
0         -2.41421 0          0 
-0.317495 0        -0.952486  2.97455 
0.316228  0        0.948683   -3.16228 

mvpInverseTranspose:

-0.392957   0          0.130986   0 
0           -0.414214  0          0 
-4.99       0          -14.97     -4.99 
-4.69377    0          -14.0813   -5.01
1 Answers

I seem to understand the problem. The lighting should be calculated in world space, so I only need to apply the inverse transpose matrix of the model transformation to the normal.

Related