0

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
4

1 に答える 1