Ошибка загрузки объекта Wavefront: отсутствующие и неправильные грани

#opengl #model #render #lwjgl #.obj

#opengl #Модель #визуализация #lwjgl #.obj

Вопрос:

Я пытаюсь загрузить файлы 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;
}
}
  

Комментарии:

1. почему вы удалили свой последний вопрос? У меня есть подходящий ответ, если вам интересно.

2. Упс, самый последний комментарий подтвердил мои подозрения, поэтому я решил избавиться от него, хотя я нигде не вижу кнопки восстановления, так что вы, вероятно, могли бы написать мне об этом в личку, хех, ошибка новичка stackoverflow xD

3. Я проголосовал за восстановление, но сомневаюсь, что найдется еще 14 участников, которые поддержат это. Я тоже не знаю, как вам написать в личку.

4. Короткий ответ — нет , вы не можете восстановиться после неопределенного поведения. Как только вызывается неопределенное поведение, что-то идет не так. Неопределенное поведение не обязательно означает сбой или даже любое поведение, наблюдаемое пользователем или программистом. Это просто означает, что программа ведет себя не так, как определено стандартом.

5. В некоторых случаях неопределенного поведения, таких как разыменование нулевого указателя, в некоторых средах выдается сигнал, и вы могли бы зарегистрировать обработчик, который будет вызываться для этого сигнала. После этого будет вызван ваш обработчик, и вы сможете передать пользователю сообщение с некоторой релевантной информацией о месте сбоя. Прочитайте руководство для signal и попробуйте зарегистрировать обработчик для SIGILL , SIGBUS и SIGSEGV . Указать местоположение может быть довольно сложно и зависит от системы, но вы все равно можете предоставить полезную информацию и даже перезапустить программу.

Ответ №1:

Я нашел это… Моя модель состоит из треугольников, а в игре я рисовал квадратики. Я изменил: glBegin(GL_QUADS); на glBegin(GL_TRIANGLES);

Комментарии:

1. Вы можете использовать GL_TRIANGLE_FAN . Тогда это будет работать независимо от того, сколько вершин у ваших граней. Это была единственная проблема? Я увидел это, когда вчера смотрел на ваш вопрос. Но, основываясь на картинке, я не думал, что это само по себе объясняет результат, который вы получали.

2. Модель до того, как я поменял КВАДРАТИКИ местами с ТРЕУГОЛЬНИКАМИ, заставила меня подумать, что проблем тоже было больше. Но это единственная проблема, которую я обнаружил, и теперь модели отображаются идеально. И я попробовал ‘GL_TRIANGLE_FAN’, это работает, но я пробовал это только с моделями, состоящими из треугольников. (Не то чтобы это имело большое значение, потому что достаточно просто нажать Ctrl T в Blender и отобразить их как GL_TRIANGLES.