2014-12-03 68 views
2

我想在我的lwjgl3 java應用程序中實現FPS樣式的鼠標外觀,但由於沒有任何Mouse.getDX()Mouse.getDY(),我正在尋找使用glfw綁定的不同方法。 我寫這個方法被調用在我update()方法:LWJGL 3 Mouse Movement

public double[] pollMouseDelta() { 
    DoubleBuffer x = BufferUtils.createDoubleBuffer(1); 
    DoubleBuffer y = BufferUtils.createDoubleBuffer(1); 

    glfwGetCursorPos(WINDOW, x, y); 
    x.rewind(); 
    y.rewind(); 

    double tempX = mouseX; 
    double tempY = mouseY; 

    mouseX = x.get(); 
    mouseY = y.get(); 

    return new double[] { 
      mouseX - tempX, 
      mouseY - tempY 
    }; 
} 

其中mouseXmouseY是全局變量。

在我更新的方法我做到以下幾點:

double[] mouseDelta = pollMouseDelta(); 

camera.rotate(Camera.Direction.LEFT_RIGHT, (float) (0.2f * -mouseDelta[0])); 
camera.rotate(Camera.Direction.UP_DOWN, (float) (0.2f * mouseDelta[1])); 

camera.update(); 

我還設置了GLFW_CURSOR模式GLFW_CURSOR_DISABLED
但相機口吃和大跳躍。另外,有時鼠標似乎是倒置的。

有什麼建議嗎?

+0

你混淆了我。 'Mouse'是一個LWJGL類,它肯定有'Mouse.getDX/DY()'。 – Joehot200 2014-12-04 23:02:37

+1

他們刪除了所有的類,但不得不做一些與視窗系統,因爲它們使用GLFW現在支持多窗口 – tobs 2014-12-05 06:31:39

回答

3

這裏是我的FPS風格相機的基礎代碼片段。正如你所看到的,我正在計算沿着X軸和Y軸的屏幕中心的鼠標位置的增量。

你可以在我的System.out.println看到來電我計算三角洲的值,它應該由這個量是旋轉的事實。然後我將這些值乘以我的靈敏度,然後將相機旋轉一圈。

import org.lwjgl.BufferUtils; 
import org.lwjgl.Sys; 
import org.lwjgl.glfw.*; 
import org.lwjgl.opengl.*; 

import java.nio.ByteBuffer; 
import java.nio.DoubleBuffer; 
import java.nio.FloatBuffer; 

import static org.lwjgl.glfw.Callbacks.*; 
import static org.lwjgl.glfw.GLFW.*; 
import static org.lwjgl.glfw.GLFW.glfwGetCursorPos; 
import static org.lwjgl.opengl.GL11.*; 
import static org.lwjgl.opengl.GL15.*; 
import static org.lwjgl.opengl.GL20.*; 
import static org.lwjgl.opengl.GL30.*; 
import static org.lwjgl.system.MemoryUtil.*; 

public class Main { 

    // We need to strongly reference callback instances. 
    private GLFWErrorCallback errorCallback; 
    private GLFWKeyCallback keyCallback; 

    // The window handle 
    private long window; 

    public void run() { 
     System.out.println("Hello LWJGL " + Sys.getVersion() + "!"); 

     try { 
      init(); 
      loop(); 

      // Release window and window callbacks 
      glfwDestroyWindow(window); 
      keyCallback.release(); 
     } finally { 
      // Terminate GLFW and release the GLFWerrorfun 
      glfwTerminate(); 
      errorCallback.release(); 
     } 
    } 

