предложи варианты как ускорить код??
package com.cgvsu.render_engine;

import com.cgvsu.math.Matrix4f;
import com.cgvsu.math.Point2f;
import com.cgvsu.math.Vector3f;
import com.cgvsu.model.Model;
import com.cgvsu.model.Polygon;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;

import static com.cgvsu.render_engine.GraphicConveyor.*;

/**
 * Содержит методы для рендеринга 3D моделей с использованием графического контекста JavaFX.
 */
public class RenderEngine {

    /**
     * Вычисляет матрицу проекции модели с учетом камеры.
     *
     * @param camera Объект камеры, содержащий матрицы вида и проекции.
     * @return Матрица модель-представление-проекция.
     */
    private static Matrix4f calculateModelViewProjectionMatrix(Camera camera) {
        Matrix4f modelMatrix = rotateScaleTranslate();
        Matrix4f viewMatrix = camera.getViewMatrix();
        Matrix4f projectionMatrix = camera.getProjectionMatrix();

        Matrix4f modelViewProjectionMatrix = new Matrix4f(projectionMatrix);
        modelViewProjectionMatrix.multiply(viewMatrix);
        modelViewProjectionMatrix.multiply(modelMatrix);
        return modelViewProjectionMatrix;
    }

    /**
     * Инициализирует Z-буфер заданными размерами.
     *
     * @param width  Ширина экрана.
     * @param height Высота экрана.
     * @return Двумерный массив Z-буфера, заполненный максимальными значениями глубины.
     */
    private static float[][] initializeZBuffer(int width, int height) {
        float[][] zBuffer = new float[width][height];
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                zBuffer[x][y] = Float.MAX_VALUE;
            }
        }
        return zBuffer;
    }

    /**
     * Выполняет рендеринг 3D модели на графическом контексте.
     *
     * @param graphicsContext Графический контекст JavaFX для рисования.
     * @param camera          Объект камеры, определяющий вид и проекцию.
     * @param mesh            Модель для рендеринга.
     * @param width           Ширина области рендеринга.
     * @param height          Высота области рендеринга.
     */
    public static void render(
            final GraphicsContext graphicsContext,
            final Camera camera,
            final Model mesh,
            final int width,
            final int height) {

        float[][] zBuffer = initializeZBuffer(width, height);
        Matrix4f modelViewProjectionMatrix = calculateModelViewProjectionMatrix(camera);

        for (Polygon polygon : mesh.polygons) {
            renderPolygon(graphicsContext, polygon, modelViewProjectionMatrix, width, height, zBuffer, mesh);
        }
    }

    /**
     * Рендерит отдельный многоугольник на графическом контексте.
     *
     * @param graphicsContext         Графический контекст для рисования.
     * @param polygon                 Многоугольник для рендеринга.
     * @param modelViewProjectionMatrix Матрица модель-представление-проекция.
     * @param width                   Ширина области рендеринга.
     * @param height                  Высота области рендеринга.
     * @param zBuffer                 Z-буфер для отслеживания глубины пикселей.
     * @param mesh                    Модель, содержащая вершины.
     */
    private static void renderPolygon(
            GraphicsContext graphicsContext,
            Polygon polygon,
            Matrix4f modelViewProjectionMatrix,
            int width,
            int height,
            float[][] zBuffer,
            Model mesh) {

        Point2f[] screenPoints = new Point2f[3];
        float[] zValues = new float[3];

        for (int i = 0; i < 3; i++) {
            Vector3f transformedVertex = transformVertex(mesh, polygon, i, modelViewProjectionMatrix);
            screenPoints[i] = vertexToPoint(transformedVertex, width, height);
            zValues[i] = transformedVertex.getZ();
        }

        rasterizeTriangle(screenPoints, zValues, zBuffer, graphicsContext);
    }

    /**
     * Применяет трансформацию к вершине многоугольника.
     *
     * @param mesh                Модель, содержащая вершины.
     * @param polygon             Многоугольник, содержащий индексы вершин.
     * @param vertexIndex         Индекс вершины в многоугольнике.
     * @param transformationMatrix Матрица трансформации.
     * @return Трансформированная вершина.
     */
    private static Vector3f transformVertex(Model mesh, Polygon polygon, int vertexIndex, Matrix4f transformationMatrix) {
        Vector3f vertex = mesh.vertices.get(polygon.getVertexIndices().get(vertexIndex));
        Vector3f vertexVecmath = new Vector3f(vertex.getX(), vertex.getY(), vertex.getZ());
        return multiplyMatrix4ByVector3(transformationMatrix, vertexVecmath);
    }

    /**
     * Выполняет растеризацию треугольника и обновляет графический контекст.
     *
     * @param points           Координаты точек треугольника на экране.
     * @param zValues          Значения глубины для каждой вершины.
     * @param zBuffer          Z-буфер для отслеживания глубины пикселей.
     * @param graphicsContext  Графический контекст для рисования.
     */

