2012-11-16 18 views
5

Próbuję stworzyć prostą aplikację, która pozwala ładować model 3D z .obj i powiększać/obracać go dotykając ekranu.libgdx jak powiększyć i obrócić model 3D na dotyk

Udało mi się napisać kod, który ładuje model 3D z pliku i wykrywa gesty, ale teraz nie jestem pewien, co zrobić, aby włączyć funkcje powiększania/obracania, dotykając ekranu.

Oto mój kod teraz:

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

Więc szukam jak obrócić PerspectiveCamera i Mesh się.

Odpowiedz

0

Musisz obrócić kamerę lub obrócić model.

Wierzę, że metoda libGDX Camera.rotateAround spełnia to, czego potrzebujesz. Pozostaw "punkt" jako środek modelu i ustaw parametr "oś" w zależności od tego, w jaki sposób użytkownik rzuca palenie/przesuwanie. "Kąt" może być albo stałą wartością, albo zależną od intensywności rzutu/panoramy.

2

Pracuję nad kamerą w stylu "Blendera", która ma funkcję "szczypta do powiększenia", a także (na pulpicie) większość funkcji, jakie oferuje aparat Blendera. Jest to praca w toku - nie idealnie imituje zachowanie kamery Blendera (jeszcze). Myślę, że to pozwoli ci wskazać właściwy kierunek. Kilka rzeczy, które powinieneś wiedzieć:

  1. Być może będziesz musiał przetłumaczyć swój model, aby był zgodny z jego pochodzeniem. Kamera pozostaje skierowana na pochodzenie, chyba że ją przetłumaczysz. (Możesz tłumaczyć tylko na komputerach, a nie na Androidzie);

  2. Mam tutaj kod obsługi pinch-zoom: https://code.google.com/p/libgdx-users/wiki/PinchToZoom.

  3. Przepraszamy za magiczne liczby. Te stałe powstaną w przyszłości.

  4. Jeśli ty lub ktokolwiek inny ulepszysz ten kod, bardzo bym chciał, gdybyś udostępnił mi kopię.

abstrakcyjna klasa:

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

Beton klasy:

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

} 
Powiązane problemy