c ++模板化矩阵类乘法

时间:2015-07-14 10:06:25

标签: c++ templates matrix

我是c ++的新手,所以我想了解为什么以下不起作用或我做错了什么。我正在尝试使用模板制作矩阵类,然后将一些数学应用于矩阵或矩阵。

在我的main.cpp中,我在main方法中有以下内容。

mat<4, 4> m = mat<4, 4>(1.0f); // Identity matrix

mat<2, 3> a = mat<2, 3>(2.0f); // Matrix with 2 rows & 2 columns
mat<3, 2> b = mat<3, 2>(3.0f); // Matrix with 3 rows & 2 columns
mat<3, 3> c = a * b; // Multiplication.

std::cout << c << std::endl;

当两个矩阵的行数和列数(即3x3,4x4等)都具有相同的大小时,乘法下面所述的矩阵类有效。只要矩阵A中的列数与矩阵B中的行数相同(即A <2,3> * B <3,2> = C <3),将2个不同大小的矩阵相乘也是合法的。 ,3&gt;)。我的矩阵类只需要能够为数字行和列乘以相同大小的矩阵(3d数学的4x4矩阵)。但我想知道我做错了什么或理解为什么这不起作用。

矩阵课程:

template <int rows, int columns>
struct mat
{
    float elements[rows * columns];

    // Default constructor.
    mat()
    {
        for (int i = 0; i < rows * columns; i++)
            elements[i] = (float) 0.0f;
    }

    // Basic constructor
    mat(float diagonal) : mat()
    {
        int min = rows > columns ? columns : rows;
        for (int i = 0; i < min; i++)
            elements[i + i * columns] = diagonal;
    }

    /*************************
    * Helper functionalities *
    *************************/

    // Returns an identity matrix.
    // Should only be used when width and height are the same.
    static mat<4, 4> identity()
    {
        return mat<4, 4>(1.0f);
    }

    // Returns an orthographic matrix.
    static mat<4, 4> orthographic(float left, float right, float bottom, float top, float near, float far)
    {
        mat<4, 4> result(1.0f);

        result.elements[0 + 0 * 4] = 2.0f / (right - left);
        result.elements[1 + 1 * 4] = 2.0f / (top - bottom);
        result.elements[2 + 2 * 4] = 2.0f / (near - far);

        result.elements[0 + 3 * 4] = (left + right) / (left - right);
        result.elements[1 + 3 * 4] = (bottom + top) / (bottom - top);
        result.elements[2 + 3 * 4] = (far + near) / (far - near);

        return result;
    }

    // Returns a perspective matrix.
    static mat<4, 4> perspective(float fov, float aspect, float near, float far)
    {
        mat<4, 4> result(1.0f);

        result.elements[0 + 0 * 4] = (1.0f / tan(torad(0.5f * fov))) / aspect;
        result.elements[1 + 1 * 4] = (1.0f / tan(torad(0.5f * fov)));
        result.elements[2 + 2 * 4] = (near + far) / (near - far);

        result.elements[3 + 2 * 4] = -1.0f;
        result.elements[2 + 3 * 4] = (2.0f * near * far) / (near - far);

        return result;
    }

    // Returns a translation matrix.
    static mat<4, 4> translation(const vec<3>& translation)
    {
        mat<4, 4> result(1.0f);

        result.elements[0 + 3 * 4] = translation.x;
        result.elements[1 + 3 * 4] = translation.y;
        result.elements[2 + 3 * 4] = translation.z;

        return result;
    }

    // Returns a rotation matrix.
    static mat<4, 4> rotation(float angle, const vec<3>& axis)
    {
        mat<4, 4> result(1.0f);

        float radians = torad(angle);
        float c = cos(radians);
        float s = sin(radians);

        result.elements[0 + 0 * 4] = axis.x * (1.0f - c) + c;
        result.elements[1 + 0 * 4] = axis.y * axis.x * (1.0f - c) + axis.z * s;
        result.elements[2 + 0 * 4] = axis.x * axis.z * (1.0f - c) - axis.y * s;

        result.elements[0 + 1 * 4] = axis.x * axis.y * (1.0f - c) - axis.z * s;
        result.elements[1 + 1 * 4] = axis.y * (1.0f - c) + c;
        result.elements[2 + 1 * 4] = axis.y * axis.z * (1.0f - c) + axis.y * s;

        result.elements[0 + 2 * 4] = axis.x * axis.z * (1.0f - c) + axis.y * s;
        result.elements[1 + 2 * 4] = axis.y * axis.z * (1.0f - c) - axis.x * s;
        result.elements[2 + 2 * 4] = axis.z * (1.0f - c) + c;

        return result;
    }

