Java – how libgdx scales and rotates 3D models when touched

I'm trying to create a simple application that allows you to start from Obj loads the 3D model and scales / rotates it by touching the screen

I managed to write code to load 3D models from files and detect gestures, but now I don't know how to enable zoom / rotation by touching the screen

This is my current code:

public class RenderObjApp implements ApplicationListener,GestureDetector.GestureListener {
    public static int SCREEN_WIDTH = 800;
    public static int SCREEN_HEIGHT = 600;

    private static final String TAG = RenderObjApp.class.getSimpleName();

    private Mesh model;
    private PerspectiveCamera camera;

    private float scale = 1f;

    @Override
    public void create() {
        model = ObjLoader.loadObj(Gdx.files.internal("data/cessna.obj").read(),true);
        Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);
        Gdx.input.setInputProcessor(new GestureDetector(this));
    }

    @Override
    public void dispose() {
    }

    @Override
    public void pause() {
    }


    @Override
    public void render() {
        Gdx.gl.glClearColor(0.0f,0.0f,1.0f);
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        camera.update();
        camera.apply(Gdx.gl10);
        model.render(GL10.GL_TRIANGLES);
    }

    @Override
    public void resize(int arg0,int arg1) {
        float aspectRatio = (float) arg0 / (float) arg1;
        camera = new PerspectiveCamera(75,2f * aspectRatio,2f);
        camera.near = 0.1f;
        camera.translate(0,0);
    }

    @Override
    public void resume() {
    }

    @Override
    public boolean touchDown(float x,float y,int pointer) {
        Gdx.app.log(TAG,"touchDown: ");
        return false;
    }

    @Override
    public boolean tap(float x,int count,int pointer,int button) {
        Gdx.app.log(TAG,"tap: ");   
        return false;
    }

    @Override
    public boolean longPress(float x,float y) {
        Gdx.app.log(TAG,"zoom: ");
        return false;
    }

    @Override
    public boolean fling(float veLocityX,float veLocityY,"fling: ");
        return false;
    }

    @Override
    public boolean pan(float x,float deltaX,float deltaY) {
        Gdx.app.log(TAG,"pan: ");
        return false;
    }

    @Override
    public boolean zoom(float initialDistance,float distance) {
        Gdx.app.log(TAG,"zoom: initialDistance=" + initialDistance + ",distance=" + distance);
        return false;
    }

    @Override
    public boolean pinch(Vector2 initialPointer1,Vector2 initialPointer2,Vector2 pointer1,Vector2 pointer2) {
        Gdx.app.log(TAG,"pinch: ");
        return false;
    }
}

So I'm looking for how to rotate the perspective camera and mesh itself

Solution

I've been working on "blender style" cameras, which have kneading zoom and most blender cameras (on the desktop) This is an ongoing work – it does not fully mimic the behavior of the blender camera (not yet) I think it will lead you in the right direction Some things you should know:

>You may need to translate the model so that it is at the origin Unless you translate, the camera still points to the origin (so far, you can only translate on the desktop, not on Android); > I got most of the zoom processing code here: https://code.google.com/p/libgdx-users/wiki/PinchToZoom. >Sorry, there are magic numbers I will make these constants in the future. > If you or anyone else improves this code, I'd be happy if you share a copy with me

Abstract class:

/* Author: Christopher Grabowski,yourchristopher6334 gmail.com */

package ...;

import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.input.GestureDetector.GestureListener;
import com.badlogic.gdx.math.Vector2;

abstract public class ControllableCamera extends PerspectiveCamera implements InputProcessor{

    abstract public void resize(int width,int height);
    abstract public void render();

    public ControllableCamera(int fieldOfView,int width,int height) {
        super(fieldOfView,width,height);
    }

    @Override
    public boolean keyDown(int keyCode) {
        return false;
    }

    @Override
    public boolean keyTyped(char arg0) {
        return false;
    }

    @Override
    public boolean keyUp(int arg0) {
        return false;
    }

    @Override
    public boolean touchDown(int x,int y,int button) {
        return false;
    }

