0
votes

I am drawing the mesh from the openGl es library in android. When i load light obj file then its load successfully. I mean whose vertex value are less than the 32767. When I load the heavy obj file whose vertex value goes beyond the this value then its fail.

But When I convert it to Long then it stop to draw the mesh. I Could not recognize the where is the error.

How can i solve this issue?

public class MyRenderer extends GLSurfaceView implements Renderer {

    /** Triangle instance */
    private OBJParser parser;
    private TDModel model;

    /* Rotation values */
    private float xrot;                 //X Rotation
    private float yrot;                 //Y Rotation

    /* Rotation speed values */

    private float xspeed;               //X Rotation Speed ( NEW )
    private float yspeed;               //Y Rotation Speed ( NEW )

    private float z = 50.0f;

    private float oldX;
    private float oldY;
    private final float TOUCH_SCALE = 0.4f;     //Proved to be good for normal rotation ( NEW )

    private float[] lightAmbient = {1.0f, 1.0f, 1.0f, 1.0f};
    private float[] lightDiffuse = {1.0f, 1.0f, 1.0f, 1.0f};
    private float[] lightPosition = {0.0f, -3.0f, 2.0f, 1.0f};
    private FloatBuffer lightAmbientBuffer;
    private FloatBuffer lightDiffuseBuffer;
    private FloatBuffer lightPositionBuffer;

    public MyRenderer(Context ctx) {
        super(ctx);

        parser=new OBJParser(ctx);
        model=parser.parseOBJ("/sdcard/door.obj");
        this.setRenderer(this);
        this.requestFocus();
        this.setFocusableInTouchMode(true);

        ByteBuffer byteBuf = ByteBuffer.allocateDirect(lightAmbient.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        lightAmbientBuffer = byteBuf.asFloatBuffer();
        lightAmbientBuffer.put(lightAmbient);
        lightAmbientBuffer.position(0);

        byteBuf = ByteBuffer.allocateDirect(lightDiffuse.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        lightDiffuseBuffer = byteBuf.asFloatBuffer();
        lightDiffuseBuffer.put(lightDiffuse);
        lightDiffuseBuffer.position(0);

        byteBuf = ByteBuffer.allocateDirect(lightPosition.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        lightPositionBuffer = byteBuf.asFloatBuffer();
        lightPositionBuffer.put(lightPosition);
        lightPositionBuffer.position(0);
    }

    /**
     * The Surface is created/init()
     */
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbientBuffer);      
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuseBuffer);      
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPositionBuffer);    
        gl.glEnable(GL10.GL_LIGHT0);

