Render .obj file doesn't work

Started by kululu, April 25, 2014, 23:37:06

Previous topic - Next topic

kululu

I'm learning openGL for educational purposes and for the fun of it now and I'm trying to render a 3D model of a bunny.

I tried to render the .obj file but nothing shows up on my screen, here's the code :

MainDisplay class :
package com.dryadengine.gui;

import com.dryadengine.core.Model;
import com.dryadengine.framework.OBJLoader;
import com.dryadengine.framework.ShaderFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import org.lwjgl.util.vector.Matrix4f;

/**
 *
 * @author Roy
 */
public class MainDisplay {

    private Model bunny;
    private Matrix4f mProjection;
    private Matrix4f mView;
    private Matrix4f mModel;
    private int shaderProgramID;
    private int vboID;
    private int vPositionID;
    private int mProjectionID;
    private int mViewID;
    private int mModelID;
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        MainDisplay md = new MainDisplay();
        md.create();
        md.init();
        md.run();
    }
    
    public MainDisplay() {
        
    }
    
    public void create() {
        try {
            Display.setDisplayMode(new DisplayMode(800, 600));
            Display.setTitle("Dryad Engine 1.0.0");
            Display.setFullscreen(false);
            Display.setResizable(true);
            Display.create();
        } catch (LWJGLException ex) {
            Logger.getLogger(MainDisplay.class.getName()).log(Level.SEVERE, null, ex);
            System.exit(-1);
        }
    }
    
    public void init() {
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        try {
            shaderProgramID = ShaderFactory.createShaderProgram("vertexShader", "fragmentShader");
            glUseProgram(shaderProgramID);
            bunny = OBJLoader.parseOBJ(new File("src/com/dryadengine/assets/bunny.obj"));
            FloatBuffer vbo = BufferUtils.createFloatBuffer(bunny.getVertices().length);
            vbo.put(bunny.getVertices());
            vbo.flip();
            vboID = glGenBuffers();
            glBindBuffer(GL_ARRAY_BUFFER, vboID);
            glBufferData(GL_ARRAY_BUFFER, vbo, GL_STATIC_DRAW);
            vPositionID = glGetAttribLocation(shaderProgramID, "vPosition");
            glEnableVertexAttribArray(vPositionID);
            mProjection = new Matrix4f();
            float fieldOfView = 60f;
            float aspectRatio = (float)Display.getWidth() / (float)Display.getHeight();
            float nearPlane = 0.1f;
            float farPlane = 100f;
            float yScale = (float)(1.0f / Math.tan((fieldOfView / 2.0f) * Math.PI / 180));//this.coTangent(this.degreesToRadians(fieldOfView / 2f));
            float xScale = yScale / aspectRatio;
            float frustum_length = farPlane - nearPlane;
            mProjection.m00 = xScale;
            mProjection.m11 = yScale;
            mProjection.m22 = -((farPlane + nearPlane) / frustum_length);
            mProjection.m23 = -1;
            mProjection.m32 = -((2 * nearPlane * farPlane) / frustum_length);
            mProjection.m33 = 0;
            mView = new Matrix4f();
            mView.m23 = -5;
            mModel = new Matrix4f();
            mProjectionID = glGetUniformLocation(shaderProgramID, "mProjection");
            mViewID = glGetUniformLocation(shaderProgramID, "mView");
            mModelID = glGetUniformLocation(shaderProgramID, "mModel");
            glEnable(GL_CULL_FACE);
            glCullFace(GL_BACK);
            glEnable(GL_DEPTH_TEST);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(MainDisplay.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(MainDisplay.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    
    
    public void run() {
        while (!Display.isCloseRequested()) {
            if (Display.isVisible()) {
                render();
            }
            if (Display.wasResized()) {
                reshape();
            }
            Display.update();
            Display.sync(60);
        }
        destroy();
    }
    
    public void render() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        FloatBuffer fb1 = BufferUtils.createFloatBuffer(16);
        FloatBuffer fb2 = BufferUtils.createFloatBuffer(16);;
        FloatBuffer fb3 = BufferUtils.createFloatBuffer(16);;
        mProjection.store(fb1);
        mView.store(fb2);
        mModel.store(fb3);
        glUniformMatrix4(mProjectionID, true, fb1);
        glUniformMatrix4(mViewID, true, fb2);
        glUniformMatrix4(mModelID, true, fb3);
        for (int i = 0; i < bunny.getVertices().length / 3; i += 3) {
            glVertexAttribPointer(vPositionID, 3, GL_FLOAT, false, 0, i);
            glDrawArrays(GL_TRIANGLES, 0, 3);
        }
    }
    
    public void reshape() {
        glViewport(0, 0, Display.getWidth(), Display.getHeight());
    }
    
    public void dispose() {
        glDeleteProgram(shaderProgramID);
        glUseProgram(0);
        glDeleteBuffers(vboID);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
    
    public void destroy() {
        Display.destroy();
    }
}


ShaderFactory class :
package com.dryadengine.framework;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;

/**
 *
 * @author Roy
 */
public class ShaderFactory {
    
    private static final String COMMON_SHADERS_PATH = "/com/dryadengine/shaders/";
    private static final String SHADER_EXTENSION = ".dsf";
    
    /**
     * 
     * @param vertexShaderName
     * @param fragmentShaderName
     * @return a shader program
     * @throws FileNotFoundException
     * @throws IOException 
     */
    public static int createShaderProgram(String vertexShaderName, String fragmentShaderName) throws FileNotFoundException, IOException {
        ArrayList<Integer> shaders = new ArrayList();
        shaders.add(ShaderFactory.compileShader(GL_VERTEX_SHADER, getShaderFileCode(COMMON_SHADERS_PATH + vertexShaderName + SHADER_EXTENSION)));
        shaders.add(ShaderFactory.compileShader(GL_FRAGMENT_SHADER, getShaderFileCode(COMMON_SHADERS_PATH + fragmentShaderName + SHADER_EXTENSION)));
        return ShaderFactory.linkProgram(shaders);
    }
    
    /**
     * 
     * @param shaderFilePath
     * @return a shader file code
     * @throws FileNotFoundException
     * @throws IOException 
     */
    private static String getShaderFileCode(String shaderFilePath) throws FileNotFoundException, IOException {
        StringBuilder shaderCode = new StringBuilder();
        String line;
        try {
            try (BufferedReader br = new BufferedReader(new InputStreamReader(ShaderFactory.class.getResourceAsStream(shaderFilePath)))) {
                while ((line = br.readLine()) != null) {
                    shaderCode.append(line).append("\n");
                }
            }
        } catch (FileNotFoundException e) {
            throw new FileNotFoundException(e.getMessage());
        }
        return shaderCode.toString();
    }
    
    /**
     * 
     * @param shaderType
     * @param shaderCode
     * @return a compiled shader file id
     */
    public static int compileShader(int shaderType, String shaderCode) {
        int shaderID = glCreateShader(shaderType);
        glShaderSource(shaderID, shaderCode);
        glCompileShader(shaderID);
        int status = glGetShaderi(shaderID, GL_COMPILE_STATUS);
        if (status == GL_FALSE) {
            glDeleteShader(shaderID);
            throw new RuntimeException(glGetShaderInfoLog(shaderID, glGetShaderi(shaderID, GL_INFO_LOG_LENGTH)));
        }
        return shaderID;
    }
    
    /**
     * Link the vertex shader and the fragment shader to the shader program
     * @param shaders
     * @return a shader program
     */
    public static int linkProgram(ArrayList <Integer> shaders) {
        int shaderProgramID = glCreateProgram();
        for (Integer shader : shaders) {
            glAttachShader(shaderProgramID, shader);
        }
        glLinkProgram(shaderProgramID);
        int status = glGetProgrami(shaderProgramID, GL_LINK_STATUS);
        if (status == GL_FALSE) {
            glDeleteProgram(shaderProgramID);
            throw new RuntimeException(glGetShaderInfoLog(shaderProgramID, glGetProgrami(shaderProgramID, GL_INFO_LOG_LENGTH)));
        }
        for (int shader : shaders) {
            glDeleteShader(shader);
        }
        return shaderProgramID;
    }
    
}


OBJLoader class :
package com.dryadengine.framework;

import com.dryadengine.core.Model;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Roy
 */
public class OBJLoader {
    
    /**
     * Parse .obj file and make a model from it.
     * @param f
     * @return a model object
     * @throws FileNotFoundException
     * @throws IOException 
     */
    public static Model parseOBJ(File f) throws FileNotFoundException, IOException {
        BufferedReader br = new BufferedReader(new FileReader(f));
        String line;
        Model m;
        List<Float> vertices = new ArrayList<>();
        List<Float> normals = new ArrayList<>();
        while ((line = br.readLine()) != null) {
            if (line.startsWith("v")) {
                float x = Float.valueOf(line.split(" ")[1]);
                float y = Float.valueOf(line.split(" ")[2]);
                float z = Float.valueOf(line.split(" ")[3]);
                vertices.add(x);
                vertices.add(y);
                vertices.add(z);
            } else if (line.startsWith("vn")) {
                float x = Float.valueOf(line.split(" ")[1]);
                float y = Float.valueOf(line.split(" ")[2]);
                float z = Float.valueOf(line.split(" ")[3]);
                normals.add(x);
                normals.add(y);
                normals.add(z);
            }
        }
        br.close();
        float[] a = new float[vertices.size()];
        float[] b = new float[normals.size()];
        for (int i = 0; i < vertices.size(); i++) {
            a[i] = vertices.get(i);
        }
        for (int i = 0; i < normals.size(); i++) {
            b[i] = normals.get(i);
        }
        m = new Model(a, b);
        return m;
    }
    
}


Model class :
package com.dryadengine.core;

/**
 *
 * @author Roy
 */
public class Model {
    
    private float[] vertices;
    private float[] normals;
    
    /**
     * Construct a new model object.
     * @param vertices
     * @param normals 
     */
    public Model(float[] vertices, float[] normals) {
        this.vertices = vertices;
        this.normals = normals;
    }
    
    /**
     * 
     * @return the model vertices array
     */
    public float[] getVertices() {
        return vertices;
    }
    
    /**
     * 
     * @return the model normals array
     */
    public float[] getNormals() {
        return normals;
    }
    
}


vertex shader code :
#version 330

uniform mat4 mProjection;
uniform mat4 mView;
uniform mat4 mModel;

in vec4 vPosition;

void main()
{
    gl_Position = mProjection * mView * mModel * vPosition;
}


fragment shader code :
#version 330

out vec4 color;

void main()
{
    color = vec4(1.0, 0.0, 0.0, 1.0);
}


Result is just black screen

quew8

A) I cannot see any checking for OpenGL errors (with glGetError() ) and I'm not going to bother checking though all that code when it'll probably just turn out that there is a simple wrong argument call somewhere.

B) Isn't this the same topic as was created on the JGO forums and where there are answers? If so it is very bad practice to post the same question in two places without clearly shutting one post down.