By jayaprakashs
on Wed, 08/05/2015 - 07:13
I imported sample vuforia project successfully by referring http://developer.vuforia.com/library/articles/Solution/Compiling-and-Running-a-Vuforia-Android-Sample-App and it is working fine without any issue. I planned to change the default model(Teapot) to different 3D model. So i have implemented my own parser for loading .obj file. Now after parsed, Small 3d models like cube.obj is loading fine. But this is not working on big object model. I am facing "Vuforia stopped unexpectedly" exception while rendering. Here is my parsing code.
public class OBJToolkit { static ArrayList<Vector3f> VBOVertices = new ArrayList<Vector3f>(); static ArrayList<Vector2f> VBOTextureCoords = new ArrayList<Vector2f>(); static ArrayList<Vector3f> VBONormals = new ArrayList<Vector3f>(); static ArrayList<Integer> VBOIndices = new ArrayList<Integer>(); int counter = 0; private ArrayList<String> parseOBJ(AssetManager assetManager, String filename) throws IOException { InputStream is = null; ArrayList<String> lines = new ArrayList<String>(); try { is = assetManager.open(filename); BufferedReader reader = new BufferedReader( new InputStreamReader(is)); while (reader.ready()) { lines.add(reader.readLine().replace(" ", " ")); } reader.close(); reader = null; } catch (Exception e) { e.printStackTrace(); } return lines; } public void loadOBJ(AssetManager assetManager, String filename) throws FileNotFoundException, IOException { Log.d("OBJToolkit", "Location searched for model: " + filename); ArrayList<Vector3f> allVertices = new ArrayList<Vector3f>(); ArrayList<Vector2f> allTextureCoords = new ArrayList<Vector2f>(); ArrayList<Vector3f> allNormals = new ArrayList<Vector3f>(); ArrayList<Face> faces = new ArrayList<Face>(); ArrayList<String> lines = parseOBJ(assetManager, filename); for (String line : lines) { if (line == null) break; if (line.startsWith("v ")) { allVertices.add(new Vector3f(Float.valueOf(line.split(" ")[1]), Float.valueOf(line.split(" ")[2]), Float.valueOf(line.split(" ")[3]))); } if (line.startsWith("vt ")) { allTextureCoords.add(new Vector2f(Float.valueOf(line.split(" ")[1]), Float.valueOf(line.split(" ")[2]))); } if (line.startsWith("vn ")) { allNormals.add(new Vector3f(Float.valueOf(line.split(" ")[1]), Float.valueOf(line.split(" ")[2]), Float.valueOf(line.split(" ")[3]))); } //f 1/4/2 7/1/2 5/2/2 if (line.startsWith("f ")) { //Log.d("OBJToolkit", line); Face f = new Face(); String[] faceVertexArray = line.split(" "); for (int index = 1; index < faceVertexArray.length; index++) { String[] valueArray = faceVertexArray[index].split("/"); if (allTextureCoords.size() > 0) f.addVertex(new Vertex(allVertices.get(Integer.valueOf(valueArray[0]) - 1), allNormals.get(Integer.valueOf(valueArray[2]) - 1), allTextureCoords.get(Integer.valueOf(valueArray[1]) - 1))); else f.addVertex(new Vertex(allVertices.get(Integer.valueOf(valueArray[0]) - 1), allNormals.get(Integer.valueOf(valueArray[2]) - 1), new Vector2f(0, 0))); } faces.add(f); } } lines = null; allVertices = null; allNormals = null; allTextureCoords = null; for (Face f : faces) { for (Vertex v : f.vertices) { VBOVertices.add(v.position); VBONormals.add(v.normal); VBOTextureCoords.add(v.textureCoord); VBOIndices.add(counter); counter++; } } faces = null; } public double[] getVertices() { return vector3fListToFloatArray(VBOVertices); } public double[] getNormals() { return vector3fListToFloatArray(VBONormals); } public double[] getTextures() { return vector2fListToFloatArray(VBOTextureCoords); } public short[] getIndices() { return integerListToShortArray(VBOIndices); } public Buffer getIndicesBuffer() { return fillBuffer(getIndices()); } public Buffer getVerticesBuffer() { return fillBuffer(getVertices()); } public Buffer getNormalsBuffer() { return fillBuffer(getNormals()); } public Buffer getTexturesBuffer() { return fillBuffer(getTextures()); } public int getVerticesCount() { return VBOVertices.size();// (int) getVertices().length / 3; } public int getIndicesCount() { return counter; } public static void printFloatArrayList(ArrayList<Float> list) { String strToPrint = ""; for (float value : list) { strToPrint += (value + ", "); } } public static String floatArrayToString(ArrayList<Float> list) { String strToPrint = ""; for (float value : list) { strToPrint += (value + ", "); } return strToPrint; } public static String vector3fArrayToString(ArrayList<Vector3f> list) { String strToPrint = ""; for (Vector3f v : list) { strToPrint += v.x + ", "; strToPrint += v.y + ", "; strToPrint += v.z + ", "; } return strToPrint; } public static void printStringArray(String[] list) { String strToPrint = ""; for (String s : list) { strToPrint += s + ","; } } public static void printIntegerArrayList(ArrayList<Integer> list) { String strToPrint = ""; for (float value : list) { strToPrint += (value + ", "); } } public static double[] vector3fListToFloatArray(ArrayList<Vector3f> list) { double[] returnArray = new double[list.size() * 3]; int counter = 0; for (Vector3f v : list) { returnArray[counter] = v.x; counter++; returnArray[counter] = v.y; counter++; returnArray[counter] = v.z; counter++; } return returnArray; } public static double[] vector2fListToFloatArray(ArrayList<Vector2f> list) { double[] returnArray = new double[list.size() * 2]; int counter = 0; for (Vector2f v : list) { returnArray[counter] = v.x; counter++; returnArray[counter] = v.y; counter++; } return returnArray; } protected Buffer fillBuffer(double[] array) { // Convert to floats because OpenGL doesn't work on doubles, and manually // casting each input value would take too much time. // Each float takes 4 bytes ByteBuffer bb = ByteBuffer.allocateDirect(4 * array.length); bb.order(ByteOrder.LITTLE_ENDIAN); for (double d : array) bb.putFloat((float) d); bb.rewind(); return bb; } protected Buffer fillBuffer(short[] array) { ByteBuffer bb = ByteBuffer.allocateDirect(2 * array.length); bb.order(ByteOrder.LITTLE_ENDIAN); for (short s : array) bb.putShort(s); bb.rewind(); return bb; } }And my rendering part is,
private void renderFrame() { GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); State state = mRenderer.begin(); mRenderer.drawVideoBackground(); GLES20.glEnable(GLES20.GL_DEPTH_TEST); // handle face culling, we need to detect if we are using reflection // to determine the direction of the culling GLES20.glEnable(GLES20.GL_CULL_FACE); GLES20.glCullFace(GLES20.GL_BACK); if (Renderer.getInstance().getVideoBackgroundConfig().getReflection() == VIDEO_BACKGROUND_REFLECTION.VIDEO_BACKGROUND_REFLECTION_ON) GLES20.glFrontFace(GLES20.GL_CW); // Front camera else GLES20.glFrontFace(GLES20.GL_CCW); // Back camera // did we find any trackables this frame? for (int tIdx = 0; tIdx < state.getNumTrackableResults(); tIdx++) { TrackableResult result = state.getTrackableResult(tIdx); Trackable trackable = result.getTrackable(); printUserData(trackable); Matrix44F modelViewMatrix_Vuforia = Tool .convertPose2GLMatrix(result.getPose()); float[] modelViewMatrix = modelViewMatrix_Vuforia.getData(); int textureIndex = trackable.getName().equalsIgnoreCase("stones") ? 0 : 1; textureIndex = trackable.getName().equalsIgnoreCase("tarmac") ? 2 : textureIndex; // deal with the modelview and projection matrices float[] modelViewProjection = new float[16]; if (!mActivity.isExtendedTrackingActive()) { Matrix.translateM(modelViewMatrix, 0, 0.0f, 0.0f, OBJECT_SCALE_FLOAT); Matrix.scaleM(modelViewMatrix, 0, OBJECT_SCALE_FLOAT, OBJECT_SCALE_FLOAT, OBJECT_SCALE_FLOAT); } else { Matrix.rotateM(modelViewMatrix, 0, 90.0f, 1.0f, 0, 0); Matrix.scaleM(modelViewMatrix, 0, kBuildingScale, kBuildingScale, kBuildingScale); } Matrix.multiplyMM(modelViewProjection, 0, vuforiaAppSession .getProjectionMatrix().getData(), 0, modelViewMatrix, 0); // activate the shader program and bind the vertex/normal/tex coords GLES20.glUseProgram(shaderProgramID); GLES20.glVertexAttribPointer(vertexHandle, 3, GLES20.GL_FLOAT, false, 0, myObjParser.getVerticesBuffer()); GLES20.glVertexAttribPointer(normalHandle, 3, GLES20.GL_FLOAT, false, 0, myObjParser.getNormalsBuffer()); GLES20.glVertexAttribPointer(textureCoordHandle, 2, GLES20.GL_FLOAT, false, 0, myObjParser.getTexturesBuffer()); GLES20.glEnableVertexAttribArray(vertexHandle); GLES20.glEnableVertexAttribArray(normalHandle); GLES20.glEnableVertexAttribArray(textureCoordHandle); // activate texture 0, bind it, and pass to shader GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures.get(textureIndex).mTextureID[0]); GLES20.glUniform1i(texSampler2DHandle, 0); // pass the model view matrix to the shader GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, modelViewProjection, 0); // // finally draw the teapot GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, myObjParser.getVerticesCount()); // disable the enabled arrays GLES20.glDisableVertexAttribArray(vertexHandle); GLES20.glDisableVertexAttribArray(normalHandle); GLES20.glDisableVertexAttribArray(textureCoordHandle); SampleUtils.checkGLError("Render Frame"); } GLES20.glDisable(GLES20.GL_DEPTH_TEST); mRenderer.end(); }Can anyone tell me, where i have done mistake?