    private void init() { 
     // Setup an error callback. The default implementation 
     // will print the error message in System.err. 
     glfwSetErrorCallback(errorCallback = errorCallbackPrint(System.err)); 

     // Initialize GLFW. Most GLFW functions will not work before doing this. 
     if (glfwInit() != GL11.GL_TRUE) 
      throw new IllegalStateException("Unable to initialize GLFW"); 

     // Configure our window 
     glfwDefaultWindowHints(); // optional, the current window hints are already the default 
     glfwWindowHint(GLFW_VISIBLE, GL_FALSE); // the window will stay hidden after creation 
     glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // the window will be resizable 
     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 
     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 
     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 
     glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 


     int WIDTH = 800; 
     int HEIGHT = 600; 

     // Create the window 
     window = glfwCreateWindow(WIDTH, HEIGHT, "Hello World!", NULL, NULL); 
     if (window == NULL) 
      throw new RuntimeException("Failed to create the GLFW window"); 

     // Setup a key callback. It will be called every time a key is pressed, repeated or released. 
     glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback() { 
      @Override 
      public void invoke(long window, int key, int scancode, int action, int mods) { 
       if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) 
        glfwSetWindowShouldClose(window, GL_TRUE); // We will detect this in our rendering loop 
      } 
     }); 

     // Get the resolution of the primary monitor 
     ByteBuffer vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); 
     // Center our window 
     glfwSetWindowPos(
       window, 
       (GLFWvidmode.width(vidmode) - WIDTH)/2, 
       (GLFWvidmode.height(vidmode) - HEIGHT)/2 
     ); 

     // Make the OpenGL context current 
     glfwMakeContextCurrent(window); 
     // Enable v-sync 
     glfwSwapInterval(1); 

     // Make the window visible 
     glfwShowWindow(window); 
    } 

    private void loop() { 
     // This line is critical for LWJGL's interoperation with GLFW's 
     // This line is critical for LWJGL's interoperation with GLFW's 
     // OpenGL context, or any context that is managed externally. 
     // LWJGL detects the context that is current in the current thread, 
     // creates the ContextCapabilities instance and makes the OpenGL 
     // bindings available for use. 
     GLContext.createFromCurrent(); 


     // Create a FloatBuffer to hold our vertex data 
     FloatBuffer vertices = BufferUtils.createFloatBuffer(9); 
     // Add vertices of the triangle 
     vertices.put(new float[] 
       { 
         0.0f, 0.5f, 0.0f, 
         0.5f, -0.5f, 0.0f, 
         -0.5f, -0.5f, 0.0f 
       }); 
     // Rewind the vertices 
     vertices.rewind(); 


     int vbo = glGenBuffers(); 
     int vao = glGenVertexArrays(); 

     glBindBuffer (GL_ARRAY_BUFFER, vbo); 
     glBufferData (GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW); 
     glBindVertexArray(vao); 

     glEnableVertexAttribArray (0); 
     glBindBuffer (GL_ARRAY_BUFFER, vbo); 
     glVertexAttribPointer (0, 3, GL_FLOAT, false, 0, 0); 

     final String vertex_shader = 
       "#version 410\n" + 
         "in vec3 vp;\n" + 
         "void main() {\n" + 
         " gl_Position = vec4 (vp, 1.0);\n" + 
         "}"; 

     final String frag_shader = 
       "#version 400\n" + 
         "out vec4 frag_colour;" + 
         "void main() {"   + 
         " frag_colour = vec4 (0.5, 0.0, 0.5, 1.0);" + 
         "}"; 

     int shader_programme = glCreateProgram(); 


     int vertexShaderID = glCreateShader(GL_VERTEX_SHADER); 
     glShaderSource(vertexShaderID, vertex_shader); 
     glCompileShader (vertexShaderID); 

     if(glGetShaderi(vertexShaderID, GL_COMPILE_STATUS) == 0){ 
      System.err.println(glGetShaderInfoLog(vertexShaderID, 1024)); 
      System.exit(1); 
     } 

     glAttachShader (shader_programme, vertexShaderID); 

     int fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); 
     glShaderSource(fragmentShaderID, frag_shader); 
     glCompileShader (fragmentShaderID); 

     if(glGetShaderi(fragmentShaderID, GL_COMPILE_STATUS) == 0){ 
      System.err.println(glGetShaderInfoLog(fragmentShaderID, 1024)); 
      System.exit(1); 
     } 

     glAttachShader (shader_programme, fragmentShaderID); 

     glLinkProgram (shader_programme); 

     if(glGetProgrami(shader_programme, GL_LINK_STATUS) == 0){ 
      System.err.println(glGetProgramInfoLog(shader_programme, 1024)); 
      System.exit(1); 
     } 

     glValidateProgram(shader_programme); 

     if(glGetProgrami(shader_programme, GL_VALIDATE_STATUS) == 0){ 
      System.err.println(glGetProgramInfoLog(shader_programme, 1024)); 
      System.exit(1); 
     } 

     boolean mouseLocked = false; 
     double newX = 400; 
     double newY = 300; 

     double prevX = 0; 
     double prevY = 0; 

     boolean rotX = false; 
     boolean rotY = false; 

     glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); 


     while (glfwWindowShouldClose(window) == GL_FALSE) { 

      if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS) { 
       glfwSetCursorPos(window, 800/2, 600/2); 

       mouseLocked = true; 
      } 

      if (mouseLocked){ 
       DoubleBuffer x = BufferUtils.createDoubleBuffer(1); 
       DoubleBuffer y = BufferUtils.createDoubleBuffer(1); 

       glfwGetCursorPos(window, x, y); 
       x.rewind(); 
       y.rewind(); 

       newX = x.get(); 
       newY = y.get(); 

       double deltaX = newX - 400; 
       double deltaY = newY - 300; 

       rotX = newX != prevX; 
       rotY = newY != prevY; 

       if(rotY) { 
        System.out.println("ROTATE Y AXIS: " + deltaY); 

       } 
       if(rotX) { 
        System.out.println("ROTATE X AXIS: " + deltaX); 
       } 

       prevX = newX; 
       prevY = newY; 


       System.out.println("Delta X = " + deltaX + " Delta Y = " + deltaY); 

       glfwSetCursorPos(window, 800/2, 600/2); 
      } 

      // wipe the drawing surface clear 
      glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
      glUseProgram (shader_programme); 
      glBindVertexArray (vao); 
      // draw points 0-3 from the currently bound VAO with current in-use shader 
      glDrawArrays (GL_TRIANGLES, 0, 3); 
      // update other events like input handling 
      glfwPollEvents(); 
      // put the stuff we've been drawing onto the display 
      glfwSwapBuffers (window); 

     } 
    } 

    public static void main(String[] args) { 
     new Main().run(); 
    } 

} 
+0

