diff --git a/client/src/main/java/nl/andrewl/aos2_client/Aos2Client.java b/client/src/main/java/nl/andrewl/aos2_client/Aos2Client.java index 3d63464..b805193 100644 --- a/client/src/main/java/nl/andrewl/aos2_client/Aos2Client.java +++ b/client/src/main/java/nl/andrewl/aos2_client/Aos2Client.java @@ -2,6 +2,7 @@ package nl.andrewl.aos2_client; import nl.andrewl.aos_core.FileUtils; import nl.andrewl.aos_core.model.Chunk; +import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector3f; import org.lwjgl.BufferUtils; @@ -35,7 +36,7 @@ public class Aos2Client { } }); -// glfwSetInputMode(windowHandle, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + glfwSetInputMode(windowHandle, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetInputMode(windowHandle, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE); glfwSetWindowPos(windowHandle, 50, 50); @@ -54,33 +55,53 @@ public class Aos2Client { Chunk chunk = Chunk.random(new Random(1)); Camera cam = new Camera(); - cam.setPosition(0, 3, 0); - float angle = 0; + glfwSetCursorPosCallback(windowHandle, cam); + + for (int i = 0; i < 16; i++) { + chunk.setBlockAt(i, 0, 0, (byte) 8); + chunk.setBlockAt(0, i, 0, (byte) 40); + chunk.setBlockAt(0, 0, i, (byte) 120); + } chunk.setBlockAt(0, 15, 0, (byte) 0); chunk.setBlockAt(1, 15, 0, (byte) 0); chunk.setBlockAt(2, 15, 0, (byte) 0); chunk.setBlockAt(2, 15, 1, (byte) 0); + chunk.setBlockAt(0, 0, 0, (byte) 0); Matrix4f projectionTransform = new Matrix4f().perspective(70, 800 / 600.0f, 0.01f, 100.0f); ChunkMesh mesh = new ChunkMesh(chunk); int shaderProgram = createShaderProgram(); int projectionTransformUniform = glGetUniformLocation(shaderProgram, "projectionTransform"); int viewTransformUniform = glGetUniformLocation(shaderProgram, "viewTransform"); + int normalTransformUniform = glGetUniformLocation(shaderProgram, "normalTransform"); glUniformMatrix4fv(projectionTransformUniform, false, projectionTransform.get(new float[16])); + long t = 0; while (!glfwWindowShouldClose(windowHandle)) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUniformMatrix4fv(viewTransformUniform, false, cam.getViewTransformData()); + Matrix3f normalTransform = new Matrix3f(); + glUniformMatrix3fv(normalTransformUniform, false, normalTransform.get(new float[9])); mesh.draw(); glfwSwapBuffers(windowHandle); glfwPollEvents(); - angle += Math.PI / 48; - Thread.sleep(40); - cam.setOrientation((float) (Math.PI), 0); +// float n = (float) (8 * Math.sin(Math.toRadians(t)) + 8); +// cam.setPosition(n, -1, n); +// cam.setOrientationDegrees(0, 0); +// Thread.sleep(20); +// t++; +// if (t >= 360) t = 0; + + if (glfwGetKey(windowHandle, GLFW_KEY_W) == GLFW_PRESS) cam.move(Camera.FORWARD); + if (glfwGetKey(windowHandle, GLFW_KEY_S) == GLFW_PRESS) cam.move(Camera.BACKWARD); + if (glfwGetKey(windowHandle, GLFW_KEY_A) == GLFW_PRESS) cam.move(Camera.LEFT); + if (glfwGetKey(windowHandle, GLFW_KEY_D) == GLFW_PRESS) cam.move(Camera.RIGHT); + if (glfwGetKey(windowHandle, GLFW_KEY_SPACE) == GLFW_PRESS) cam.move(Camera.UP); + if (glfwGetKey(windowHandle, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) cam.move(Camera.DOWN); } Callbacks.glfwFreeCallbacks(windowHandle); diff --git a/client/src/main/java/nl/andrewl/aos2_client/Camera.java b/client/src/main/java/nl/andrewl/aos2_client/Camera.java index a52a5eb..4a6c90d 100644 --- a/client/src/main/java/nl/andrewl/aos2_client/Camera.java +++ b/client/src/main/java/nl/andrewl/aos2_client/Camera.java @@ -4,26 +4,49 @@ import nl.andrewl.aos_core.MathUtils; import org.joml.Matrix4f; import org.joml.Vector2f; import org.joml.Vector3f; +import org.lwjgl.glfw.GLFWCursorPosCallbackI; + +import static org.lwjgl.glfw.GLFW.glfwGetCursorPos; + +public class Camera implements GLFWCursorPosCallbackI { + public static final Vector3f UP = new Vector3f(0, 1, 0); + public static final Vector3f DOWN = new Vector3f(0, -1, 0); + public static final Vector3f RIGHT = new Vector3f(1, 0, 0); + public static final Vector3f LEFT = new Vector3f(-1, 0, 0); + public static final Vector3f FORWARD = new Vector3f(0, 0, -1); + public static final Vector3f BACKWARD = new Vector3f(0, 0, 1); -public class Camera { private final Vector3f position; private final Vector2f orientation; private final Matrix4f viewTransform; private final float[] viewTransformData = new float[16]; + private float lastMouseCursorX; + private float lastMouseCursorY; + private float mouseCursorSensitivity = 0.005f; + public Camera() { this.position = new Vector3f(); - this.orientation = new Vector2f(); + this.orientation = new Vector2f(0, (float) (Math.PI / 2)); this.viewTransform = new Matrix4f(); } + public Matrix4f getViewTransform() { + return viewTransform; + } + public float[] getViewTransformData() { return viewTransformData; } + public Vector2f getOrientation() { + return orientation; + } + public void setPosition(float x, float y, float z) { position.set(x, y, z); updateViewTransform(); + System.out.printf("Position: x=%.2f, y=%.2f, z=%.2f%n", position.x, position.y, position.z); } public void setOrientation(float x, float y) { @@ -31,11 +54,50 @@ public class Camera { updateViewTransform(); } + public void setOrientationDegrees(float x, float y) { + setOrientation((float) Math.toRadians(x), (float) Math.toRadians(y)); + } + private void updateViewTransform() { viewTransform.identity(); - viewTransform.rotate(-orientation.x, new Vector3f(1, 0, 0)); - viewTransform.rotate(-orientation.y, new Vector3f(0, 1, 0)); - viewTransform.translate(position.x, position.y, position.z); + viewTransform.rotate(-orientation.y, RIGHT); + viewTransform.rotate(-orientation.x, UP); + viewTransform.translate(-position.x, -position.y, -position.z); viewTransform.get(viewTransformData); } + + @Override + public void invoke(long windowHandle, double xPos, double yPos) { + double[] xb = new double[1]; + double[] yb = new double[1]; + glfwGetCursorPos(windowHandle, xb, yb); + float x = (float) xb[0]; + float y = (float) yb[0]; + float dx = x - lastMouseCursorX; + float dy = y - lastMouseCursorY; + lastMouseCursorX = x; + lastMouseCursorY = y; + setOrientation(orientation.x - dx * mouseCursorSensitivity, orientation.y - dy * mouseCursorSensitivity); +// System.out.printf("rX=%.0f deg about the Y axis, rY=%.0f deg about the X axis%n", Math.toDegrees(orientation.x), Math.toDegrees(orientation.y)); + var vv = getViewVector(); +// System.out.printf("View vector: [%.2f, %.2f, %.2f]%n", vv.x, vv.y, vv.z); + } + + public Vector3f getViewVector() { + return new Vector3f( + (float) -Math.sin(orientation.x), + (float) -Math.cos(orientation.y), + (float) Math.cos(orientation.x) + ); + } + + public void move(Vector3f relativeMotion) { + Vector3f actualMotion = new Vector3f(relativeMotion).mul(0.1f); + Matrix4f moveTransform = new Matrix4f(); + moveTransform.rotate(orientation.x, UP); + moveTransform.transformDirection(actualMotion); + position.add(actualMotion); + updateViewTransform(); + System.out.printf("Position: x=%.2f, y=%.2f, z=%.2f%n", position.x, position.y, position.z); + } } diff --git a/client/src/main/java/nl/andrewl/aos2_client/TextMesh.java b/client/src/main/java/nl/andrewl/aos2_client/TextMesh.java new file mode 100644 index 0000000..d61d870 --- /dev/null +++ b/client/src/main/java/nl/andrewl/aos2_client/TextMesh.java @@ -0,0 +1,50 @@ +package nl.andrewl.aos2_client; + +import org.joml.Vector2f; +import org.lwjgl.BufferUtils; + +import java.awt.*; +import java.nio.ByteBuffer; + +import static org.lwjgl.opengl.GL46.*; +import static org.lwjgl.stb.STBEasyFont.stb_easy_font_print; + +public class TextMesh { + private final int vbo; + private final int vao; + private int quadCount; + + private String text; + private final Vector2f position; + + public TextMesh() { + this.vbo = glGenBuffers(); + this.vao = glGenVertexArrays(); + this.position = new Vector2f(); + this.text = "Hello world"; + + glBindVertexArray(vao); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, false, 7, 0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, false, 7, 3); + } + + public void updateMesh() { + ByteBuffer colorBuffer = ByteBuffer.allocate(4); + colorBuffer.putInt(Color.WHITE.getRGB()); + colorBuffer.flip(); + ByteBuffer vertexBuffer = BufferUtils.createByteBuffer(text.length() * 500); + quadCount = stb_easy_font_print(position.x, position.y, text, colorBuffer, vertexBuffer); + vertexBuffer.flip(); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, vertexBuffer, GL_STATIC_DRAW); + } + + public void draw() { + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBindVertexArray(vao); + + glDrawArrays(GL_QUADS, 0, quadCount); + } +} diff --git a/client/src/main/resources/shader/fragment.glsl b/client/src/main/resources/shader/fragment.glsl index 8341631..71ed3f8 100644 --- a/client/src/main/resources/shader/fragment.glsl +++ b/client/src/main/resources/shader/fragment.glsl @@ -7,7 +7,7 @@ in vec3 vertexNormal; out vec4 fragmentColor; void main() { - vec3 lightDirection = vec3(0.0, -1.0, -0.5);// TODO: Add this via a uniform. + vec3 lightDirection = normalize(vec3(0.1, -1.0, -0.5));// TODO: Add this via a uniform. vec3 lightColor = vec3(1.0, 1.0, 0.9); // TODO: Add this via a uniform. vec3 ambientComponent = vec3(0.1, 0.1, 0.1); diff --git a/client/src/main/resources/shader/vertex.glsl b/client/src/main/resources/shader/vertex.glsl index fbbfefe..fc0580c 100644 --- a/client/src/main/resources/shader/vertex.glsl +++ b/client/src/main/resources/shader/vertex.glsl @@ -6,6 +6,7 @@ layout (location = 2) in vec3 vertexNormalIn; uniform mat4 projectionTransform; uniform mat4 viewTransform; +uniform mat3 normalTransform; out vec3 vertexPosition; out vec3 vertexColor; @@ -16,5 +17,5 @@ void main() { gl_Position = projectionTransform * viewTransform * vec4(vertexPositionIn, 1.0); vertexPosition = vertexPositionIn; vertexColor = vertexColorIn; - vertexNormal = vertexNormalIn; + vertexNormal = normalize(normalTransform * vertexNormalIn); }