0

At the moment I have a pretty sweet little OBJ loader that I am using for my game that I am creating with LWJGL, and it has worked out great so far, however I attempted to use an .obj file I found on a NASA website or something, and it wouldn't load. I had a look at the file itself in a text editor and noticed two things that my current OBJ loader doesn't seem to account for. Firstly, this model had a .mtl file associated with it, and secondly, the "v", "vt", "vn", and "f" portions of the file seem to be scattered about the place, rather than all grouped together and in succession of one another like in the files I am used to dealing with.

In the tutorial I am following in order to make the base for my game, it is apparent that I am expected to simply use OBJs that are in a format such that there will be a bunch of lines starting with 'v', then with 'vt', blah blah blah. As such I am having a hard time actually finding models online that are compatible with my OBJ loader.

I have tried to also create my own model in Blender, a simple Earth model, just a sphere with a texture of Earth, but when I exported it I ended up with a MTL file (again, something my OBJ loader doesn't account for) and an error when I try to load it as it would appear there are no 'vn' lines in the file, so basically no normals associated with the model. I have little to no experience with Blender and I have found the tutorials that I have looked at to be no help as it's all very convoluted for a new user such as myself. Any quick steps to just "add normals" onto the model I am trying to export?

Here's the meat of my OBJ loader:

BufferedReader reader = new BufferedReader(fileReader);
    String line;
    List<Vector3f> vertices = new ArrayList<Vector3f>();
    List<Vector2f> textureCoords = new ArrayList<Vector2f>();
    List<Vector3f> normals = new ArrayList<Vector3f>();
    List<Integer> indices = new ArrayList<Integer>();
    float[] verticesArray = null;
    float[] normalsArray = null;
    float[] textureCoordsArray = null;
    int[] indicesArray = null;

    try {
        while (true)
        {
            line = reader.readLine();
            String[] currentLine = line.split(" ");

            if (currentLine[0].equals("v"))
            {
                Vector3f vertex = new Vector3f(Float.parseFloat(currentLine[1]), Float.parseFloat(currentLine[2]), Float.parseFloat(currentLine[3]));
                vertices.add(vertex);
            }
            else if (currentLine[0].equals("vt"))
            {
                Vector2f textureCoord = new Vector2f(Float.parseFloat(currentLine[1]), Float.parseFloat(currentLine[2]));
                textureCoords.add(textureCoord);
            }
            else if (currentLine[0].equals("vn"))
            {
                Vector3f normal = new Vector3f(Float.parseFloat(currentLine[1]), Float.parseFloat(currentLine[2]), Float.parseFloat(currentLine[3]));
                normals.add(normal);
            }
            else if (currentLine[0].equals("f"))
            {
                textureCoordsArray = new float[vertices.size() * 2];
                normalsArray = new float[vertices.size() * 3];
                break;
            }
        }

        while (line != null)
        {
            if (!line.startsWith("f "))
            {
                line = reader.readLine();
                continue;
            }

            String[] currentLine = line.split(" ");
            String[] vertex1 = currentLine[1].split("/");
            String[] vertex2 = currentLine[2].split("/");
            String[] vertex3 = currentLine[3].split("/");

            processVertex(vertex1, indices, textureCoords, normals, textureCoordsArray, normalsArray);
            processVertex(vertex2, indices, textureCoords, normals, textureCoordsArray, normalsArray);
            processVertex(vertex3, indices, textureCoords, normals, textureCoordsArray, normalsArray);

            line = reader.readLine();
        }

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

What can I do to allow my OBJ loader to handle more sophisticated .obj files?

Also any tips or advice about anything LWJGL related that can help me with developing a 3D lunar lander game?

genpfault
  • 51,148
  • 11
  • 85
  • 139
Jake
  • 1
  • 2
  • It's unclear what your specific problem is. The code you posted can easily be modified to handle the entries in any order. Where you currently break out of the loop when you find an `f`, just process the face right there, and stay in the loop. Then you won't need the second loop for the faces. You may have to size some of the arrays dynamically. But if you use a container like an `ArrayList` instead of a plain array, that comes for free. – Reto Koradi Feb 21 '15 at 19:23
  • Generally, reading OBJ files is somewhat of a pain because it's not an official standard, and depending on where they come from, certain aspects look different. There's no magic to support additional portions like materials. It's just more code you need to write to parse and process the information. – Reto Koradi Feb 21 '15 at 19:25
  • I hadn't thought of it that way, I guess I just thought that the file had to be in that specific fashion otherwise it wouldn't work. I don't know, I'm just very new to OpenGL/LWJGL and I've been cramming a bunch of new concepts into my head and it's all a little confusing. I'll try out what you have suggested and come back and edit my post if I have any luck or run into any issues. Thank you. – Jake Feb 21 '15 at 19:29
  • the most robust way is to not use obj. It's a beginners format, instead study the other formats that your modeling software can export in. (or create your own format that's more compact and faster than obj) – ratchet freak Feb 21 '15 at 21:51
  • Just do a single loop that goes over each line of the file, switch on the first characters, and add a vertex/texcoord/normal as they appear while you're reading them into a buffer, resizing as you need it. At the end of the file, trim the buffers and you're good to go. – TheStack Feb 24 '15 at 11:43

0 Answers0