    // Returns a scale matrix.
    static mat<4, 4> scale(const vec<3>& scale)
    {
        mat<4, 4> result(1.0f);

        result.elements[0 + 0 * 4] = scale.x;
        result.elements[1 + 1 * 4] = scale.y;
        result.elements[2 + 2 * 4] = scale.z;

        return result;
    }

    /***********************
    * Math functionalities *
    ***********************/

    // Overloaded addition operator to add two matrices together.
    friend mat<rows, columns> operator + (mat<rows, columns> left, const mat<rows, columns>& right)
    {
        for (int i = 0; i < rows * columns; i++)
            left.elements[i] += right.elements[i];
        return left;
    }

    // Overloaded addition operator to add a scalar to a matrix.
    friend mat<rows, columns> operator + (mat<rows, columns> left, const float& scalar)
    {
        for (int i = 0; i < rows * columns; i++)
            left.elements[i] += scalar;
        return left;
    }

    // Overloaded add and assign operator to add a matrix to a matrix.
    mat<rows, columns>& operator += (const mat<rows, columns>& other)
    {
        for (int i = 0; i < rows * columns; i++)
            elements[i] += other.elements[i];
        return *this;
    }

    // Overloaded add and assign operator to add a scalar to a matrix.
    mat<rows, columns>& operator += (const float& scalar)
    {
        for (int i = 0; i < rows * columns; i++)
            elements[i] += scalar;
        return *this;
    }

    // Overloaded subtraction operator to subtract a matrix from another matrix.
    friend mat<rows, columns> operator - (mat<rows, columns> left, const mat<rows, columns>& right)
    {
        for (int i = 0; i < rows * columns; i++)
            left.elements[i] -= right.elements[i];
        return left;
    }

    // Overloaded subtraction operator to subtract a scalar from a matrix.
    friend mat<rows, columns> operator - (mat<rows, columns> left, const float& scalar)
    {
        for (int i = 0; i < rows * columns; i++)
            left.elements[i] -= scalar;
        return left;
    }

    // Overloaded subtract and assign operator to subtract a matrix from a matrix.
    mat<rows, columns>& operator -= (const mat<rows, columns>& other)
    {
        for (int i = 0; i < rows * columns; i++)
            elements[i] -= other.elements[i];
        return *this;
    }

    // Overloaded subtract and assign operator to subtract a scalar from a matrix.
    mat<rows, columns>& operator -= (const float& scalar)
    {
        for (int i = 0; i < rows * columns; i++)
            elements[i] -= scalar;
        return *this;
    }

    template<int rows, int equals, int columns>
    // Overloaded multiplication operator to multiply a matrix with another matrix.
    friend mat<rows, columns> operator * (const mat<rows, equals>& left, const mat<equals, columns>& right)
    {
        mat<rows, columns> result;

        for (int y = 0; y < rows; y++)
        {
            for (int x = 0; x < columns; x++)
            {
                float sum = 0.0f;
                for (int i = 0; i < columns; i++)
                {
                    sum += left.elements[x + i * columns] * right.elements[i + y * columns];
                }

                result.elements[x + y * columns] = sum;
            }
        }

        return result;
    }

    /*************************
    * Output functionalities *
    *************************/

    // Overloaded output operator to print the vector to output
    friend std::ostream& operator << (std::ostream& out, mat& matrix)
    {
        out << "mat<" << rows << ", " << columns << "> (" << std::endl;

        for (int y = 0; y < rows; y++)
        {
            out << "\t";

            for (int x = 0; x < columns; x++)
            {
                out << matrix.elements[x + y * columns];

                if (x < columns - 1)
                    out << ", ";

                else
                    out << std::endl;
            }
        }

        return out << ")";
    }
};

编辑@filmor要求编译错误: 我得到的错误是 错误C2995:'mat operator *(const mat&amp;,const mat&amp;)':函数模板已经定义了maths \ matrix.h 190 1测试

1 个答案:

答案 0 :(得分:1)

在运算符*的这段代码中,我看到两个错误:首先你应该迭代i等于(而不是列)然后左边的矩阵有equals列,所以你需要通过{访问它的元素{1}}

left.elements[x + i * equals]