Объединение нескольких сеток с матрицей преобразования в одну сетку в OpenGL - PullRequest
0 голосов
/ 25 августа 2018

Я пытаюсь объединить несколько сеток с матрицей преобразования в одну сетку.Каждая сетка имеет 4 набора данных.

  1. Вершины
  2. Индексы
  3. Координаты текстуры
  4. Нормы

ПутьЯ пытаюсь сделать это должно быть ленивым и не стоить так много процессора.Это трехэтапный процесс.

  1. Умножьте каждую вершину и нормаль на матрицу преобразования.
  2. Объедините вершины, координаты текстуры и нормали каждой сетки в 3 больших массива.
  3. Объедините индексы каждой сетки в один массив, но используйте сумму предыдущих сеток в качестве смещения.Например: если сетка 1 имеет 800 индексов, то 800 необходимо добавить ко всем индексам из сетки 2.

У этого метода есть две большие проблемы.

  1. Дублироватьвершины не являются общими
  2. Части, которые невидимы из-за отсечения, не удаляются

Но это нормально, так как предполагается, что это ленивый метод с небольшим использованием ЦП.Он уже оптимален для создания сеток для травы и кустов.

Я попытался реализовать этот метод, который выглядит следующим образом:

public static final MeshData mergeLazy(List<MeshData> meshes, List<Matrix4f> transformations) {

    int lengthVertices = 0;
    int lengthNormals = 0;
    int lengthTexCoords = 0;
    int lengthIndices = 0;
    ArrayList<Integer> indexLengths = new ArrayList<>();

    for(MeshData mesh : meshes) {

        lengthVertices += mesh.getVertices().length;
        lengthNormals += mesh.getNormals().length;
        lengthTexCoords += mesh.getTextureCoordinates().length;
        int length = mesh.getIndices().length;
        lengthIndices += length;
        indexLengths.add(length);
    }

    float[] vertices = new float[lengthVertices];
    float[] texCoords = new float[lengthTexCoords];
    float[] normals = new float[lengthNormals];
    int[] indices = new int[lengthIndices];

    int iv = 0;
    int ivt = 0;
    int ivn = 0;
    int i = 0;
    int indexLength = 0;

    for(int im = 0; im < meshes.size(); im++) {

        MeshData mesh = meshes.get(im);
        float[] mVertices = mesh.getVertices();
        float[] mTexCoords = mesh.getTextureCoordinates();
        float[] mNormals = mesh.getNormals();
        int[] mIndices = mesh.getIndices();
        Matrix4f transformation = transformations.get(im);

        for(int index = 0; index < mVertices.length; index += 3) {

            Vector3f vertex = MatrixUtil.multiply(transformation, mVertices[index], mVertices[index + 1], mVertices[index + 2]);
            vertices[iv++] = vertex.x;
            vertices[iv++] = vertex.y;
            vertices[iv++] = vertex.z;

            Vector3f normal = MatrixUtil.multiply(transformation, mNormals[index], mNormals[index + 1], mNormals[index + 2]);
            normals[ivn++] = normal.x;
            normals[ivn++] = normal.y;
            normals[ivn++] = normal.z;
        }

        for(int index = 0; index < mTexCoords.length; index++) {

            texCoords[ivt++] = mTexCoords[index];
        }

        for(int index = 0; index < mIndices.length; index++) {

            indices[i++] = indexLength + mIndices[index];
        }

        indexLength += indexLengths.get(im);
    }

    MeshData data = new MeshData();
    data.setIndices(indices);
    data.setNormals(normals);
    data.setTextureCoordinates(texCoords);
    data.setVertices(vertices);

    return data;
}

В конце концов, у меня фактически есть одна сетка иумножение преобразования также работает .... для вращения и масштабирования, но здесь возникают проблемы.

Умножение с преобразованием НЕ работает для перевода.Мой метод умножения матрицы на вектор выглядит следующим образом:

public static final Vector3f multiply(Matrix4f matrix, float x, float y, float z) {

    Vector3f result = new Vector3f();
    result.x = x * matrix.m00 + y * matrix.m01 + z * matrix.m02;
    result.y = x * matrix.m10 + y * matrix.m11 + z * matrix.m12;
    result.z = x * matrix.m20 + y * matrix.m21 + z * matrix.m22;
    return result;
}

И вторая проблема заключается в том, что текстуры второй сетки несколько отключены.

Вот картинка: Error

