перепиши метод:
public static Vector3f multiplyMatrix4ByVector3(final Matrix4f matrix, final Vector3f vertex) {
        final float x = (vertex.x * matrix.m00) + (vertex.y * matrix.m10) + (vertex.z * matrix.m20) + matrix.m30;
        final float y = (vertex.x * matrix.m01) + (vertex.y * matrix.m11) + (vertex.z * matrix.m21) + matrix.m31;
        final float z = (vertex.x * matrix.m02) + (vertex.y * matrix.m12) + (vertex.z * matrix.m22) + matrix.m32;
        final float w = (vertex.x * matrix.m03) + (vertex.y * matrix.m13) + (vertex.z * matrix.m23) + matrix.m33;
        return new Vector3f(x / w, y / w, z / w);
    }

    public static Point2f vertexToPoint(final Vector3f vertex, final int width, final int height) {
        return new Point2f(vertex.x * width + width / 2.0F, -vertex.y * height + height / 2.0F);
    }
с учетом моих классов:
package com.cgvsu.math;

public class Matrix4f extends AbstractMatrix {
    private static final int SIZE = 4;
    private float[][] elements;

    // Конструкторы + getters and setters
    public Matrix4f(float[] elements) {
        if (elements.length != SIZE * SIZE) {
            throw new IllegalArgumentException("Массив должен содержать ровно " + (SIZE * SIZE) + " элементов.");
        }
        this.elements = new float[SIZE][SIZE];
        int k = 0;
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++, k++) {
                this.elements[i][j] = elements[k];
            }
        }
    }

    public Matrix4f(Matrix4f elements) {
        if (elements.getElements().length != SIZE * SIZE) {
            throw new IllegalArgumentException("Массив должен содержать ровно " + (SIZE * SIZE) + " элементов.");
        }
        this.elements = new float[SIZE][SIZE];

        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                this.elements[i][j] = elements.getElement(i, j);
            }
        }
    }

    public Matrix4f(int one) {
        //Опять вопрос к Борисову: проверять ли это num на какое-то значение, отличное от нуля, или нет... а, хотя, я наебу систему
        this.elements = new float[SIZE][SIZE];
        for (int i = 0; i < SIZE; i++) {
            this.elements[i][i] = 1;
        }
    }

    public Matrix4f() {
        this.elements = new float[SIZE][SIZE];
    }

    @Override
    public Matrix4f add(AbstractMatrix other) {
        float[] a = new float[16];
        int k = 0;
        if (!isMatrix4x4(other)) {
            throw new IllegalArgumentException("Invalid matrix type for dot product");
        }
        Matrix4f o = (Matrix4f) other;
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++, k++) {
                a[k] = this.elements[i][j] + o.elements[i][j];
            }
        }
        return new Matrix4f(a);
    }

    @Override
    public Matrix4f sub(AbstractMatrix other) {
        float[] a = new float[16];
        int k = 0;
        if (!isMatrix4x4(other)) {
            throw new IllegalArgumentException("Invalid matrix type for dot product");
        }
        Matrix4f o = (Matrix4f) other;
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++, k++) {
                a[k] = this.elements[i][j] - o.elements[i][j];
            }
        }
        return new Matrix4f(a);
    }

    @Override
    public Vector4f multiply(AbstractVector other) {
        if (!isVector4f(other)) {
            throw new IllegalArgumentException("Invalid vector type for dot product");
        }
        Vector4f o = (Vector4f) other;
        Vector4f result = new Vector4f();
        for (int i = 0; i < SIZE; i++) {
            float res = 0;
            for (int j = 0; j < SIZE; j++) {
                res += (elements[i][j] * o.getNum(j));
            }
            result.setNum(i, res);
        }
        return result;
    }

    @Override
    public void multiply(AbstractMatrix other) {
        if (!isMatrix4x4(other)) {
            throw new IllegalArgumentException("Invalid vector type for dot product");
        }
        Matrix4f o = (Matrix4f) other;
        Matrix4f result = new Matrix4f();
        for (int i = 0; i < SIZE; i++) {
            for (int k = 0; k < SIZE; k++) {
                float res = 0;
                for (int j = 0; j < SIZE; j++) {
                    res += this.elements[i][j] * o.elements[j][k];
                }
                result.elements[i][k] = res;
            }
        }
        this.elements = result.getElements();

    }

    @Override
    public void transposition() {
        for (int i = 0; i < SIZE; i++) {
            for (int j = i + 1; j < SIZE; j++) {
                float temp = elements[i][j];
                elements[i][j] = elements[j][i];
                elements[j][i] = temp;
            }
        }
    }

    @Override
    // Вычисление определителя матрицы 4x4
    public float determinant() {
        float det = 0;
        for (int col = 0; col < SIZE; col++) {
            det += (col % 2 == 0 ? 1 : -1) * elements[0][col] * getMinorMatrix(0, col).determinant();
        }
        return det;
    }

    /**
     * Вычисление матрицы алгебраических дополнений для матрицы 4x4
     *
     * @return Матрица алгебраических дополнений 4x4
     */
    private float[][] computeDopMatrix() {
        float[][] cofactors = new float[SIZE][SIZE];
        for (int row = 0; row < SIZE; row++) {
            for (int col = 0; col < SIZE; col++) {
                Matrix3f minorMatrix = getMinorMatrix(row, col);
                float minorDeterminant = minorMatrix.determinant();
                cofactors[row][col] = ((row + col) % 2 == 0 ? 1 : -1) * minorDeterminant;

            }
        }
        return cofactors;
    }

    /**
     * Вычисление матрицы тильда для матрицы 4x4
     *
     * @return Матрица присоединённых 4x4
     */
    private Matrix4f computeTildaMatrix() {
        float[][] cofactors = computeDopMatrix();
        Matrix4f tilda = new Matrix4f();
        tilda.elements = cofactors;

        // Транспонирование матрицы кофакторов
        tilda.transposition();

        return tilda;
    }

    /**
     * Получение минорной матрицы 3x3, исключая указанную строку и столбец
     *
     * @param rowToExclude Строка для исключения
     * @param colToExclude Столбец для исключения
     * @return Минорная матрица 3x3
     */
    private Matrix3f getMinorMatrix(int rowToExclude, int colToExclude) {
        float[] minorElements = new float[9];
        int index = 0;
        for (int i = 0; i < SIZE; i++) {
            if (i == rowToExclude) continue;
            for (int j = 0; j < SIZE; j++) {
                if (j == colToExclude) continue;
                minorElements[index++] = elements[i][j];
            }
        }
        return new Matrix3f(minorElements);
    }


    /**
     * Вычисление обратной матрицы 4x4
     *
     * @return Обратная матрица 4x4
     * @throws ArithmeticException если матрица вырождена и не имеет обратной
     */
    @Override
    public Matrix4f inverse() {
        float det = determinant();
        if (det == 0) {
            throw new ArithmeticException("Матрица вырождена и не имеет обратной.");
        }
        Matrix4f tilda = computeTildaMatrix();
        float[] inverseElements = new float[16];
        int k = 0;
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++, k++) {
                inverseElements[k] = tilda.elements[i][j] / det;
            }
        }
        return new Matrix4f(inverseElements);
    }

    @Override
    public float getElement(int rows, int col) {
        return elements[rows][col];
    }

    @Override
    public void setElement(int rows, int col, float result) {
        elements[rows][col] = result;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (float[] row : elements) {
            for (float elem : row) {
                sb.append(String.format("%.2f\t", elem));
            }
            sb.append("\n");
        }
        boolean a = false;
        return sb.toString();
    }

    private boolean isMatrix4x4(AbstractMatrix other) {
        return other instanceof Matrix4f;
    }

    private boolean isVector4f(AbstractVector other) {
        return other instanceof Vector4f;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof Matrix4f)) return false;
        Matrix4f other = (Matrix4f) obj;
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                if (Float.compare(this.elements[i][j], other.elements[i][j]) != 0) {
                    return false;
                }
            }
        }
        return true;
    }

    @Override
    public int hashCode() {
        int result = 1;
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                result = 31 * result + Float.hashCode(elements[i][j]);
            }
        }
        return result;
    }

    // Геттер для элементов матрицы
    public float[][] getElements() {
        return elements;
    }
}
package com.cgvsu.math;

