Zoom functionality, resetting of SurfaceView & Progress

Started by r0xx, September 16, 2013, 10:50:47 AM

Previous topic - Next topic

r0xx

Hello Community

I'm pretty new to jPCT-AE but I gotta say, I love it's simplicity.
I have a few questions. I am writing a 3d model viewer for Android to open some files. I have used the sample provided here: http://www.jpct.net/wiki/index.php/Hello_World_for_Android

Now I want to add zoom functionality to this example, but don't really know how. So this would be my first question: How can I add zoom functionality to my scene?

My next problem is the following. I am opening my model. Sometimes they are kind of big. How can I add a Progressbar or get some information from jPCT from which I can create a ProgressDialog and show how many percent have already been loaded of the model?

And my last question is: How can I reset my SurfaceView after I load another model? If I want to load a new Model now, it just shows me my old model.

Here is some of my code (If you need more let me know...):

This is the fragment where I load the model into the SurfaceView:

public static class ViewModelFragment extends Fragment {

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup
                container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.main,
                    container, false);

            if (master != null) {
                copy(master);
            }

            super.onCreate(savedInstanceState);
            startTime = System.currentTimeMillis();
            mGLView = (ClearGLSurfaceView) rootView.findViewById(R.id.mySurfaceView);

            mGLView.setEGLConfigChooser(new GLSurfaceView.EGLConfigChooser() {
                public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
                    int[] attributes = new int[] {
                            EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE
                    };
                    EGLConfig[] configs = new EGLConfig[1];
                    int[] result = new int[1];
                    egl.eglChooseConfig(display, attributes, configs, 1, result);
                    return configs[0];
                }
            });
            mGLView.setEGLContextClientVersion(2);
            mGLView.setEGLConfigChooser(new AAConfigChooser(mGLView));

            renderer = new MyRenderer(myContext);
            mGLView.setRenderer(renderer);

            endTime = System.currentTimeMillis();
            Log.e("My App", "used time to load model: " + (endTime - startTime) / 1000 + " s ("
                    + (endTime - startTime) + " ms)");

            return rootView;
        }

        private void copy(Object src) {
            try {
                Logger.log("Copying data from master Activity!");
                Field[] fs = src.getClass().getDeclaredFields();
                for (Field f : fs) {
                    f.setAccessible(true);
                    f.set(this, f.get(src));
                }
            } catch (Exception e) {
                // throw new RuntimeException(e);
            }
        }

        protected boolean isFullscreenOpaque() {
            return true;
        }

        static class MyRenderer implements GLSurfaceView.Renderer {

            private long fpsTime = System.currentTimeMillis();
            Resources res = myContext.getResources();
            Context thecontext;

            private int fps, lfps;

            public MyRenderer(Context context) {
                thecontext = context;
            }

            public void onSurfaceChanged(GL10 gl, int w, int h) {
                if (fb != null) {
                    fb.dispose();
                }
                fb = new FrameBuffer(w, h);

                screenWidth = w;
                screenHeight = h;

                if (master == null) {

                    world = new World();
                    world.setAmbientLight(30, 30, 30);

                    sun = new Light(world);
                    sun.setIntensity(250, 250, 250);

                    try {
                        cube = loadModel(thingName, thingScale);
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }

                    cube.build();

                    world.addObject(cube);

                    Camera cam = world.getCamera();
                    cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
                    cam.lookAt(cube.getTransformedCenter());

                    SimpleVector sv = new SimpleVector();
                    sv.set(cube.getTransformedCenter());
                    sv.y -= 100;
                    sv.z -= 100;
                    sun.setPosition(sv);
                    MemoryHelper.compact();

                    if (master == null) {
                        Logger.log("Saving master Activity!");
                        master = (MainActivity) thecontext;
                    }
                }
            }

            public void onSurfaceCreated(GL10 gl, EGLConfig config) {
                paint = new Paint();
                paint.setAntiAlias(true);
                paint.setTypeface(Typeface.create((String) null, Typeface.BOLD));

                paint.setTextSize(30);
                glFont = new AGLFont(paint);

                paint2 = new Paint();
                paint2.setAntiAlias(true);
                Typeface typeface = Typeface.createFromAsset(myContext.getAssets(), "comp.ttf");
                paint2.setTypeface(typeface);

                paint2.setTextSize(70);
                glFont2 = new AGLFont(paint2);
            }

            public void onDrawFrame(GL10 gl) {
                if (touchTurn != 0) {
                    cube.rotateY(touchTurn);
                    touchTurn = 0;
                }

                if (touchTurnUp != 0) {
                    cube.rotateX(touchTurnUp);
                    touchTurnUp = 0;
                }

                fb.clear(back);
                world.renderScene(fb);
                world.draw(fb);

                String fpsStr = lfps + " fps";
                glFont.blitString(fb, fpsStr,
                        screenWidth - fpsStr.length() * 15, 35, 10, RGBColor.WHITE);

                glFont2.blitString(fb, "comp",
                        20, screenHeight - 45, 10, RGBColor.WHITE);
                fb.display();

                if (System.currentTimeMillis() - fpsTime >= 1000) {
                    lfps = (fps + lfps) >> 1;
                    fps = 0;
                    fpsTime = System.currentTimeMillis();
                }
                fps++;
            }

            private Object3D loadModel(String filename, float scale) throws UnsupportedEncodingException {

                InputStream stream = null;
                InputStream stream2 = null;
                Object3D[] model = null;
                if (filename.toLowerCase().endsWith(".obj")) {
                    try {
                        File f_path = new File(filename);
                        stream = new BufferedInputStream(new FileInputStream(f_path));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    try {
                        File f_path2 = new File(filename + ".mtl");
                        stream2 = new BufferedInputStream(new FileInputStream(f_path2));
                    } catch (FileNotFoundException fnfe) {
                        Log.w("My App", "Texture not found...");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    try {
                        model = Loader.loadOBJ(stream, stream2, scale);
                    } catch (RuntimeException re) {
                        Log.e("My App", "Model has problems...");
                    }
                } else if (filename.toLowerCase().endsWith(".3ds")) {
                    try {
                        File f_path = new File(filename);
                        stream = new BufferedInputStream(new FileInputStream(f_path));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    try {
                        model = Loader.load3DS(stream, scale);
                    } catch (RuntimeException re) {
                        Log.e("My App", "Model has problems...");
                    }
                }
                Object3D o3d = new Object3D(0);
                Object3D temp = null;
                for (int i = 0; i < model.length; i++) {
                    temp = model[i];
                    temp.setCenter(SimpleVector.ORIGIN);
                    temp.rotateX((float) (-.5 * Math.PI));
                    temp.rotateMesh();
                    temp.setRotationMatrix(new Matrix());
                    temp.compile(true, true);
                    o3d = Object3D.mergeObjects(o3d, temp);
                    o3d.build();
                }
                return o3d;
            }

        }
    }



This is my SurfaceView at the moment (Where I want to add zoom):

public static class ClearGLSurfaceView extends GLSurfaceView {
        public ClearGLSurfaceView(Context context) {
            super(context);
        }

        public ClearGLSurfaceView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        @Override
        public boolean onTouchEvent(MotionEvent me) {

            if (me.getAction() == MotionEvent.ACTION_DOWN) {
                xpos = me.getX();
                ypos = me.getY();
                return true;
            }

            if (me.getAction() == MotionEvent.ACTION_UP) {
                xpos = -1;
                ypos = -1;
                touchTurn = 0;
                touchTurnUp = 0;
                return true;
            }

            if (me.getAction() == MotionEvent.ACTION_MOVE) {
                float xd = me.getX() - xpos;
                float yd = me.getY() - ypos;

                xpos = me.getX();
                ypos = me.getY();

                touchTurn = xd / 100f;
                touchTurnUp = yd / 100f;
                return true;
            }

            try {
                Thread.sleep(15);
            } catch (Exception e) {
                // Doesn't matter here...
            }

            return super.onTouchEvent(me);
        }
    }


Thank you already for help.

EgonOlsen

Quote from: r0xx on September 16, 2013, 10:50:47 AM
Now I want to add zoom functionality to this example, but don't really know how. So this would be my first question: How can I add zoom functionality to my scene?
The best way to do this is to change the camera's fov.

Quote from: r0xx on September 16, 2013, 10:50:47 AM
My next problem is the following. I am opening my model. Sometimes they are kind of big. How can I add a Progressbar or get some information from jPCT from which I can create a ProgressDialog and show how many percent have already been loaded of the model?
You can't. I suggest to use the solution that javascript frameworks do: Show a spinning "wheel" or some fake progress bar that loops.

Quote from: r0xx on September 16, 2013, 10:50:47 AM
And my last question is: How can I reset my SurfaceView after I load another model? If I want to load a new Model now, it just shows me my old model.
Remove and dispose the old model, load the new one!? I don't get why it should still show the old one.... ???

r0xx

Thanks alot for your help.

So there is not any example which shows how to add zoom to the world? I don't really know how to
Where would I add this code inside my onTouchView() method?


So is there any kind of Event which shows when the model is completely loaded? Or how would I set the end of the progress?

Ok thanks. Where do I need to dispose and remove my world? Inside onSurfaceChanged?

EgonOlsen

Quote
So there is not any example which shows how to add zoom to the world? I don't really know how to
Where would I add this code inside my onTouchView() method?
No, because jPCT-AE isn't thread-safe (http://www.jpct.net/wiki/index.php/Thread_safety). You must place all the code that interferes with the rendering inside the rendering thread (i.e. inside onDrawFrame) or synchronize rendering and your code by yourself. Fiddling around with the camera in onTouchEvent while the renderer uses it to render the scene will cause all kinds of visual glitches.
            
Quote
So is there any kind of Event which shows when the model is completely loaded? Or how would I set the end of the progress?
??? The loading ends when the method returns. It's synchronous.
Quote
Where do I need to dispose and remove my world? Inside onSurfaceChanged?
That depends on your app and what it's supposed to do. Just make sure (as mentioned above) that it doesn't interfere with the rendering, because removing stuff that is currently being rendered isn't a smart idea. onDrawFrame() is usually a good place to place such code if it should happen at runtime.