0

编辑:我已经回答了这个问题并且代码已经更改,所以它是可用的,请随意在您自己的项目中使用代码。亲切的问候,利亚姆

我目前正在使用 LWJGL 进行 3D 模型渲染,我遇到了一个问题,当我运行程序时,显示出现并且除了模型之外一切都可以工作。我测试了 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;
    }
}
}

谢谢,利亚姆。

4

1 回答 1

0

好的,我解决了这个问题。

它在模型构造函数代码中,当 while 循环完成时,它没有将最后一组添加到列表中。这意味着如果只有一个组(或没有),它不会被添加到列表中并且不会被渲染。

我已经更改了问题中的模型代码,因此它可以使用,请随时在您的项目中使用它

亲切的问候,利亚姆

于 2012-12-14T04:49:56.247 回答