import java.util.Objects;

/**
 * Класс для работы с двумерными векторами с плавающей точкой.
 * Это заготовка для собственной библиотеки линейной алгебры.
 */
public class Vector2f extends AbstractVector {
    private static final int SIZE = 2;
    private float[] components = new float[SIZE];
    private float length;

    /**
     * Конструктор для создания вектора с заданными компонентами.
     *
     * @param x Компонента по оси X.
     * @param y Компонента по оси Y.
     */
    public Vector2f(float x, float y) {
        this.components[0] = x;
        this.components[1] = y;
        calcLength();
    }

    /**
     * Конструктор для создания нулевого вектора.
     */
    public Vector2f() {
        this.components[0] = 0;
        this.components[1] = 0;
        calcLength();
    }

    // Геттеры и сеттеры для компонентов X и Y
    public float getX() {
        return components[0];
    }

    public void setX(float x) {
        components[0] = x;
        calcLength();
    }

    public float getY() {
        return components[1];
    }

    public void setY(float y) {
        components[1] = y;
        calcLength();
    }

    /**
     * Возвращает компонент вектора по индексу.
     *
     * @param index Индекс компонента (0 для X, 1 для Y).
     * @return Значение компонента.
     * @throws IndexOutOfBoundsException если индекс не равен 0 или 1.
     */
    public float getNum(int index) {
        if (index < 0 || index >= components.length) {
            throw new IndexOutOfBoundsException("Неверный индекс: " + index);
        }
        return components[index];
    }

