在 LWJGL 中加载 MTL 文件

Load MTL Files in LWJGL

所以我正在使用 LWJGL 制作 "game",然后我开始加载 3D 模型(使用 Wavefront .obj 文件)。我已经成功加载了模型,但我没有纹理,而是想尝试 .mtl 文件来指定材料。我 "sort of" 做到了,但似乎还没有完全奏效。这是我的代码,以及我尝试渲染的树模型的图片: Tree Model

现在这是我的代码:

    private static OBJMesh mesh;

public static Mesh load3DModel(String objFileName)
{
    mesh = new OBJMesh();

    BufferedReader reader = null;

    try
    {
        reader = new BufferedReader(new FileReader(new File(objFileName)));
    }
    catch (FileNotFoundException e)
    {
        System.err.println("Could not locate OBJ File at " + objFileName);
        e.printStackTrace();
    }

    String mtlFileName = null;
    String line = null;
    String currentFaceMat = null;
    try
    {
        while ((line = reader.readLine()) != null)
        {
            String[] lineParts = line.split(" ");
            switch (line.substring(0, 2))
            {
            case "v ":
                Vertex v = new Vertex(lineParts[1], lineParts[2], lineParts[3]);
                mesh.addVertex(v);
                break;
            case "vn":
                Normal n = new Normal(lineParts[1], lineParts[2], lineParts[3]);
                mesh.addNormal(n);
                break;
            case "mt":
                mtlFileName = FileHelper.getDirectory(objFileName) + lineParts[1];
                break;
            case "us":
                currentFaceMat = lineParts[1];
                break;
            case "f ":
                Face face = createFace(currentFaceMat, lineParts);
                mesh.addFace(face);
                break;
            }
        }

        reader = new BufferedReader(new FileReader(mtlFileName));

        Material mat = null;
        while ((line = reader.readLine()) != null)
        {
            String[] lineParts = line.split(" ");

            if (line.length() > 1)
            {
                switch (line.substring(0, 2))
                {
                case "ne":
                    mat = new Material(lineParts[1]);
                    mesh.addMaterial(lineParts[1], mat);
                    break;
                case "Ka":
                    mat.setKa(createVector(lineParts));
                    break;
                case "Kd":
                    mat.setKd(createVector(lineParts));
                    break;
                case "Ks":
                    mat.setKs(createVector(lineParts));
                    break;
                case "Ns":
                    mat.setNs(Float.parseFloat(lineParts[1]));
                    break;
                case "d ":
                    mat.setD(Float.parseFloat(lineParts[1]));
                    break;
                case "il":
                    mat.setIllum(Integer.parseInt(lineParts[1]));
                    break;
                }
            }
        }

        reader.close();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }

    mesh.normalArray = new float[mesh.vertices.size() * 3];

    for (Face face : mesh.faces)
    {
        decodeNormals(face.indices1);
        decodeNormals(face.indices2);
        decodeNormals(face.indices3);
    }

    mesh.vertexArray = new float[mesh.vertices.size() * 3];
    mesh.indexArray = new int[mesh.indices.size() * 3];
    mesh.colorArray = new float[mesh.faces.size() * 3];

    int vertexPointer = 0;
    for (Vertex vertex : mesh.vertices)
    {
        mesh.vertexArray[vertexPointer++] = vertex.x;
        mesh.vertexArray[vertexPointer++] = vertex.y;
        mesh.vertexArray[vertexPointer++] = vertex.z;
    }

    for (int i = 0; i < mesh.indices.size(); i++)
    {
        mesh.indexArray[i] = mesh.indices.get(i);
    }

    int colorPointer = 0;
    for (Face face : mesh.faces)
    {
        mesh.colorArray[colorPointer++] = mesh.materials.get(face.material).Kd.x;
        mesh.colorArray[colorPointer++] = mesh.materials.get(face.material).Kd.y;
        mesh.colorArray[colorPointer++] = mesh.materials.get(face.material).Kd.z;
    }

    return MeshLoader.genVertexModel(mesh.vertexArray, mesh.indexArray, mesh.colorArray);
}

private static Face createFace(String materialName, String[] lineData)
{
    String[] indices1 = General.replaceEmptySlashes(lineData[1]).split("/");
    String[] indices2 = General.replaceEmptySlashes(lineData[2]).split("/");
    String[] indices3 = General.replaceEmptySlashes(lineData[3]).split("/");

    return new Face(materialName, indices1, indices2, indices3);
}

private static Vector3f createVector(String[] lineData)
{
    float x = Float.parseFloat(lineData[1]);
    float y = Float.parseFloat(lineData[2]);
    float z = Float.parseFloat(lineData[3]);

    return new Vector3f(x, y, z);
}

private static void decodeNormals(Vector3f vertex)
{
    int vertexPointer = (int) vertex.x - 1;
    mesh.indices.add(vertexPointer);
    Normal normal = mesh.normals.get((int) vertex.z - 1);
    mesh.normalArray[vertexPointer * 3] = normal.x;
    mesh.normalArray[vertexPointer * 3 + 1] = normal.y;
    mesh.normalArray[vertexPointer * 3 + 2] = normal.z;
}

OBJMesh class:

    public List<Vertex> vertices = new ArrayList<Vertex>();
public List<Normal> normals = new ArrayList<Normal>();
public List<Integer> indices = new ArrayList<Integer>();
public List<Face> faces = new ArrayList<Face>();
public Map<String, Material> materials = new HashMap<String, Material>();

public float[] vertexArray;
public float[] normalArray;
public float[] colorArray;
public int[] indexArray;

public void addVertex(Vertex vertex)
{
    vertices.add(vertex);
}

public void addNormal(Normal normal)
{
    normals.add(normal);
}

public void addMaterial(String name, Material material)
{
    materials.put(name, material);
}

public void addFace(Face face)
{
    faces.add(face);
}

脸 class:

    public Vector3f indices1;
public Vector3f indices2;
public Vector3f indices3;
public String material;

public Face(String material, String[] v1, String[] v2, String[] v3)
{
    this.material = material;
    this.indices1 = new Vector3f(Float.parseFloat(v1[0]), Float.parseFloat(v1[1]), Float.parseFloat(v1[2]));
    this.indices2 = new Vector3f(Float.parseFloat(v2[0]), Float.parseFloat(v2[1]), Float.parseFloat(v2[2]));
    this.indices3 = new Vector3f(Float.parseFloat(v3[0]), Float.parseFloat(v3[1]), Float.parseFloat(v3[2]));
}

Material class 仅包含 RGB 值。

如果你能找到什么,请告诉我;我一直在寻找几周(不是开玩笑!)。谢谢

OpenGL 期望所有顶点属性都是每个顶点的。您目前填充 colorArray 的方式表明您只是针对每张脸执行此操作。更改它,它应该会给出正确的结果。