        gl.glEnable(GL10.GL_TEXTURE_2D);
        gl.glShadeModel(GL10.GL_SMOOTH);            
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);    
        gl.glClearDepthf(1.0f);                     
        gl.glEnable(GL10.GL_DEPTH_TEST);            
        gl.glDepthFunc(GL10.GL_LEQUAL);         

        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); 
    }

    /**
     * Here we do our drawing
     */
    public void onDrawFrame(GL10 gl) {
        //Clear Screen And Depth Buffer
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);    
        gl.glLoadIdentity();                    
        gl.glEnable(GL10.GL_LIGHTING);
        gl.glTranslatef(0.0f, -1.2f, -z);   //Move down 1.2 Unit And Into The Screen 6.0
        gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);   //X
        gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f);   //Y
        model.draw(gl);                     //Draw the square
        gl.glLoadIdentity();

        xrot += xspeed;
        yrot += yspeed;

    }

    /**
     * If the surface changes, reset the view
     */
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        if(height == 0) {                       //Prevent A Divide By Zero By
            height = 1;                         //Making Height Equal One
        }

        gl.glViewport(0, 0, width, height);     //Reset The Current Viewport
        gl.glMatrixMode(GL10.GL_PROJECTION);    //Select The Projection Matrix
        gl.glLoadIdentity();                    //Reset The Projection Matrix

        //Calculate The Aspect Ratio Of The Window
        GLU.gluPerspective(gl, 45.0f, 0.1f, 0.1f, 500.0f);

        gl.glMatrixMode(GL10.GL_MODELVIEW);     //Select The Modelview Matrix
        gl.glLoadIdentity();                    //Reset The Modelview Matrix
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //
        float x = event.getX();
        float y = event.getY();

        //If a touch is moved on the screen
        if(event.getAction() == MotionEvent.ACTION_MOVE) {
            //Calculate the change
            float dx = x - oldX;
            float dy = y - oldY;
            //Define an upper area of 10% on the screen
            int upperArea = this.getHeight() / 10;

            //Zoom in/out if the touch move has been made in the upper
            if(y < upperArea) {
                z -= dx * TOUCH_SCALE / 2;

            //Rotate around the axis otherwise
            } else {                
                xrot += dy * TOUCH_SCALE;
                yrot += dx * TOUCH_SCALE;
            }        

        //A press on the screen
        } else if(event.getAction() == MotionEvent.ACTION_UP) {

        }

        //Remember the values
        oldX = x;
        oldY = y;

        //We handled the event
        return true;
    }
    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        //
        if(keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {

        } else if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {

        } else if(keyCode == KeyEvent.KEYCODE_DPAD_UP) {
            z -= 3;

        } else if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
            z += 3;

        } else if(keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {

        }

        //We handled the event
        return true;
    }
}


public class TDModel {
    Vector<Float> v;
    Vector<Float> vn;
    Vector<Float> vt;
    Vector<TDModelPart> parts;
    FloatBuffer vertexBuffer;

    public TDModel(Vector<Float> v, Vector<Float> vn, Vector<Float> vt, Vector<TDModelPart> parts) {
        super();
        this.v = v;
        this.vn = vn;
        this.vt = vt;
        this.parts = parts;
    }

    public String toString(){
        String str=new String();
        str+="Number of parts: "+parts.size();
        str+="\nNumber of vertexes: "+v.size();
        str+="\nNumber of vns: "+vn.size();
        str+="\nNumber of vts: "+vt.size();
        str+="\n/////////////////////////\n";
        for(int i=0; i<parts.size(); i++){
            str+="Part "+i+'\n';
            str+=parts.get(i).toString();
            str+="\n/////////////////////////";
        }
        return str;
    }

    public void draw(GL10 gl) {
        gl.glColor4f(0.0f, 1.0f, 0.0f, 0.5f);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        for(int i=0; i<parts.size(); i++){
            TDModelPart t=parts.get(i);
            gl.glNormalPointer(GL10.GL_FLOAT, 0, t.getNormalBuffer());
            gl.glDrawElements(GL10.GL_TRIANGLES,t.getFacesCount(),GL10.GL_UNSIGNED_SHORT,t.getFaceBuffer());
            gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        }
    }

    public void buildVertexBuffer(){
        ByteBuffer vBuf = ByteBuffer.allocateDirect(v.size() * 4);
        vBuf.order(ByteOrder.nativeOrder());
        vertexBuffer = vBuf.asFloatBuffer();
        vertexBuffer.put(toPrimitiveArrayF(v));
        vertexBuffer.position(0);
    }

    private static float[] toPrimitiveArrayF(Vector<Float> vector){
        float[] f;
        f=new float[vector.size()];
        for (int i=0; i<vector.size(); i++){
            f[i]=vector.get(i);
        }
        return f;
    }
}


public class OBJParser {
    int numVertices=0;
    int numFaces=0;
    Context context;

    Vector<Short> faces=new Vector<Short>();
    Vector<Short> vtPointer=new Vector<Short>();
    Vector<Short> vnPointer=new Vector<Short>();
    Vector<Float> v=new Vector<Float>();
    Vector<Float> vn=new Vector<Float>();
    Vector<Float> vt=new Vector<Float>();
    Vector<TDModelPart> parts=new Vector<TDModelPart>();
    Vector<Material> materials=null;