//    private static void rasterizeTriangle(Point2f[] points, float[] zValues, float[][] zBuffer, GraphicsContext graphicsContext) {
//        // Определяем цвета для вершин треугольника
//        Color color = Color.RED; // Одноцветное заполнение треугольника
//
//        // Координаты вершин треугольника
//        double[] xPoints = {points[0].getX(), points[1].getX(), points[2].getX()};
//        double[] yPoints = {points[0].getY(), points[1].getY(), points[2].getY()};
//
//        // Устанавливаем цвет и закрашиваем треугольник
//        graphicsContext.setFill(color);
//        graphicsContext.fillPolygon(xPoints, yPoints, 3);
//    }



    private static void rasterizeTriangle(Point2f[] points, float[] zValues, float[][] zBuffer, GraphicsContext graphicsContext) {
        Color colorA = Color.RED;
        Color colorB = Color.BLACK;
        Color colorC = Color.BLUE;

        int minX = (int) Math.max(0, Math.floor(Math.min(points[0].getX(), Math.min(points[1].getX(), points[2].getX()))));
        int maxX = (int) Math.min(zBuffer.length - 1, Math.ceil(Math.max(points[0].getX(), Math.max(points[1].getX(), points[2].getX()))));
        int minY = (int) Math.max(0, Math.floor(Math.min(points[0].getY(), Math.min(points[1].getY(), points[2].getY()))));
        int maxY = (int) Math.min(zBuffer[0].length - 1, Math.ceil(Math.max(points[0].getY(), Math.max(points[1].getY(), points[2].getY()))));

        for (int x = minX; x <= maxX; x++) {
            for (int y = minY; y <= maxY; y++) {
                float[] barycentricCoords = calculateBarycentricCoordinates(points, x, y);
                float lambda0 = barycentricCoords[0];
                float lambda1 = barycentricCoords[1];
                float lambda2 = barycentricCoords[2];

                if (isPointInsideTriangle(lambda0, lambda1, lambda2)) {
                    float depth = interpolateDepth(lambda0, lambda1, lambda2, zValues);

                    if (depth < zBuffer[x][y]) {
                        zBuffer[x][y] = depth;
                        Color color = interpolateColor(lambda0, lambda1, lambda2, colorA, colorB, colorC);
                        graphicsContext.getPixelWriter().setColor(x, y, color);
                    }
                }
            }
        }
    }

    /**
     * Вычисляет барицентрические координаты точки относительно треугольника.
     *
     * @param points Координаты вершин треугольника.
     * @param x      Координата X точки.
     * @param y      Координата Y точки.
     * @return Массив из трех барицентрических координат.
     */
    private static float[] calculateBarycentricCoordinates(Point2f[] points, int x, int y) {
        float denominator = ((points[1].getY() - points[2].getY()) * (points[0].getX() - points[2].getX()) +
                (points[2].getX() - points[1].getX()) * (points[0].getY() - points[2].getY()));

        float lambda0 = ((points[1].getY() - points[2].getY()) * (x - points[2].getX()) +
                (points[2].getX() - points[1].getX()) * (y - points[2].getY())) / denominator;

        float lambda1 = ((points[2].getY() - points[0].getY()) * (x - points[2].getX()) +
                (points[0].getX() - points[2].getX()) * (y - points[2].getY())) / denominator;

        float lambda2 = 1.0f - lambda0 - lambda1;

        return new float[]{lambda0, lambda1, lambda2};
    }

    /**
     * Проверяет, находится ли точка внутри треугольника на основе барицентрических координат.
     *
     * @param lambda0 Барицентрическая координата λ0.
     * @param lambda1 Барицентрическая координата λ1.
     * @param lambda2 Барицентрическая координата λ2.
     * @return {@code true}, если точка внутри треугольника, иначе {@code false}.
     */
    private static boolean isPointInsideTriangle(float lambda0, float lambda1, float lambda2) {
        return lambda0 >= 0 && lambda1 >= 0 && lambda2 >= 0;
    }

    /**
     * Интерполирует значение глубины точки внутри треугольника.
     *
     * @param lambda0 Барицентрическая координата λ0.
     * @param lambda1 Барицентрическая координата λ1.
     * @param lambda2 Барицентрическая координата λ2.
     * @param zValues Массив значений глубины вершин треугольника.
     * @return Интерполированное значение глубины.
     */
    private static float interpolateDepth(float lambda0, float lambda1, float lambda2, float[] zValues) {
        return lambda0 * zValues[0] + lambda1 * zValues[1] + lambda2 * zValues[2];
    }

    /**
     * Интерполирует цвет точки внутри треугольника на основе барицентрических координат.
     *
     * @param lambda0 Барицентрическая координата λ0.
     * @param lambda1 Барицентрическая координата λ1.
     * @param lambda2 Барицентрическая координата λ2.
     * @param colorA  Цвет первой вершины треугольника.
     * @param colorB  Цвет второй вершины треугольника.
     * @param colorC  Цвет третьей вершины треугольника.
     * @return Интерполированный цвет.
     */
    private static Color interpolateColor(float lambda0, float lambda1, float lambda2, Color colorA, Color colorB, Color colorC) {
        double red = lambda0 * colorA.getRed() + lambda1 * colorB.getRed() + lambda2 * colorC.getRed();
        double green = lambda0 * colorA.getGreen() + lambda1 * colorB.getGreen() + lambda2 * colorC.getGreen();
        double blue = lambda0 * colorA.getBlue() + lambda1 * colorB.getBlue() + lambda2 * colorC.getBlue();
        return new Color(clamp(red), clamp(green), clamp(blue), 1.0);
    }

    /**
     * Ограничивает значение в диапазоне [0, 1].
     *
     * @param value Исходное значение.
     * @return Ограниченное значение.
     */
    private static double clamp(double value) {
        return Math.max(0.0, Math.min(1.0, value));
    }
}