    /**
     * Заменяет значение компонента вектора по индексу.
     *
     * @param index Индекс компонента (0 для X, 1 для Y).
     * @param num   Новое значение для компонента.
     * @throws IndexOutOfBoundsException если индекс не равен 0 или 1.
     */
    public void setNum(int index, float num) {
        if (index < 0 || index >= components.length) {
            throw new IndexOutOfBoundsException("Неверный индекс: " + index);
        }
        components[index] = num;
        calcLength();
    }

    /**
     * Вычисляет длину вектора и сохраняет её.
     */
    private void calcLength() {
        length = (float) Math.sqrt(components[0] * components[0] + components[1] * components[1]);
    }

    @Override
    public float length() {
        return length;
    }

    /**
     * Нормализует вектор.
     * Если длина вектора равна нулю, метод ничего не делает.
     */
    private void calcNormalize() {
        calcLength();
        if (length == 0) {
            return;
        }
        divide(length);
    }

    @Override
    public void normalize() {
        calcNormalize();
    }

    /**
     * Складывает текущий вектор с другим вектором.
     *
     * @param other Другой вектор для сложения.
     * @return Новый вектор, являющийся суммой двух векторов.
     * @throws IllegalArgumentException если тип другого вектора не Vector2f.
     */
    @Override
    public Vector2f add(AbstractVector other) {
        if (!isVector2f(other)) {
            throw new IllegalArgumentException("Неверный тип вектора для сложения");
        }
        Vector2f o = (Vector2f) other;
        return new Vector2f(
                this.components[0] + o.components[0],
                this.components[1] + o.components[1]
        );
    }

    /**
     * Вычитает из текущего вектора другой вектор.
     *
     * @param other Другой вектор для вычитания.
     * @return Новый вектор, являющийся разностью двух векторов.
     * @throws IllegalArgumentException если тип другого вектора не Vector2f.
     */
    @Override
    public Vector2f sub(AbstractVector other) {
        if (!isVector2f(other)) {
            throw new IllegalArgumentException("Неверный тип вектора для вычитания");
        }
        Vector2f o = (Vector2f) other;
        return new Vector2f(
                this.components[0] - o.components[0],
                this.components[1] - o.components[1]
        );
    }

