简体   繁体   中英

3D Graphics - Matrix math is not working

I'm fairly new to 3D Graphics, so I expect I have done something fundamentally wrong. I have built 4 matrixes to handle my objects in 3D space, a Scaling matrix, Translation Matrix, Perspective Matrix and Rotation matrix.

The rotation and scaling matrix work fine, however my Perspective and Translation Matrixes do not behave as expected, from what I understand the Translation and Perspective Matrixes look like:

Translation      Perspective 
[1, 0, 0, x]    [1, 0,  0 , 0]
[0, 1, 0, y]    [0, 1,  0 , 1]
[0, 0, 1, z]    [0, 0,  1 , 0]
[0, 0, 0, 1]    [0, 0, 1/D, 1]

To understand how everything works behind the scenes I am writing my own Math lib - to create the matrixes defined above I have the following methods:

public static ASMATRIX4 CreatePerspectiveMatrix(double focalLength)
{
    // Create matrix as an identity matrix
    var m = new ASMATRIX4();

    // Set the perspective matrix 
    m.Matrix[3].Points[2] = 1 / focalLength;
    m.Matrix[1].Points[3] = 1;

    return m;
}

public static ASMATRIX4 CreateTranslationMatrix(double x, double y, double z)
{
    // reset to identity matrix
    var m = new ASMATRIX4();

    // Set the translation matrix
    m.Matrix[0].Points[3] = x;
    m.Matrix[1].Points[3] = y;
    m.Matrix[2].Points[3] = z;

   return m;
}

Nothing too complicated, but when I multiply my matrixes together, nothing happens - I can rotate about any axis, but I cannot translate. Also note above that new ASMATRIX4() initialises a new 4x4 matrix as an identity matrix.

To multiply my matrixes together I do the following:

m_scaling = ASMATRIX4.CreateScalingMatrix(s, s, s);
m_translation = ASMATRIX4.CreateTranslationMatrix(tX, tY, tZ);
m_perspective = ASMATRIX4.CreatePerspectiveMatrix(f);
m_rotation = ASMATRIX4.RotateByDegrees(rX, rY, rZ);

var transformationMatrix = m_scaling*m_translation*m_perspective*m_rotation;

I also wrote an operator overload to handle multiplying matrixes together:

public static ASMATRIX4 operator *(ASMATRIX4 mA, ASMATRIX4 mB)
{
    //  Creates a new identity matrix
    var m = new ASMATRIX4();

    // Multiply the two matrixes together and return the output matrix
    for (var i = 0; i < 4; i++)
    {
        for (var j = 0; j < 4; j++)
        {
            m.Matrix[i].Points[j] =
                (mB.Matrix[i].Points[0]*mA.Matrix[0].Points[j]) +
                (mB.Matrix[i].Points[1]*mA.Matrix[1].Points[j]) +
                (mB.Matrix[i].Points[2]*mA.Matrix[2].Points[j]) +
                (mB.Matrix[i].Points[3]*mA.Matrix[3].Points[j])
        }
    }
    return m;
 }

Finally to actually transform my mesh, I have an array of Faces, that I draw to a 2D rendering context, the method below transforms each face by the transformation matrix defined above.

private void TransformMesh()
{
    var transformationMatrix = m_scaling*m_translation*m_perspective*m_rotation;
    for (var i = 0; i < m_numFaces; i++)
    {     
        m_meshData[i] = m_meshData[i].TransformFace(transformationMatrix);
    }
}

The TransformFace method looks as described below:

public ASFace TransformFace(ASMATRIX4 matrix)
{
    var transformedFace = new ASFace();

    for (var i = 0; i < 3; i++)
    {
        transformedFace.m_points[i] = m_points[i].TransformVector(matrix);
        transformedFace.m_points[i] = transformedFace.m_points[i].Rescale();
    }

    return transformedFace;
 }

This first method in the loop transforms the homogenous point by the input matrix, and then a rescale method is called to normalise the vector.

I'm confused as to what I have done wrong? I am thinking the order of operations on multiplying the matrixes could be wrong but I am not too sure, any suggestions would be greatly appreciated.

I'm not an expert about this, but aren't you missing a row/column here?

-- EDITED (tnx andand)

public static ASMATRIX4 operator *(ASMATRIX4 mA, ASMATRIX4 mB)
{
    //  Creates a new identity matrix
    var m = new ASMATRIX4();

    // Multiply the two matrixes together and return the output matrix
    for (var i = 0; i < 4; i++)
    {
        for (var j = 0; j < 4; j++)
        {
            m.Matrix[i].Points[j] =
                (mB.Matrix[i].Points[0]*mA.Matrix[0].Points[j]) +
                (mB.Matrix[i].Points[1]*mA.Matrix[1].Points[j]) +
                (mB.Matrix[i].Points[2]*mA.Matrix[2].Points[j]) +
                (mB.Matrix[i].Points[3]*mA.Matrix[3].Points[j]);   //  <----
        }
    }
    return m;
}

I see two problems in your posted code. First, your CreatePerspectiveMatrix method does not set the (1, 3) element to 1; either the method or the initial definition of the perspective matrix is wrong. (Or both!) Second, in your multiplication code you seem to be only multiplying the sub-matrix of the first three rows and columns. Since these sub-matrices are initially unit matrices, it's not too surprising that nothing happens.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM