这是我FPS风格相机的基础代码片段。如您所见,我正在计算鼠标位置与屏幕中心沿X和Y轴的差值。
您可以在我的System.out.println调用中看到我计算Delta的值以及应该旋转这个角度的事实。然后,我将这些值乘以灵敏度,并按此数量旋转相机。
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 {
private GLFWErrorCallback errorCallback;
private GLFWKeyCallback keyCallback;
private long window;
public void run() {
System.out.println("Hello LWJGL " + Sys.getVersion() + "!");
try {
init();
loop();
glfwDestroyWindow(window);
keyCallback.release();
} finally {
glfwTerminate();
errorCallback.release();
}
}
private void init() {
glfwSetErrorCallback(errorCallback = errorCallbackPrint(System.err));
if ( glfwInit() != GL11.GL_TRUE )
throw new IllegalStateException("Unable to initialize GLFW");
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
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;
window = glfwCreateWindow(WIDTH, HEIGHT, "Hello World!", NULL, NULL);
if ( window == NULL )
throw new RuntimeException("Failed to create the GLFW window");
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);
}
});
ByteBuffer vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(
window,
(GLFWvidmode.width(vidmode) - WIDTH) / 2,
(GLFWvidmode.height(vidmode) - HEIGHT) / 2
);
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwShowWindow(window);
}
private void loop() {
GLContext.createFromCurrent();
FloatBuffer vertices = BufferUtils.createFloatBuffer(9);
vertices.put(new float[]
{
0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f
});
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);
}
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram (shader_programme);
glBindVertexArray (vao);
glDrawArrays (GL_TRIANGLES, 0, 3);
glfwPollEvents ();
glfwSwapBuffers (window);
}
}
public static void main(String[] args) {
new Main().run();
}
}
Mouse
是一个LWJGL类,肯定有Mouse.getDX/DY()
方法。 - Joehot200