    @Override
    public boolean touchDragged(int screenX,int screenY,int pointer) {
        return false;
    }

    @Override
    public boolean touchUp(int x,int button) {
        return false;
    }

    @Override
    public boolean mouseMoved(int arg0,int arg1) {
        return false;
    }

    @Override
    public boolean scrolled(int direction) {
        return false;
    }
}

Specific courses:

/* Author: Christopher Grabowski,yourchristopher6334 gmail.com */

package ...;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.math.Vector3;

/*
 * the pause,resize,and render methods must be called within their corresponding
 * methods in the ApplicationListener
 */

public class BlenderStyleCamera extends ControllableCamera {
    public static final Vector3 ORIGIN = new Vector3(0,0);

    private static boolean shiftIsPressed = false,controlIsPressed = false,isScrollingUp = false,isScrollingDown = false,isSingleTouched = false,justSingleTouched = false;

    private float aspectRatio;
    private int x = -1,y = -1;
    private float dx = 0.0f,dy = 0.0f;
    private final Vector3 tmp = new Vector3();

    // fields related to pinch-to-zoom
    private int numberOfFingers = 0;
    private int fingerOnePointer;
    private int fingerTwoPointer;
    private float lastDistance = 0;
    private final Vector3 fingerOne = new Vector3();
    private final Vector3 fingerTwo = new Vector3();

