java – libgdx如何在触摸时缩放和旋转3d模型

前端之家收集整理的这篇文章主要介绍了java – libgdx如何在触摸时缩放和旋转3d模型前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试创建一个简单的应用程序,它允许您从.obj加载3D模型,并通过触摸屏幕缩放/旋转它.

我设法编写了从文件中加载3d模型并检测手势的代码,但现在我不知道如何通过触摸屏幕来启用缩放/旋转功能.

这是我现在的代码

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

所以我正在寻找如何旋转PerspectiveCamera和Mesh本身.

解决方法

我一直致力于“Blender风格”相机,它具有捏合变焦功能以及(在桌面上)大多数Blender相机的功能.这是一项正在进行的工作 – 它并不完全模仿Blender相机的行为(尚未).我想这会让你指出正确的方向.你应该知道的一些事情:

>您可能需要翻译模型,使其位于原点.除非您翻译,否则相机仍然指向原点. (到目前为止,您只能在桌面上翻译而不是在Android上翻译);
>我在这里得到了大部分的缩放变焦处理代码https://code.google.com/p/libgdx-users/wiki/PinchToZoom.
>抱歉有神奇的数字.我将在未来制作这些常数.
>如果您或其他任何人改进了此代码,我很乐意,如果您与我共享副本.

抽象类:

/* 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;
    }
}

具体课程:

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

}
原文链接:https://www.f2er.com/java/444663.html

猜你在找的Java相关文章