對不起,我沒有回覆,本週我很忙。無論如何,感謝您的快速回復。它現在工作正常! – tobs 2014-12-17 17:38:46

+0

我只有一個問題:你是如何實現此方法有回調?你只是設置newX/newY變量,還是使用Zeroni在LWJGL論壇中提出的方法?我感興趣的是這一點,因爲我也試過他的方法,口吃是走了,但我還是看到了大的跳躍就在開始和鼠標有時反轉。 – tobs 2014-12-17 18:02:41

1

我正在研究與此相似的事情。

的想法是每次攝像機位置重置爲中心,你循環,像這樣:

glfwSetCursorPos(YOUR WINDOW HANDLE, YOUR_WINDOW_WIDTH/2, YOU_WINDOW_HEIGHT/2); 

這樣,你的增量始終相比,從屏幕中心的距離。所以這應該解決你的問題。

編輯(離開我的答案以上爲後人):

好了,我也有同樣的問題,你。無視我上面所說的不完全正確。

我最終實現了一些類似於您正在做的事情,但在三角洲太大以至於相機移動得太快時收到了相同的結果。

我做了什麼來解決這個實際上是做鼠標投票的每一個幀,並與下面的操作來計算「增量」:

deltaX = currentMousePos.x - lastFrameMousePos.x 
deltaY = currentMousePos.y - lastFrameMousePos.y 

現在增量應該足夠小,每幀也計算。

然後用於計算我的旋轉角度予使用:

deltaPos.getY() * sensitivity * Time.getDelta() 

凡Time.getDelta()是每幀循環之間的時間差異。我最終得到的是一個相當流暢的相機,儘管還不完美。

讓我知道你是否想要更多的信息。

編輯2:

看看這個鏈接,有我類似的問題Link在LWJGL論壇。我現在確實有這個工作很好。我會用代碼發佈一個單獨的答案。

+0

感謝您的答覆靜態方法。我嘗試這樣做,得到一個奇怪的控制檯輸出:鼠標正在在比賽開始一個大的跳躍,鼠標三角洲超過800 X和Y座標。如果我重新開始遊戲,鼠標有時會倒轉。 – tobs 2014-12-13 12:29:18

+1

退房的編輯我的答案,讓我知道如果這有助於 – abarax 2014-12-14 02:03:22

+0

感謝這個快速回復。你正在使用回調還是直接拉光標位置? – tobs 2014-12-14 10:53:53

0

的另一種方式讓你的鼠標位置是延長GLFWCursorPosCallback類,然後只用x和y的值,它提供了在它的調用方法。

做這方面的一個很好的教程,可以在這裏找到:

LWJGL 3 Mouse Position