在opengl中绘制网格

时间:2013-07-12 13:01:03

标签: android opengl-es

我正在从android中的openGl es库中绘制网格物体。当我加载光obj文件然后成功加载。我的意思是它的顶点值小于32767.当我加载顶点值超出此值的重的obj文件时,它的失败。

但是当我将它转换为Long时,它会停止绘制网格。我无法识别出错误在哪里。

我该如何解决这个问题?

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 个答案:

答案 0 :(得分:0)

在processFLine方法中,使用Short来存储顶点,法线和其他属性。 但是short只能存储32767作为最大值。因此,如果您使用包含超过32768个顶点或普通或文本条的模型,则会出现此类错误。将其更改为整数。

以下是我加载网格的方法:

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);
}

}