Java OpenGL中带变换矩阵的多网格合并为单个网格

Java OpenGL中带变换矩阵的多网格合并为单个网格,java,opengl,3d,lwjgl,matrix-multiplication,Java,Opengl,3d,Lwjgl,Matrix Multiplication,我尝试将具有变换矩阵的多个网格合并为单个网格。 每个网格有4个数据集 顶点 指数 纹理坐标 常态 我尝试这样做的方式应该是懒惰的,并且不会花费那么多CPU。 这是一个三步过程 将每个顶点和法线与变换矩阵相乘 将每个网格的顶点、纹理坐标和法线合并为3个大数组 将每个网格的索引合并到单个数组中,但使用以前网格的总和作为偏移。例如:如果网格1有800个索引,则必须将800添加到网格2的所有索引中 这种方法有两大问题 不共享重复的顶点 由于剪裁而不可见的零件不会被删除 但这是可以的,因为这应该是一个没有

我尝试将具有变换矩阵的多个网格合并为单个网格。 每个网格有4个数据集

  • 顶点
  • 指数
  • 纹理坐标
  • 常态
  • 我尝试这样做的方式应该是懒惰的,并且不会花费那么多CPU。 这是一个三步过程

  • 将每个顶点和法线与变换矩阵相乘
  • 将每个网格的顶点、纹理坐标和法线合并为3个大数组
  • 将每个网格的索引合并到单个数组中,但使用以前网格的总和作为偏移。例如:如果网格1有800个索引,则必须将800添加到网格2的所有索引中
  • 这种方法有两大问题

  • 不共享重复的顶点
  • 由于剪裁而不可见的零件不会被删除
  • 但这是可以的,因为这应该是一个没有太多CPU使用的惰性方法。它已经是为草地和灌木创建网格的最佳选择

    我已尝试实现此方法,如下所示:

    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;
    }
    
        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);
    
    第二个问题是第二个网格的纹理有点不对劲

    这是一张照片:

    如您所见,第二个网格只有实际纹理的1/4左右

    我用于生成此网格的代码如下所示:

    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;
    }
    
        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);
    
    我现在的问题是:我做错了什么?为什么纹理如此怪异,为什么转换的乘法对翻译不起作用


    如果您需要更多的代码,我这里有一个Eclipse项目的GitHub Repo:

    多亏了@rabbi76,我更接近我的答案,现在我终于找到了问题所在。 翻译不起作用的第一个问题是通过将转换垂直相乘而不是水平相乘来解决的。再次感谢@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;
    }
    
    publicstaticfinalmeshdatamergelazy(列表网格、列表变换){
    ArrayList顶点=新建ArrayList();
    ArrayList texCoords=新的ArrayList();
    ArrayList法线=新的ArrayList();
    ArrayList索引=新的ArrayList();
    整数偏移=0;
    int m=0;
    用于(网格数据网格:网格){
    Matrix4f transformation=transformations.get(m);
    float[]mVertices=mesh.getVertices();
    float[]mNormals=mesh.getNormals();
    对于(int index=0;index
    必须是
    结果。x=x*matrix.m00+y*matrix.m01+z*matrix.m02+1.0*matrix.m03…难道整个方法不只有在网格使用相同纹理时才有效吗?@BDL是的。创建大量不同的草地和灌木网格是一种懒惰的方法,这些网格从每一侧使用相同的纹理。@rabbi76结果仍然相同,但您是正确的,应该是这样的。噢,可能必须是
    result.x=x*matrix.m00+y*matrix.m10+z*matrix.m20+matrix.m30。通常,翻译是(m30、m31、m32)。注意,数学矩阵和OpenGL矩阵的内存图像之间存在差异。