    @Override
    public void sub(AbstractVector other, AbstractVector second) {
        if (!(isVector2f(other) && isVector2f(second))) {
            new Exception("не правильный тип векторов");
        }
        Vector2f o = (Vector2f) other;
        Vector2f s = (Vector2f) second;
        this.components[0] = o.getX() - s.getX();
        this.components[1] = o.getY() - s.getY();
    }

    /**
     * Умножает текущий вектор на скаляр.
     *
     * @param scalar Скаляр для умножения.
     */
    @Override
    public void multiply(float scalar) {
        for (int i = 0; i < components.length; i++) {
            this.components[i] *= scalar;
        }
        calcLength();
    }

    /**
     * Делит текущий вектор на скаляр.
     *
     * @param scalar Скаляр для деления.
     * @throws ArithmeticException если скаляр равен нулю.
     */
    @Override
    public void divide(float scalar) {
        if (scalar == 0) {
            throw new ArithmeticException("Деление на ноль");
        }
        for (int i = 0; i < components.length; i++) {
            this.components[i] /= scalar;
        }
        calcLength();
    }

    /**
     * Вычисляет скалярное произведение текущего вектора с другим вектором.
     *
     * @param other Другой вектор для скалярного произведения.
     * @return Значение скалярного произведения.
     * @throws IllegalArgumentException если тип другого вектора не Vector2f.
     */
    @Override
    public float dot(AbstractVector other) {
        if (!isVector2f(other)) {
            throw new IllegalArgumentException("Неверный тип вектора для скалярного произведения");
        }
        Vector2f o = (Vector2f) other;
        return this.components[0] * o.components[0] + this.components[1] * o.components[1];
    }

    /**
     * Проверяет, является ли другой вектор экземпляром Vector2f.
     *
     * @param other Другой вектор для проверки.
     * @return true если другой вектор является Vector2f, иначе false.
     */
    private boolean isVector2f(AbstractVector other) {
        return other instanceof Vector2f;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof Vector2f)) return false;
        Vector2f other = (Vector2f) obj;
        return Float.compare(components[0], other.components[0]) == 0 &&
                Float.compare(components[1], other.components[1]) == 0;
    }

    @Override
    public int hashCode() {
        return Objects.hash(components[0], components[1]);
    }

    @Override
    public String toString() {
        return "Vector2f{" +
                "x=" + components[0] +
                ", y=" + components[1] +
                '}';
    }
}package com.cgvsu.math;

import java.util.Objects;

// Это заготовка для собственной библиотеки для работы с линейной алгеброй
public class Vector3f extends AbstractVector {
    private float[] components = new float[SIZE];
    private static final int SIZE = 3;

    private float length;

    // Конструкторы + getters and setters
    public Vector3f(float x, float y, float z) {
        this.components[0] = x;
        this.components[1] = y;
        this.components[2] = z;
        calcLength();
    }
    public Vector3f() {
        this.components[0] = 0;
        this.components[1] = 0;
        this.components[2] = 0;
        calcLength();
    }

    public float getX() {
        return components[0];
    }

    public void setX(float x) {
        components[0] = x;
        calcLength();
    }

    public float getY() {
        return components[1];
    }

    public void setY(float y) {
        components[1] = y;
        calcLength();
    }

    public float getZ() {
        return components[2];
    }

    public void setZ(float z) {
        components[2] = z;
        calcLength();
    }

    /**
     * Возвращает компонент вектора по индексу.
     *
     * @param a Индекс компонента (0 для x, 1 для y, 2 для z).
     * @return Значение компонента.
     * @throws IndexOutOfBoundsException если индекс не равен 0, 1 или 2.
     */
    public float getNum(int a) {
        if (a < 0 || a >= components.length) {
            throw new IndexOutOfBoundsException("Invalid index: " + a);
        }
        return components[a];
    }