    public OBJParser(Context ctx){
        context=ctx;
    }

    public TDModel parseOBJ(String fileName) {
        BufferedReader reader=null;
        String line = null;
        Material m=null;

        try { //try to open file
            reader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
        }       catch(IOException e){
        }
        try {//try to read lines of the file
            while((line = reader.readLine()) != null) {
                Log.v("obj",line);
                if(line.startsWith("f")){//a polygonal face
                    processFLine(line);
                }
                else
                    if(line.startsWith("vn")){
                        processVNLine(line);
                    }
                    else
                        if(line.startsWith("vt")){
                            processVTLine(line);
                        }
                        else
                            if(line.startsWith("v")){ //line having geometric position of single vertex
                                processVLine(line);
                            }
                            /*else
                                if(line.startsWith("usemtl")){
                                    try{//start of new group
                                    if(faces.size()!=0){//if not this is not the start of the first group
                                        TDModelPart model=new TDModelPart(faces, vtPointer, vnPointer, m,vn);
                                        parts.add(model);
                                    }
                                    String mtlName=line.split("[ ]+",2)[1]; //get the name of the material
                                    for(int i=0; i<materials.size(); i++){//suppose .mtl file already parsed
                                        m=materials.get(i);
                                        if(m.getName().equals(mtlName)){//if found, return from loop
                                            break;
                                        }
                                        m=null;//if material not found, set to null
                                    }
                                    faces=new Vector<Short>();
                                    vtPointer=new Vector<Short>();
                                    vnPointer=new Vector<Short>();
                                    }
                                    catch (Exception e) {
                                        // TODO: handle exception
                                    }
                                }
                                else
                                    if(line.startsWith("mtllib")){
                                        materials=MTLParser.loadMTL(line.split("[ ]+")[1]);
                                        for(int i=0; i<materials.size(); i++){
                                            Material mat=materials.get(i);
                                            Log.v("materials",mat.toString());
                                        }
                                    }*/
            }
        }       
        catch(IOException e){
            System.out.println("wtf...");
        }
        if(faces!= null){//if not this is not the start of the first group
            TDModelPart model=new TDModelPart(faces, vtPointer, vnPointer, m,vn);
            parts.add(model);
        }
        TDModel t=new TDModel(v,vn,vt,parts);
        t.buildVertexBuffer();
        Log.v("models",t.toString());
        return t;
    }