    public BlenderStyleCamera(int fieldOfView,height);
        aspectRatio = viewportHeight / viewportWidth;
        Gdx.input.setInputProcessor(this);
        up.set(0.0f,1.0f,0.0f);
        position.set(0.0f,30.0f);
        far = 300.0f;
        lookAt(0,0);
        translate(0.0f,2.1f);
        lookAt(0,0);
        update();
    }

    public void pause() {
        numberOfFingers = 0;
    }

    @Override
    public void resize(int width,int height) {
        viewportWidth = width;
        viewportHeight = height;
        aspectRatio = viewportHeight / viewportWidth;
        update();
    }

    @Override
    public void render() {
        if (isSingleTouched) {

            // This gets the change in touch position and
            // compensates for the aspect ratio.
            if (x == -1 || y == -1 || justSingleTouched) {
                x = Gdx.input.getX();
                y = Gdx.input.getY();
            } else {
                dx = (x - Gdx.input.getX());
                dy = (y - Gdx.input.getY()) / aspectRatio;
            }

            // This zooms when control is pressed.
            if (controlIsPressed && dy > 0) {
                scrollIn();
            } else if (controlIsPressed && dy < 0) {
                scrollOut();
            }

            // This translates the camera blender-style
            // if shift is pressed.
            // Note that this will look weird with a
            // perspective camera.
            else if (shiftIsPressed) {
                translateTangentially();
            }

            // Default is to rotate the object
            // (actually rotate the camera about a sphere
            // that surrounds the object).
            else {
                travelAround();
            }

            x = Gdx.input.getX();
            y = Gdx.input.getY();

            justSingleTouched = false;
        }

        // this zooms when the mouse wheel is rotated
        if (isScrollingUp) {
            scrollIn();
            isScrollingUp = false;
        } else if (isScrollingDown) {
            scrollOut();
            isScrollingDown = false;
        }

        // Some key controls
        if (Gdx.input.isKeyPressed(Keys.LEFT) || Gdx.input.isKeyPressed(Keys.A)) {
            translateTangentially(1,0);
        } else if (Gdx.input.isKeyPressed(Keys.RIGHT)
                || Gdx.input.isKeyPressed(Keys.D)) {
            translateTangentially(-1,0);
        }

        if (Gdx.input.isKeyPressed(Keys.UP) || Gdx.input.isKeyPressed(Keys.W)) {
            translateTangentially(0,1);
        } else if (Gdx.input.isKeyPressed(Keys.DOWN)
                || Gdx.input.isKeyPressed(Keys.S)) {
            translateTangentially(0,-1);
        }

        update();
    }

    // These methods create the pinch zoom
    // and set some flags for logic in render method.
    @Override
    public boolean touchDown(int x,int button) {
        // for pinch-to-zoom
        numberOfFingers++;
        if (numberOfFingers == 1) {
            isSingleTouched = true;
            justSingleTouched = true;
            fingerOnePointer = pointer;
            fingerOne.set(x,y,0);
        } else if (numberOfFingers == 2) {
            isSingleTouched = false;
            fingerTwoPointer = pointer;
            fingerTwo.set(x,0);

            float distance = fingerOne.dst(fingerTwo);
            lastDistance = distance;
        }
        return true;
    }

    @Override
    public boolean touchDragged(int x,int pointer) {
        if (numberOfFingers > 1) {
            if (pointer == fingerOnePointer) {
                fingerOne.set(x,0);
            }
            if (pointer == fingerTwoPointer) {
                fingerTwo.set(x,0);
            }

            float distance = fingerOne.dst(fingerTwo);

            if (lastDistance > distance) {
                scrollOut();
            } else if (lastDistance < distance) {
                scrollIn();
            }

            lastDistance = distance;
            update();
        }
        return true;
    }

    @Override
    public boolean touchUp(int x,int button) {
        isSingleTouched = false;
        if (numberOfFingers == 1) {
            Vector3 touchPoint = new Vector3(x,0);
            unproject(touchPoint);
        }
        numberOfFingers--;

        // just some error prevention... clamping number of fingers (ouch! :-)
        if (numberOfFingers < 0) {
            numberOfFingers = 0;
        }

        lastDistance = 0;
        return false;
    }   

    // These methods set flags for logic in render method.
    @Override
    public boolean keyDown(int keycode) {

        switch (keycode) {
        case (Keys.SHIFT_LEFT):
        case (Keys.SHIFT_RIGHT):
            shiftIsPressed = true;
            break;
        case (Keys.CONTROL_LEFT):
        case (Keys.CONTROL_RIGHT):
            controlIsPressed = true;
            break;
        case (Keys.O):
            this.up.set(0.0f,0.0f);
            this.position.set(0.0f,30.0f);
            this.lookAt(0,0);
            this.update();
        }
        return true;
    }

    @Override
    public boolean keyUp(int arg0) {
        shiftIsPressed = controlIsPressed = false;
        return true;
    }

    @Override
    public boolean scrolled(int direction) {
        if (direction == -1) {
            isScrollingUp = true;
        } else if (direction == 1) {
            isScrollingDown = true;
        }
        return true;
    }

    // The rest of the methods translate the camera.
    public void scrollIn() {
        float magnitude = 1.0f;
        scrollIn(magnitude);
    }

    public void scrollIn(float magnitude) {
        if (position.dst2(ORIGIN) > 2.0f) {
            tmp.set(position);
            tmp.nor();
            this.translate(-tmp.x * magnitude,-tmp.y * magnitude,-tmp.z
                    * magnitude);
            update();
        }
    }

    public void scrollOut() {
        float magnitude = 1.0f;
        scrollOut(magnitude);
    }

    public void scrollOut(float magnitude) {
        tmp.set(position);
        tmp.nor();
        this.translate(tmp.x * magnitude,tmp.y * magnitude,tmp.z * magnitude);
        update();
    }

    private void travelAround() {
        tmp.set(up);
        rotateAround(ORIGIN,tmp,dx);
        tmp.crs(position).nor();
        rotateAround(ORIGIN,dy);
    }

    private void translateTangentially() {
        translateTangentially(dx,dy);
    }

    private void translateTangentially(float dx,float dy) {
        tmp.set(up);
        tmp.crs(position);
        if (dx > 0) {
            translate(tmp.x / 15.0f,tmp.y / 15.0f,tmp.z / 15.0f);
        } else if (dx < 0) {
            translate(-tmp.x / 15.0f,-tmp.y / 15.0f,-tmp.z / 15.0f);
        }

        if (dy > 0) {
            translate(-up.x,-up.y,-up.z);
        } else if (dy < 0) {
            translate(up);
        }
    }

}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>