I have a parser for OBJ files and MTL Files however I keep on getting a null pointer exception even though it is there. I know I have my file correct because I double-check where the files are. resources (source file)/res/meshes/{}.obj,.mtl
Here is my MyFile class
package com.darkerminecraft.utils; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; public class MyFile { private static final String FILE_SEPARATOR = "/"; private String path; private String name; public MyFile(String path) { this.path = FILE_SEPARATOR + path; String[] dirs = path.split(FILE_SEPARATOR); this.name = dirs[dirs.length - 1]; } public MyFile(String... paths) { this.path = ""; for (String part : paths) { this.path += (FILE_SEPARATOR + part); } String[] dirs = path.split(FILE_SEPARATOR); this.name = dirs[dirs.length - 1]; } public MyFile(MyFile file, String subFile) { this.path = file.path + FILE_SEPARATOR + subFile; this.name = subFile; } public MyFile(MyFile file, String... subFiles) { this.path = file.path; for (String part : subFiles) { this.path += (FILE_SEPARATOR + part); } String[] dirs = path.split(FILE_SEPARATOR); this.name = dirs[dirs.length - 1]; } public String getPath() { return path; } @Override public String toString() { return getPath(); } public InputStream getInputStream() { return Class.class.getResourceAsStream(path); } public BufferedReader getReader() throws Exception { try { InputStreamReader isr = new InputStreamReader(getInputStream()); BufferedReader reader = new BufferedReader(isr); return reader; } catch (Exception e) { System.err.println("Couldn't get reader for " + path); throw e; } } public String getName() { return name; } }
This is my parser class
package com.darkerminecraft.graphics.mesh; import java.util.ArrayList; import java.util.List; import org.joml.Vector3f; import com.darkerminecraft.utils.MyFile; public class MeshLoader { public static Mesh load3DModel(String fileName) { MyFile objFile = new MyFile("res/meshes/" + fileName + ".obj"); String line = ""; String mtlFileName = ""; String currentFaceMat = ""; Mesh mesh = new Mesh(); try { while ((line = objFile.getReader().readLine()) != null) { String[] lineParts = line.split(" "); switch (line.substring(0, 2)) { case "v ": Vertex v = new Vertex(createVector(lineParts)); mesh.addVertex(v); break; case "vn": Normal n = new Normal(createVector(lineParts)); mesh.addNormal(n); break; case "mt": mtlFileName = lineParts[1]; break; case "us": currentFaceMat = lineParts[1]; break; case "f ": Face face = createFace(currentFaceMat, lineParts); mesh.addFace(face); break; } objFile.getReader().close(); } } catch (Exception e) { e.printStackTrace(); } MyFile mtlFile = new MyFile("res/meshes/" + mtlFileName + ".mtl"); Material mat = null; try { while ((line = mtlFile.getReader().readLine()) != null) { String[] lineParts = line.split(" "); switch (line.substring(0, 2)) { case "ne": mat = new Material(lineParts[1]); mesh.addMaterial(lineParts[1], mat); break; case "Ka": mat.setKa(createVector(lineParts)); break; case "Kd": mat.setKd(createVector(lineParts)); break; case "Ks": mat.setKs(createVector(lineParts)); break; case "Ns": mat.setNs(Float.parseFloat(lineParts[1])); break; case "d ": mat.setD(Float.parseFloat(lineParts[1])); break; case "il": mat.setIllum(Float.parseFloat(lineParts[1])); break; } mtlFile.getReader().close(); } } catch (Exception e) { e.printStackTrace(); } mesh.normalArray = new float[mesh.vertices.size() * 3]; for(Face face : mesh.faces) { decodeNormals(face.indices1, mesh); decodeNormals(face.indices2, mesh); decodeNormals(face.indices3, mesh); } List<Vertex> materialVertices = new ArrayList<>(); for(Face face : mesh.faces) { Vertex v1 = new Vertex(face.material, face.indices1); Vertex v2 = new Vertex(face.material, face.indices2); Vertex v3 = new Vertex(face.material, face.indices3); materialVertices.add(v1); materialVertices.add(v2); materialVertices.add(v3); } mesh.vertexArray = new float[mesh.vertices.size() * 3]; mesh.indexArray = new int[mesh.indices.size() * 3]; mesh.colorArray = new float[mesh.vertices.size() * 3]; int vertexPointer = 0; int colorPointer = 0; for(Vertex vertex : mesh.vertices) { mesh.vertexArray[vertexPointer++] = vertex.getPosition().x; mesh.vertexArray[vertexPointer++] = vertex.getPosition().y; mesh.vertexArray[vertexPointer++] = vertex.getPosition().z; mesh.colorArray[colorPointer++] = mesh.materials.get(vertex.getMaterialName()).getKd().x; mesh.colorArray[colorPointer++] = mesh.materials.get(vertex.getMaterialName()).getKd().y; mesh.colorArray[colorPointer++] = mesh.materials.get(vertex.getMaterialName()).getKd().z; } return mesh; } private static Vector3f createVector(String[] lineData) { float x = Float.parseFloat(lineData[1]); float y = Float.parseFloat(lineData[2]); float z = Float.parseFloat(lineData[3]); return new Vector3f(x, y, z); } private static Face createFace(String materialName, String[] lineData) { String[] indices1 = lineData[1].split("/"); String[] indices2 = lineData[2].split("/"); String[] indices3 = lineData[3].split("/"); return new Face(materialName, indices1, indices2, indices3); } private static void decodeNormals(Vector3f vertex, Mesh mesh) { int vertexPointer = (int) vertex.x - 1; mesh.indices.add(vertexPointer); Normal normal = mesh.normals.get((int) vertex.z - 1); mesh.normalArray[vertexPointer * 3] = normal.getNormal().x; mesh.normalArray[vertexPointer * 3 + 1] = normal.getNormal().y; mesh.normalArray[vertexPointer * 3 + 2] = normal.getNormal().z; } }
I am getting this NullPointerException
Couldn't get reader for /res/meshes/Crate1.obj java.lang.NullPointerException at java.base/java.io.Reader.<init>(Reader.java:167) at java.base/java.io.InputStreamReader.<init>(InputStreamReader.java:72) at com.darkerminecraft.utils.MyFile.getReader(MyFile.java:59) at com.darkerminecraft.graphics.mesh.MeshLoader.load3DModel(MeshLoader.java:22) at com.darkerminecraft.Game.main(Game.java:10) Couldn't get reader for /res/meshes/.mtl java.lang.NullPointerException at java.base/java.io.Reader.<init>(Reader.java:167) at java.base/java.io.InputStreamReader.<init>(InputStreamReader.java:72) at com.darkerminecraft.utils.MyFile.getReader(MyFile.java:59) at com.darkerminecraft.graphics.mesh.MeshLoader.load3DModel(MeshLoader.java:53) at com.darkerminecraft.Game.main(Game.java:10)
Answer
Class
, or more accurately java.lang.Class
is a system class, which means that Class.class.getResourceAsStream(...)
only looks in the system ClassLoader
for the resource, i.e. it doesn’t use the ClassLoader
that is responsible for the application code and resources.
Change code to MyFile.class.getResourceAsStream(...)
or getClass().getResourceAsStream(...)