Проблемы с отображением в LWJGL

EDIT: я ответил на вопрос, и код был изменен, чтобы его можно было использовать, не стесняйтесь использовать код в своих собственных проектах. С уважением, Лиам

В настоящее время я работаю над рендерингом 3D-моделей в LWJGL, и у меня возникла проблема: когда я запускаю программу, появляется дисплей, и все работает, кроме модели. Я протестировал код 3D-пространства с несколькими случайными точками, и я мог видеть их и ходить, поэтому мой код 3D-пространства работает, но не код модели.

Мой вопрос заключается в следующем: что-то не так с моим кодом отображения или это код загрузки моей модели, ниже приведен мой исходный код (извините за большое количество кода, но я не мог т сократить его).

Основная тема игры:

public class GameThread implements Runnable {

private boolean running;
private Camera cam = new Camera(0, 0, 0, 0, 0.25f, 25, new int[] {Keyboard.KEY_W, Keyboard.KEY_S, Keyboard.KEY_A, Keyboard.KEY_D});
private Model testModel;

@Override
public void run() 
{
    initialize();

    while(running)
    {
        if(Display.isCloseRequested())
            tryClose();

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        tick();
        Display.update();
    }

    close();
}

private void initialize()
{
    try
    {
        Display.setTitle("Test Game");
        Display.setDisplayMode(new DisplayMode(1280, 768));
        Display.setVSyncEnabled(true);
        Display.create();

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective((float) 30, 1024f / 768f, 0.001f, 100);
        glMatrixMode(GL_MODELVIEW);

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_BLEND);
        glEnable(GL_ALPHA_TEST);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

        testModel = new Model(this.getClass().getClassLoader().getResource("res\\untitled.obj"), new Vector3f(0, 0, 0), new Vector3f(0, 0, 0));
        cam.setPosition(new Vector3f(0, 0, -10));

        running = true;
    }
    catch(Exception e)
    {
        Display.destroy();
        e.printStackTrace();
        System.exit(1);
    }
}

private void tick()
{   
    cam.update();

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    testModel.draw();
}

private void tryClose()
{
    running = false;
}

private void close()
{
    Display.destroy();
}

Код загрузки/рендеринга модели:

public class Model {

private HashMap<String, ModelGroup> groups = new HashMap<String, ModelGroup>();
private Vector3f position, rotation;

public Model(URL modelLocation, Vector3f position, Vector3f rotation)
{
    this.setPosition(position);
    this.setRotation(rotation);

    try
    {
        BufferedReader in = new BufferedReader(new InputStreamReader(modelLocation.openStream()));

        String line;
        ModelGroup group = new ModelGroup("default");

        while((line = in.readLine()) != null)
        {
            if(line.startsWith("g "))
            {
                String newGroupName = (new StringTokenizer(line)).nextToken();

                if(newGroupName.equals(group.getGroupName()))
                    continue;

                groups.put(group.getGroupName(), group);
                group = new ModelGroup(newGroupName);
            }
            else if(line.startsWith("v "))
            {
                StringTokenizer vertices = new StringTokenizer(line);

                vertices.nextToken(); // Skips 'v'

                float x, y, z, w = 1;

                x = Float.valueOf(vertices.nextToken());
                y = Float.valueOf(vertices.nextToken());
                z = Float.valueOf(vertices.nextToken());

                if(vertices.hasMoreTokens())
                    w = Float.valueOf(vertices.nextToken());
                else
                    w = 1;

                group.addVertice(new Vector4f(x, y, z, w));                 
            }
            else if(line.startsWith("vn "))
            {
                StringTokenizer normalVertices = new StringTokenizer(line);

                normalVertices.nextToken(); // Skips 'vn'

                float x, y, z;

                x = Float.valueOf(normalVertices.nextToken());
                y = Float.valueOf(normalVertices.nextToken());
                z = Float.valueOf(normalVertices.nextToken());

                group.addNormal(new Vector3f(x, y, z));
            }
            else if(line.startsWith("vt "))
            {
                StringTokenizer textureVertices = new StringTokenizer(line);

                textureVertices.nextToken(); // Skips 'vt'

                float u, v, w;

                u = Float.valueOf(textureVertices.nextToken());

                if(textureVertices.hasMoreTokens())
                    v = Float.valueOf(textureVertices.nextToken());
                else
                    v = 0;

                if(textureVertices.hasMoreTokens())
                    w = Float.valueOf(textureVertices.nextToken());
                else
                    w = 0;

                group.addTextureCoordinate(new Vector3f(u, v, w));
            }
            else if(line.startsWith("f "))
            {
                StringTokenizer token = new StringTokenizer(line.replace('f', ' '));
                String[] indices = new String[token.countTokens()];

                int polygon_type = (indices.length == 3 ? GL_TRIANGLES : GL_QUADS);

                for(int i = 0; i < indices.length; i++)
                    indices[i] = token.nextToken();

                int mode = 0;

                if(line.contains("//"))
                    mode = 3;

                if(mode != 3)
                    if(indices[0].split("/").length == 2)
                        mode = 1;
                    else if(indices[0].split("/").length == 3)
                        mode = 2;

                if(mode == 0)
                {
                    Vector4f vertices = new Vector4f();
                    vertices.set(Float.valueOf(indices[0]), Float.valueOf(indices[1]), Float.valueOf(indices[2]), (indices.length == 4 ? Float.valueOf(indices[3]) : -1));

                    group.addFace(new ModelFace(vertices).setPolygonType(polygon_type));
                }
                else if(mode == 1)
                {
                    float x, y, z, vw;
                    float u, v, tw;

                    x = Float.valueOf(indices[0].split("/")[0]);
                    y = Float.valueOf(indices[1].split("/")[0]);
                    z = Float.valueOf(indices[2].split("/")[0]);

                    if(indices.length == 4)
                        vw = Float.valueOf(indices[3].split("/")[0]);
                    else
                        vw = -1;

                    u = Float.valueOf(indices[0].split("/")[1]);
                    v = Float.valueOf(indices[1].split("/")[1]);
                    tw = Float.valueOf(indices[2].split("/")[1]);

                    group.addFace(new ModelFace(new Vector4f(x, y, z, vw), new Vector3f(u, v, tw), new Vector3f(-1, 0, 0)).setPolygonType(polygon_type));
                }
                else if(mode == 2)
                {
                    float vx, vy, vz, vw;
                    float u, v, tw;
                    float nx, ny, nz;

                    vx = Float.valueOf(indices[0].split("/")[0]);
                    vy = Float.valueOf(indices[1].split("/")[0]);
                    vz = Float.valueOf(indices[2].split("/")[0]);

                    if(indices.length == 4)
                        vw = Float.valueOf(indices[3].split("/")[0]);
                    else
                        vw = -1;

                    u = Float.valueOf(indices[0].split("/")[1]);
                    v = Float.valueOf(indices[1].split("/")[1]);
                    tw = Float.valueOf(indices[2].split("/")[1]);

                    nx = Float.valueOf(indices[0].split("/")[2]);
                    ny = Float.valueOf(indices[1].split("/")[2]);
                    nz = Float.valueOf(indices[2].split("/")[2]);

                    group.addFace(new ModelFace(new Vector4f(vx, vy, vz, vw), new Vector3f(u, v, tw), new Vector3f(nx, ny, nz)).setPolygonType(polygon_type));
                }
                else if(mode == 3)
                {
                    float vx, vy, vz, vw;
                    float nx, ny, nz;

                    System.out.println(indices[0]);

                    vx = Float.valueOf(indices[0].split("//")[0]);
                    vy = Float.valueOf(indices[1].split("//")[0]);
                    vz = Float.valueOf(indices[2].split("//")[0]);

                    if(indices.length == 4)
                        vw = Float.valueOf(indices[3].split("//")[0]);
                    else
                        vw = -1;

                    nx = Float.valueOf(indices[0].split("//")[1]);
                    ny = Float.valueOf(indices[1].split("//")[1]);
                    nz = Float.valueOf(indices[2].split("//")[1]);

                    group.addFace(new ModelFace(new Vector4f(vx, vy, vz, vw), new Vector3f(-1, 0, 0), new Vector3f(nx, ny, nz)).setPolygonType(polygon_type));
                }
            }
        }

        groups.put(group.getGroupName(), group);
        in.close();
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
}   

public Vector3f getPosition() {
    return position;
}

public void setPosition(Vector3f position) {
    this.position = position;
}

public Vector3f getRotation() {
    return rotation;
}

public void setRotation(Vector3f rotation) {
    this.rotation = rotation;
}

public void draw()
{
    ArrayList<ModelGroup> groups = new ArrayList<ModelGroup>(this.groups.values());

    for(int i = 0; i < groups.size(); i++)
        drawGroup(groups.get(i).getGroupName());
}

public void drawGroup(String name)
{
    ModelGroup group = groups.get(name);

    if(group == null)
        return;

    glPushMatrix();
    {
        glRotatef(rotation.x, 1, 0, 0);
        glRotatef(rotation.y, 0, 1, 0);
        glRotatef(rotation.z, 0, 0, 1);
        glTranslatef(position.x, position.y, position.z);

        for(ModelFace face : group.getFaces())
        {
            glBegin(face.getPolygonType());
            {
                for(int id = 0; id < 3; id++)
                {
                    Vector4f vertex = group.getVertices().get(face.getVerticeIndex(id));
                    glVertex4f(vertex.x, vertex.y, vertex.z, vertex.w);

                    if(face.hasTextureCoordinates())
                    {
                        Vector3f textureCoordinate = group.getTextureCoordinates().get(face.getTextureCoordinateIndex(id));
                        glTexCoord3f(textureCoordinate.x, textureCoordinate.y, textureCoordinate.z);
                    }

                    if(face.hasNormals())
                    {
                        Vector3f normal = group.getNormals().get(face.getNormalIndex(id));
                        glNormal3f(normal.x, normal.y, normal.z);
                    }
                }

                if(face.getPolygonType() == GL_QUADS)
                {
                    Vector4f vertex = group.getVertices().get(face.getVerticeIndex(3));
                    glVertex4f(vertex.x, vertex.y, vertex.z, vertex.w);
                }
            }
            glEnd();
        }
    }
    glPopMatrix();
}

//====================================================================================================//

private class ModelGroup
{
    private final String groupName;

    private ArrayList<Vector4f> vertices = new ArrayList<Vector4f>();
    private ArrayList<Vector3f> normals = new ArrayList<Vector3f>();
    private ArrayList<Vector3f> textureCoordinates = new ArrayList<Vector3f>();
    private ArrayList<ModelFace> faces = new ArrayList<ModelFace>();

    public ModelGroup(String name) {
        this.groupName = name;
    }

    public String getGroupName() {
        return this.groupName;
    }

    public void addVertice(Vector4f vertice) {
        this.vertices.add(vertice);
    }

    public ArrayList<Vector4f> getVertices() {
        return this.vertices;
    }

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

    public ArrayList<Vector3f> getNormals() {
        return this.normals;
    }

    public void addTextureCoordinate(Vector3f coordinate) {
        this.textureCoordinates.add(coordinate);
    }

    public ArrayList<Vector3f> getTextureCoordinates() {
        return this.textureCoordinates;
    }

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

    public ArrayList<ModelFace> getFaces() {
        return this.faces;
    }
}

private class ModelFace {

    private Vector4f vertices;
    private Vector3f textureCoordinates, normals;
    private int POLYGON_TYPE = 0;

    private boolean hasTextureCoords = true, hasNormals = true;

    public ModelFace(Vector4f vertices) {
        this(vertices, new Vector3f(-1, 0, 0), new Vector3f(-1, 0, 0));
    }

    public ModelFace(Vector4f vertices, Vector3f textureCoordinates, Vector3f normals)
    {
        this.vertices = vertices;
        this.textureCoordinates = textureCoordinates;
        this.normals = normals;

        if(this.textureCoordinates.x == -1)
            this.hasTextureCoords = false;

        if(this.normals.x == -1)
            this.hasNormals = false;
    }

    public boolean hasTextureCoordinates() {
        return this.hasTextureCoords;
    }

    public boolean hasNormals() {
        return this.hasNormals;
    }

    public int getVerticeIndex(int id)
    {
        if(id == 0)
            return (int)vertices.x - 1;
        else if(id == 1)
            return (int)vertices.y - 1;
        else if(id == 2)
            return (int)vertices.z - 1;
        else if(id == 3)
            return (int)vertices.w - 1;
        else
            return -1;
    }

    public int getTextureCoordinateIndex(int id)
    {
        if(id == 0)
            return (int)textureCoordinates.x - 1;
        else if(id == 1)
            return (int)textureCoordinates.y - 1;
        else if(id == 2)
            return (int)textureCoordinates.z - 1;
        else
            return -1;
    }

    public int getNormalIndex(int id)
    {
        if(id == 0)
            return (int)textureCoordinates.x - 1;
        else if(id == 1)
            return (int)textureCoordinates.y - 1;
        else if(id == 2)
            return (int)textureCoordinates.z - 1;
        else
            return -1;
    }

    public ModelFace setPolygonType(int type) {
        this.POLYGON_TYPE = type;
        return this;
    }

    public int getPolygonType() {
        return this.POLYGON_TYPE;
    }
}
}

Спасибо, Лиам.


person Liam Haworth    schedule 14.12.2012    source источник


Ответы (1)


Хорошо, я исправил проблему.

Это было в коде конструктора модели, когда цикл while завершился, он не добавил последнюю группу в список. Это означало, что если бы была только одна группа (или ни одной), она не была бы добавлена ​​в список и не отображалась бы.

Я изменил код модели в вопросе, чтобы его можно было использовать, не стесняйтесь использовать его в своих проектах

С уважением, Лиам

person Liam Haworth    schedule 14.12.2012