    /**
     * Заменяет значения для x,y,z по индексу.
     *
     * @param a Индекс компонента (0 для x, 1 для y, 2 для z).
     * @param num Новое число для переменной
     * @throws IndexOutOfBoundsException если индекс не равен 0, 1 или 2.
     */
    public void setNum(int a, float num) {
        if (a < 0 || a >= components.length) {
            throw new IndexOutOfBoundsException("Invalid index: " + a);
        }
        components[a] = num;
    }

    // Метод для вычисления длины вектора
    private void calcLength() {
        length = (float) Math.sqrt(components[0] * components[0]
                + components[1] * components[1]
                + components[2] * components[2]);
    }

    @Override
    public float length() {
        return length;
    }

    // Метод для нормализации вектора
    private void calcNormalize() {
        calcLength();
        if (length == 0) {
            return;
        }
        divide(length);
    }

    @Override
    public void normalize() {
        calcNormalize();
    }

    // Метод сложения векторов
    @Override
    public Vector3f add(AbstractVector other) {
        if (!isVector3f(other)) {
            throw new IllegalArgumentException("Неверный тип вектора для сложения");
        }
        Vector3f o = (Vector3f) other;
        return new Vector3f(
                this.components[0] + o.components[0],
                this.components[1] + o.components[1],
                this.components[2] + o.components[2]
        );
    }

    // Метод вычитания векторов
    @Override
    public Vector3f sub(AbstractVector other) {
        if (!isVector3f(other)) {
            throw new IllegalArgumentException("Неверный тип вектора для вычитания");
        }
        Vector3f o = (Vector3f) other;
        return new Vector3f(
                this.components[0] - o.components[0],
                this.components[1] - o.components[1],
                this.components[2] - o.components[2]
        );
    }

    @Override
    public void sub(AbstractVector other, AbstractVector second) {
        if (!(isVector3f(other) && isVector3f(second))) {
            new Exception("не правильный тип векторов");
        }
        Vector3f o = (Vector3f) other;
        Vector3f s = (Vector3f) second;
        this.components[0] = o.getX() - s.getX();
        this.components[1] = o.getY() - s.getY();
        this.components[2] = o.getZ() - s.getZ();
    }

    // Метод умножения вектора на скаляр
    @Override
    public void multiply(float scalar) {
        for (int i = 0; i < components.length; i++) {
            this.components[i] *= scalar;
        }
        calcLength();
    }

    // Метод деления вектора на скаляр
    @Override
    public void divide(float scalar) {
        if (scalar == 0) throw new ArithmeticException("Деление на ноль");
        for (int i = 0; i < components.length; i++) {
            this.components[i] /= scalar;
        }
        calcLength();
    }

    // Метод скалярного произведения
    @Override
    public float dot(AbstractVector other) {
        if (!isVector3f(other)) {
            throw new IllegalArgumentException("Неверный тип вектора для скалярного произведения");
        }
        Vector3f o = (Vector3f) other;
        return this.components[0] * o.components[0]
                + this.components[1] * o.components[1]
                + this.components[2] * o.components[2];
    }

    // Метод векторного произведения
    public Vector3f cross(Vector3f other) {
        float x = this.components[1] * other.components[2] - this.components[2] * other.components[1];
        float y = this.components[2] * other.components[0] - this.components[0] * other.components[2];
        float z = this.components[0] * other.components[1] - this.components[1] * other.components[0];
        return new Vector3f(x, y, z);
    }

        // Проверка типа вектора
    private boolean isVector3f(AbstractVector other) {
        return other instanceof Vector3f;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof Vector3f)) return false;
        Vector3f other = (Vector3f) obj;
        return Float.compare(components[0], other.components[0]) == 0 &&
                Float.compare(components[1], other.components[1]) == 0 &&
                Float.compare(components[2], other.components[2]) == 0;
    }

    @Override
    public int hashCode() {
        return Objects.hash(components[0], components[1], components[2]);
    }

    @Override
    public String toString() {
        return "Vector3f{" +
                "x=" + components[0] +
                ", y=" + components[1] +
                ", z=" + components[2] +
                '}';
    }

}
умножать надо вектора столбцы