    private void processVLine(String line){
        String [] tokens=line.split("[ ]+"); //split the line at the spaces
        int c=tokens.length; 
        for(int i=1; i<c; i++){ //add the vertex to the vertex array
            v.add(Float.valueOf(tokens[i]));
        }
    }
    private void processVNLine(String line){
        String [] tokens=line.split("[ ]+"); //split the line at the spaces
        int c=tokens.length; 
        for(int i=1; i<c; i++){ //add the vertex to the vertex array
            vn.add(Float.valueOf(tokens[i]));
        }
    }
    private void processVTLine(String line){
        String [] tokens=line.split("[ ]+"); //split the line at the spaces
        int c=tokens.length; 
        for(int i=1; i<c; i++){ //add the vertex to the vertex array
            vt.add(Float.valueOf(tokens[i]));
        }
    }
    private void processFLine(String line){
        String [] tokens=line.split("[ ]+");
        int c=tokens.length;

        if(tokens[1].matches("[0-9]+")){//f: v
            if(c==4){//3 faces
                for(int i=1; i<c; i++){
                    Short s=Short.valueOf(tokens[i]);
                    s--;
                    faces.add(s);
                }
            }
            else{//more faces
                Vector<Short> polygon=new Vector<Short>();
                for(int i=1; i<tokens.length; i++){
                    Short s=Short.valueOf(tokens[i]);
                    s--;
                    polygon.add(s);
                }
                faces.addAll(Triangulator.triangulate(polygon));//triangulate the polygon and add the resulting faces
            }
        }
        if(tokens[1].matches("[0-9]+/[0-9]+")){//if: v/vt
            if(c==4){//3 faces
                for(int i=1; i<c; i++){
                    Short s=Short.valueOf(tokens[i].split("/")[0]);
                    s--;
                    faces.add(s);
                    s=Short.valueOf(tokens[i].split("/")[1]);
                    s--;
                    vtPointer.add(s);
                }
            }
            else{//triangulate
                Vector<Short> tmpFaces=new Vector<Short>();
                Vector<Short> tmpVt=new Vector<Short>();
                for(int i=1; i<tokens.length; i++){
                    Short s=Short.valueOf(tokens[i].split("/")[0]);
                    s--;
                    tmpFaces.add(s);
                    s=Short.valueOf(tokens[i].split("/")[1]);
                    s--;
                    tmpVt.add(s);
                }
                faces.addAll(Triangulator.triangulate(tmpFaces));
                vtPointer.addAll(Triangulator.triangulate(tmpVt));
            }
        }
        if(tokens[1].matches("[0-9]+//[0-9]+")){//f: v//vn
            if(c==4){//3 faces
                for(int i=1; i<c; i++){
                    Short s=Short.valueOf(tokens[i].split("//")[0]);
                    s--;
                    faces.add(s);
                    s=Short.valueOf(tokens[i].split("//")[1]);
                    s--;
                    vnPointer.add(s);
                }
            }
            else{//triangulate
                Vector<Short> tmpFaces=new Vector<Short>();
                Vector<Short> tmpVn=new Vector<Short>();
                for(int i=1; i<tokens.length; i++){
                    Short s=Short.valueOf(tokens[i].split("//")[0]);
                    s--;
                    tmpFaces.add(s);
                    s=Short.valueOf(tokens[i].split("//")[1]);
                    s--;
                    tmpVn.add(s);
                }
                faces.addAll(Triangulator.triangulate(tmpFaces));
                vnPointer.addAll(Triangulator.triangulate(tmpVn));
            }
        }
        if(tokens[1].matches("[0-9]+/[0-9]+/[0-9]+")){//f: v/vt/vn

            if(c==4){//3 faces
                for(int i=1; i<c; i++){
                    Short s=Short.valueOf(tokens[i].split("/")[0]);
                    s--;
                    faces.add(s);
                    s=Short.valueOf(tokens[i].split("/")[1]);
                    s--;
                    vtPointer.add(s);
                    s=Short.valueOf(tokens[i].split("/")[2]);
                    s--;
                    vnPointer.add(s);
                }
            }
            else{//triangulate
                Vector<Short> tmpFaces=new Vector<Short>();
                Vector<Short> tmpVn=new Vector<Short>();
                //Vector<Short> tmpVt=new Vector<Short>();
                for(int i=1; i<tokens.length; i++){
                    Short s=Short.valueOf(tokens[i].split("/")[0]);
                    s--;
                    tmpFaces.add(s);
                    //s=Short.valueOf(tokens[i].split("/")[1]);
                    //s--;
                    //tmpVt.add(s);
                    //s=Short.valueOf(tokens[i].split("/")[2]);
                    //s--;
                    //tmpVn.add(s);
                }
                faces.addAll(Triangulator.triangulate(tmpFaces));
                vtPointer.addAll(Triangulator.triangulate(tmpVn));
                vnPointer.addAll(Triangulator.triangulate(tmpVn));
            }
        }
    }

}

