5

.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, 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, 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, float y, 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, int pointer, int button) {
        Gdx.app.log(TAG, "fling: ");
        return false;
    }

    @Override
    public boolean pan(float x, float y, 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 自体を回転させる方法を探しています。

4

3 に答える 3

2

私は、Blender のカメラで得られるほとんどの機能と同様に、(デスクトップ上で) ピンチしてズームする機能を備えた「Blender スタイル」のカメラに取り組んできました。これは進行中の作業です — Blender のカメラの動作を完全に模倣するわけではありません (まだ)。これにより、正しい方向に向けられると思います。あなたが知っておくべきいくつかのこと:

  1. モデルを原点に配置するために、モデルを変換する必要がある場合があります。平行移動しない限り、カメラは原点を向いたままです。(これまでのところ、デスクトップでのみ翻訳でき、Android では翻訳できません);

  2. ここでピンチツーズーム処理コードのほとんどを取得しました: https://code.google.com/p/libgdx-users/wiki/PinchToZoom

  3. マジックナンバーでごめんなさい。私は将来それらの定数を作ります。

  4. あなたまたは他の誰かがこのコードを改善する場合は、コピーを私と共有していただければ幸いです.

抽象クラス:

/* 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 pointer, int button) {
        return false;
    }

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

    @Override
    public boolean touchUp(int x, int y, int pointer, 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, 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, int width, int height) {
        super(fieldOfView, width, height);
        aspectRatio = viewportHeight / viewportWidth;
        Gdx.input.setInputProcessor(this);
        up.set(0.0f, 1.0f, 0.0f);
        position.set(0.0f, 0.0f, 30.0f);
        far = 300.0f;
        lookAt(0, 0, 0);
        translate(0.0f, 0.0f, 2.1f);
        lookAt(0, 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 y, int pointer, 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, y, 0);

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

    @Override
    public boolean touchDragged(int x, int y, int pointer) {
        if (numberOfFingers > 1) {
            if (pointer == fingerOnePointer) {
                fingerOne.set(x, y, 0);
            }
            if (pointer == fingerTwoPointer) {
                fingerTwo.set(x, y, 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 y, int pointer, int button) {
        isSingleTouched = false;
        if (numberOfFingers == 1) {
            Vector3 touchPoint = new Vector3(x, y, 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, 1.0f, 0.0f);
            this.position.set(0.0f, 0.0f, 30.0f);
            this.lookAt(0, 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, tmp, 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);
        }
    }

}
于 2013-03-04T19:21:33.830 に答える
1

これを見てください:メッシュ レンダリングの問題 libgdx

メソッドrenderには、必要なコードが含まれています。

于 2012-11-23T18:34:16.630 に答える
0

カメラを回転させるか、モデルを回転させる必要があります。

libGDX Camera.rotateAroundメソッドが必要なことを行うと思います。モデルの中心として「ポイント」を残し、ユーザーがフリング/パンする方法に基づいて「軸」パラメーターを設定します。「角度」は、固定値にするか、フリング/パンの強度に相対的にすることができます。

于 2012-11-22T04:29:57.460 に答える