Как вы можете видеть, вторая сетка имеет только около 1/4 фактической текстуры.

Код, который я использовал для генерации этой сетки, выглядит следующим образом:

    Material grassMaterial = new Material();
    grassMaterial.setMinBrightness(0.1F);
    grassMaterial.setColorMap(new Texture(new XImgTextureReader().read(new FileInputStream("res/textures/grass2.ximg"))));
    grassMaterial.setAffectedByLight(true);
    grassMaterial.setTransparent(true);
    grassMaterial.setUpwardsNormals(true);
    grassMaterial.setFog(fog);

    MeshData quad = Quad.generateMeshData(
        new Vector3f(0.0F, 1F, 0.0F),
        new Vector3f(0.0F, 0.0F, 0.0F),
        new Vector3f(1F, 0.0F, 0.0F),
        new Vector3f(1F, 1F, 0.0F)
    );

    StaticMesh grassMesh = new StaticMesh(MeshUtil.mergeLazy(Arrays.asList(quad, quad), Arrays.asList(
        MatrixUtil.createTransformationMatrx(
            new Vector3f(0.0F, 0.0F, 0.0F),
            new Vector3f(0.0F, 0.0F, 0.0F),
            new Vector3f(1.0F, 1.0F, 1.0F)
        ),
        MatrixUtil.createTransformationMatrx(
            new Vector3f(0F, 0.0F, -0F),
            new Vector3f(0.0F, 90.0F, 0.0F),
            new Vector3f(1.0F, 1.0F, 1.0F)
        )
    )));
    grassMesh.setCullMode(StaticMesh.CULLING_DISABLED);

    Entity grass = new Entity();
    grass.setShaderPipeline(shaderPipeline);
    grass.setMaterial(grassMaterial);
    grass.setMesh(grassMesh);
    grass.setTranslation(0, 0, 1);

Мой вопрос сейчас: что я сделал не так?Почему текстура такая странная и почему умножение с преобразованием не работает для перевода?

Если вам нужно больше кода, у меня есть репозиторий GitHub с проектом Eclipse: https://github.com/RalleYTN/Heroica-Fabulis

1 Ответ

0 голосов
/ 26 августа 2018

Благодаря @ Rabbid76 я подошел к своему ответу и теперь, наконец, нашел проблему. Первая проблема с неработающим переводом была исправлена ​​путем умножения преобразования по вертикали, а не по горизонтали. Еще раз спасибо @ Rabidd76.

И причина, по которой текстуры такие странные, в том, что я неправильно слил индексы. Я не должен был принимать сумму всех индексов в ячейках до смещения, а сумму вершин.

Вот теперь рабочий метод:

public static final MeshData mergeLazy(List<MeshData> meshes, List<Matrix4f> transformations) {

    ArrayList<Float> vertices = new ArrayList<>();
    ArrayList<Float> texCoords = new ArrayList<>();
    ArrayList<Float> normals = new ArrayList<>();
    ArrayList<Integer> indices = new ArrayList<>();
    int offset = 0;
    int m = 0;

    for(MeshData mesh : meshes) {

        Matrix4f transformation = transformations.get(m);
        float[] mVertices = mesh.getVertices();
        float[] mNormals = mesh.getNormals();

        for(int index = 0; index < mesh.getVertices().length; index += 3) {

            Vector3f vertex = MatrixUtil.multiply(transformation, mVertices[index], mVertices[index + 1], mVertices[index + 2]);
            vertices.add(vertex.x);
            vertices.add(vertex.y);
            vertices.add(vertex.z);

            Vector3f normal = MatrixUtil.multiply(transformation, mNormals[index], mNormals[index + 1], mNormals[index + 2]);
            normals.add(normal.x);
            normals.add(normal.y);
            normals.add(normal.z);
        }

        ListUtil.addFloatArray(texCoords, mesh.getTextureCoordinates());
        int[] mIndices = mesh.getIndices();

        for(int index : mIndices) {

            indices.add(index + offset);
        }

        offset += mVertices.length / 3;
        m++;
    }

    MeshData mesh = new MeshData();
    mesh.setIndices(ListUtil.toPrimitiveIntArray(indices));
    mesh.setNormals(ListUtil.toPrimitiveFloatArray(normals));
    mesh.setTextureCoordinates(ListUtil.toPrimitiveFloatArray(texCoords));
    mesh.setVertices(ListUtil.toPrimitiveFloatArray(vertices));

    return mesh;
}
...