07-12 18:23:45.519: E/AndroidRuntime(6037): FATAL EXCEPTION: main
07-12 18:23:45.519: E/AndroidRuntime(6037): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.opengldemo/com.example.opengldemo.MainActivity}: java.lang.NumberFormatException: Value out of range for short: "32776"
07-12 18:23:45.519: E/AndroidRuntime(6037):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1970)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1995)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at android.app.ActivityThread.access$600(ActivityThread.java:128)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1161)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at android.os.Looper.loop(Looper.java:137)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at android.app.ActivityThread.main(ActivityThread.java:4514)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at java.lang.reflect.Method.invokeNative(Native Method)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at java.lang.reflect.Method.invoke(Method.java:511)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at dalvik.system.NativeStart.main(Native Method)
07-12 18:23:45.519: E/AndroidRuntime(6037): Caused by: java.lang.NumberFormatException: Value out of range for short: "32776"
07-12 18:23:45.519: E/AndroidRuntime(6037):     at java.lang.Short.parseShort(Short.java:218)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at java.lang.Short.parseShort(Short.java:194)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at java.lang.Short.valueOf(Short.java:260)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at com.example.opengldemo.OBJParser.processFLine(OBJParser.java:152)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at com.example.opengldemo.OBJParser.parseOBJ(OBJParser.java:45)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at com.example.opengldemo.MyRenderer.<init>(MyRenderer.java:50)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at com.example.opengldemo.MainActivity.onCreate(MainActivity.java:11)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at android.app.Activity.performCreate(Activity.java:4465)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1053)
07-12 18:23:45.519: E/AndroidRuntime(6037):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1934)
07-12 18:23:45.519: E/AndroidRuntime(6037):     ... 11 more
1

1 Answers

0
votes

In your processFLine method you use Short for storing vertices, normals and other attributes. But short can store only 32767 as max value. So if you use model that contains more than 32768 vertices or normal or textcoords you get such error. Change it to Integer.

Here is how I load a mesh:

