【问题标题】:Wavefront OBJ Loading Error: Missing and incorrect facesWavefront OBJ 加载错误:缺少和不正确的面
【发布时间】:2014-08-26 03:24:24
【问题描述】:

我正在尝试为我正在制作的游戏加载 Wavefront OBJ 文件。我把它记下来了……有点。某些面在渲染时丢失,或者它们的顶点位置不正确。我加载它们的方式可能也不是很优化。我正在使用 LWJGL 和它的 OpenGL 绑定(我认为它是一个绑定)来渲染我的模型。

这是模型的外观: http://i1291.photobucket.com/albums/b560/DandDMC/blender2014-07-0415-28-40-23_zps0fbfcebb.png

这是游戏中的样子: http://i1291.photobucket.com/albums/b560/DandDMC/javaw2014-07-0415-52-54-99_zpsdf14fb6c.png

这是加载方法:

public static Model loadModel(String fileLocation)
{
    File file = new File(fileLocation);

    if(!file.exists())
    {
        try
        {
            throw new FileNotFoundException("The file named: " + fileLocation + " doesn't exist!");
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }

        return null;
    }

    ArrayList<Vertex> vertices = new ArrayList<Vertex> ();
    ArrayList<Vertex> texVertices = new ArrayList<Vertex> ();
    ArrayList<Face> faces = new ArrayList<Face> ();

    try
    {
        BufferedReader r = new BufferedReader(new FileReader(file));
        String s = "";

        int refIndex = 1;

        int vertIndex = 1;
        int texVertIndex = 1;

        while((s = r.readLine()) != null)
        {               
            String[] split = s.split(" ");

            if(split[0].equals("v"))
            {
                vertices.add(new Vertex(Double.parseDouble(split[1]), Double.parseDouble(split[2]), Double.parseDouble(split[3]), vertIndex));
                vertIndex ++;
            }
            else if(split[0].equals("vt"))
            {
                texVertices.add(new Vertex(Double.parseDouble(split[1]), Double.parseDouble(split[2]), 0.0, texVertIndex));
                texVertIndex ++;
            }
            else if(split[0].equals("f"))
            {
                ArrayList<Integer> vert = new ArrayList<Integer> ();
                ArrayList<Integer> texVert = new ArrayList<Integer> ();

                for(int i = 1; i < split.length; i ++)
                {
                    String[] fSplit = split[i].split("/");

                    vert.add(Integer.parseInt(fSplit[0]));
                    texVert.add(Integer.parseInt(fSplit[1]));
                }

                faces.add(new Face(vert, texVert));
            }
            else if(split[0].equals("#") || split[0].equals("o") || split[0].equals("mtllib") || split[0].equals("usemtl") || split[0].equals("s"))
            {
                // Don't have a use for as of now
            }
            else
            {
                throw new Exception("The syntax at line: " + refIndex + " is incorrect.");
            }

            refIndex ++;
        }

        r.close();
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }

    return new Model(vertices, texVertices, faces);
}

这是 Face 类(非常简单):

package com.glh.model;

import java.util.*;

public class Face
{
public ArrayList<Integer> verticeIndexes;
public ArrayList<Integer> texVerticeIndexes;

public Face(ArrayList<Integer> verticeIndexes, ArrayList<Integer> texVerticeIndexes)
{
    this.verticeIndexes = verticeIndexes;
    this.texVerticeIndexes = texVerticeIndexes;
}

public ArrayList<Vertex> getVertexPositions(Model parentModel)
{
    ArrayList<Vertex> l = new ArrayList<Vertex> ();

    for(int i : verticeIndexes)
    {
        l.add(parentModel.vertices.get(i - 1));
    }

    return l;
}

public ArrayList<Vertex> getTextureVertexPositions(Model parentModel)
{
    ArrayList<Vertex> l = new ArrayList<Vertex> ();

    for(int i : texVerticeIndexes)
    {
        l.add(parentModel.texVertices.get(i - 1));
    }

    return l;
}

}

