2012-11-16 19 views
5

3Dモデルを.objから読み込み、画面にタッチしてズーム/回転させるためのシンプルなアプリケーションを作成しようとしています。libgdxタッチで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を回転させ、自身をメッシュする方法を探しています。

答えて

0

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

私はlibGDX Camera.rotateAroundメソッドが必要としていると信じています。 "ポイント"をモデルの中心にしておき、ユーザーが遊んでいる/パンしている方法に基づいて "軸"パラメータを設定します。 「角度」は固定値でもよいし、フライ/パンの強度に関連してもよい。

2

私は、ピンチャーツーズーム機能と(デスクトップ上で)Blenderのカメラで得られるほとんどの機能を備えた「Blenderスタイル」のカメラに取り組んでいます。これは進行中の作業です。Blenderのカメラの動作を完全に模倣するわけではありません(まだ)。私はこれが正しい方向に指摘されると思う。

  1. モデルが翻訳元になるように翻訳しなければならない場合があります。あなたが翻訳しない限り、カメラは原点を指差したままです。 (あなたはデスクトップ上でのみ翻訳することができ、アンドロイドではこれまでのところ翻訳することはできません)。

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

} 
関連する問題