public class Mesh {

private Context context;

private final int mBytesPerFloat = 4;

public int vertexCount;
FloatBuffer mPositions;
FloatBuffer mNormals;
FloatBuffer mTextureCoordinates;

private float[] mModelMatrix = new float[16];

int mTextureDataHandle;

/**
 * 
 * @param context
 * @param path
 */
public Mesh(Context context, String path, float scale) {
    this.context = context;

    InputStream is = null;
    BufferedReader br = null;

    int vCount = 0; // vertices count
    int vnCount = 0; // normals count
    int vtCount = 0; // texture coordinates count
    int fCount = 0; // faces count

    try {
        is = context.getAssets().open(path);
        br = new BufferedReader(new InputStreamReader(is));
        String l;

        /**
         * First pass: collect information
         */
        Log.d("ALEKSO", "Collecting model info..");
        while ((l = br.readLine()) != null) {
            l.trim();
            if (l.startsWith("v "))
                vCount++;
            if (l.startsWith("vn "))
                vnCount++;
            if (l.startsWith("vt "))
                vtCount++;
            if (l.startsWith("f "))
                fCount++;
        }

        Log.d("ALEKSO", "vertices: " + vCount);
        Log.d("ALEKSO", "vertex normals: " + vnCount);
        Log.d("ALEKSO", "texture coords: " + vtCount);
        Log.d("ALEKSO", "faces: " + fCount);

        br.close();
        is.close();

        /**
         * Second pass: retrieve data
         */

        // initialize arrays for data
        float vertices[] = new float[vCount * 3];
        float normals[] = new float[vnCount * 3];
        float texcoords[] = new float[vtCount * 2];

        int facesVertices[] = new int[fCount * 3];
        int facesNormals[] = new int[fCount * 3];
        int facesTexCoords[] = new int[fCount * 3];

        int vertexIdx = 0;
        int normalIdx = 0;
        int texcoordIdx = 0;
        int faceIdx = 0;

        // read file again
        is = context.getAssets().open(path);
        br = new BufferedReader(new InputStreamReader(is));
        while ((l = br.readLine()) != null) {
            l.trim();
            if (l.startsWith("v ")) {
                String arr[] = l.substring(2).split(" ");
                vertices[vertexIdx++] = Float.parseFloat(arr[0]);
                vertices[vertexIdx++] = Float.parseFloat(arr[1]);
                vertices[vertexIdx++] = Float.parseFloat(arr[2]);
                continue;
            }

            if (l.startsWith("vn ")) {
                String arr[] = l.substring(3).split(" ");
                normals[normalIdx++] = Float.parseFloat(arr[0]);
                normals[normalIdx++] = Float.parseFloat(arr[1]);
                normals[normalIdx++] = Float.parseFloat(arr[2]);
                continue;
            }

            if (l.startsWith("vt ")) {
                String arr[] = l.substring(3).split(" ");
                texcoords[texcoordIdx++] = Float.parseFloat(arr[0]);
                texcoords[texcoordIdx++] = Float.parseFloat(arr[1]);
                continue;
            }

            if (l.startsWith("f ")) {
                String arr[] = l.substring(2).trim().split(" ");

                String parts[] = arr[0].split("/");
                facesVertices[faceIdx] = Integer.parseInt(parts[0]) - 1;
                facesTexCoords[faceIdx] = Integer.parseInt(parts[1]) - 1;
                facesNormals[faceIdx] = Integer.parseInt(parts[2]) - 1;
                faceIdx++;

                parts = arr[1].split("/");
                facesVertices[faceIdx] = Integer.parseInt(parts[0]) - 1;
                facesTexCoords[faceIdx] = Integer.parseInt(parts[1]) - 1;
                facesNormals[faceIdx] = Integer.parseInt(parts[2]) - 1;
                faceIdx++;

                parts = arr[2].split("/");
                facesVertices[faceIdx] = Integer.parseInt(parts[0]) - 1;
                facesTexCoords[faceIdx] = Integer.parseInt(parts[1]) - 1;
                facesNormals[faceIdx] = Integer.parseInt(parts[2]) - 1;
                faceIdx++;
                continue;
            }
        }

        float meshVertices[] = new float[facesVertices.length * 3];
        float meshNormals[] = new float[facesNormals.length * 3];
        float meshTexCoords[] = new float[facesTexCoords.length * 2];

        int nid = 0, tid = 0, vid = 0;
        for (int i = 0; i < fCount * 3; i++) {
            if (vnCount > 0) {
                int nIdx = facesNormals[i] * 3;
                meshNormals[nid++] = normals[nIdx] * scale;
                meshNormals[nid++] = normals[nIdx + 1] * scale;
                meshNormals[nid++] = normals[nIdx + 2] * scale;
            }
            if (vtCount > 0) {
                int uvIdx = facesTexCoords[i] * 2;
                meshTexCoords[tid++] = texcoords[uvIdx];
                meshTexCoords[tid++] = texcoords[uvIdx + 1];
            }

            int vIdx = facesVertices[i] * 3;
            meshVertices[vid++] = vertices[vIdx] * scale;
            meshVertices[vid++] = vertices[vIdx + 1] * scale;
            meshVertices[vid++] = vertices[vIdx + 2] * scale;
        }

        vertexCount = fCount * 3;

        // Initialize the buffers.
        mPositions = ByteBuffer.allocateDirect(meshVertices.length * mBytesPerFloat).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mPositions.put(meshVertices).position(0);

        mNormals = ByteBuffer.allocateDirect(meshNormals.length * mBytesPerFloat).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mNormals.put(meshNormals).position(0);

        mTextureCoordinates = ByteBuffer.allocateDirect(meshTexCoords.length * mBytesPerFloat).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mTextureCoordinates.put(meshTexCoords).position(0);

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (br != null)
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        if (is != null)
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }
}

/**
 * 
 * @param textureRes
 */
public void loadTexture(final int textureRes) {
    mTextureDataHandle = Utils.loadTexture(this.context, textureRes);
    GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
}

}