Vertex 类更简单:

package com.glh.model;

public class Vertex
{
public double x;
public double y;
public double z;
public int index;

public Vertex(double x, double y, double z, int index)
{
    this.x = x;
    this.y = y;
    this.z = z;
    this.index = index;
}

public Vertex()
{
    this(0.0, 0.0, 0.0, 0);
}
}

以及渲染它的方法:

public void renderModel_tri(Model m)
{
    // The model is much smaller in Blender
    glScalef(0.3F, 0.3F, 0.3F);

    glBegin(GL_QUADS);

    for(Face f : m.faces)
    {
        ArrayList<Vertex> vertices = f.getVertexPositions(m);
        ArrayList<Vertex> texVertices = f.getTextureVertexPositions(m);

        for(int i = 0; i < vertices.size(); i ++)
        {
            Vertex vert = vertices.get(i);
            Vertex texVert = texVertices.get(i);

            glTexCoord2d(texVert.x, texVert.y);
            glVertex3d(vert.x, vert.y, vert.z);
        }
    }

    glEnd();
}

Model 类只包含所有顶点和面的列表。

package com.glh.model;

import java.util.*;

public class Model
{
public ArrayList<Vertex> vertices;
public ArrayList<Vertex> texVertices;
public ArrayList<Face> faces;

public Model(ArrayList<Vertex> vertices, ArrayList<Vertex> texVertices, ArrayList<Face> faces)
{
    this.vertices = vertices;
    this.texVertices = texVertices;
    this.faces = faces;
}
}

【问题讨论】:

  • 你为什么要删除你最近的问题?如果您有兴趣,我有一个中肯的答案。
  • 哎呀,最近的评论证实了我的怀疑,所以我想我会摆脱它,虽然我在任何地方都看不到取消删除按钮,所以你可以把它发给我,呵呵, stackoverflow noob 错误 xD
  • 我已经投票支持取消删除,但我怀疑会有其他 14 位成员支持它。我也不知道怎么PM你。
  • 简短的回答是,您无法从未定义的行为中恢复。一旦调用了未定义的行为,就会出现问题。未定义的行为并不一定意味着崩溃或任何用户或程序员可观察到的行为。这只是意味着程序没有按照标准定义的方式运行。
  • 在某些未定义行为的情况下,例如取消对空指针的引用,在某些环境中,会引发一个信号,您可能能够注册一个处理程序以为此信号调用。然后将调用您的处理程序,您可能能够向用户发送一条消息,其中包含有关崩溃位置的一些相关信息。阅读signal 的手册并尝试为SIGILLSIGBUSSIGSEGV 注册一个处理程序。提供位置可能非常困难并且非常特定于系统,但您仍然可以提供有用的信息,甚至重新启动程序。

标签: opengl model render lwjgl .obj


【解决方案1】:

我找到了...我的模型是由三角形组成的,我在游戏中绘制了 QUADS。我改变了: glBegin(GL_QUADS);到 glBegin(GL_TRIANGLES);

【讨论】:

  • 您可以使用GL_TRIANGLE_FAN。然后,无论您的面有多少个顶点,它都会起作用。这是唯一的问题吗?我昨天看你的问题时看到了这个。但是根据图片,我认为仅此一项并不能解释您得到的输出。
  • 在我将 QUADS 与 TRIANGLES 交换之前的模型让我觉得还有更多问题。但这是我发现的唯一问题,模型现在可以完美渲染。我尝试了“GL_TRIANGLES_FAN”,它可以工作,但我只尝试了由三角形制成的模型。 (并不是说它有什么不同,因为只需在 Blender 中按 Ctrl + T 并将它们渲染为 GL_TRIANGLES 就很容易了。
猜你喜欢
  • 2023-03-27
  • 2017-12-25
  • 1970-01-01
  • 2016-07-19
  • 1970-01-01
  • 2013-09-09
  • 2016-07-27
  • 2018-07-09
  • 2015-08-15
相关资源
最近更新 更多