Added ability to render mutiple players.

This commit is contained in:
Andrew Lalis 2022-07-17 16:24:41 +02:00
parent 6cf5b599d0
commit 833ca720f1
27 changed files with 1133 additions and 240 deletions

View File

@ -146,6 +146,11 @@
<artifactId>aos2-core</artifactId>
<version>${parent.version}</version>
</dependency>
<dependency>
<groupId>de.javagl</groupId>
<artifactId>obj</artifactId>
<version>0.3.0</version>
</dependency>
<dependency>
<groupId>org.lwjgl</groupId>

View File

@ -5,16 +5,11 @@ import nl.andrewl.aos2_client.control.PlayerInputKeyCallback;
import nl.andrewl.aos2_client.control.PlayerInputMouseClickCallback;
import nl.andrewl.aos2_client.control.PlayerViewCursorCallback;
import nl.andrewl.aos2_client.render.GameRenderer;
import nl.andrewl.aos_core.model.Chunk;
import nl.andrewl.aos_core.model.ColorPalette;
import nl.andrewl.aos_core.model.World;
import nl.andrewl.aos_core.net.ChunkDataMessage;
import nl.andrewl.aos_core.net.ChunkHashMessage;
import nl.andrewl.aos_core.net.WorldInfoMessage;
import nl.andrewl.aos_core.net.*;
import nl.andrewl.aos_core.net.udp.ChunkUpdateMessage;
import nl.andrewl.aos_core.net.udp.PlayerUpdateMessage;
import nl.andrewl.record_net.Message;
import org.joml.Vector3i;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -60,14 +55,18 @@ public class Client implements Runnable {
gameRenderer.setupWindow(
new PlayerViewCursorCallback(gameRenderer.getCamera(), communicationHandler),
new PlayerInputKeyCallback(inputHandler),
new PlayerInputMouseClickCallback(inputHandler)
new PlayerInputMouseClickCallback(inputHandler),
false,
false
);
long lastFrameAt = System.currentTimeMillis();
while (!gameRenderer.windowShouldClose()) {
long now = System.currentTimeMillis();
float dt = (now - lastFrameAt) / 1000f;
world.processQueuedChunkUpdates();
gameRenderer.getCamera().interpolatePosition(dt);
world.interpolatePlayers(dt);
gameRenderer.draw();
lastFrameAt = now;
}
@ -75,31 +74,17 @@ public class Client implements Runnable {
communicationHandler.shutdown();
}
public int getClientId() {
return clientId;
}
public World getWorld() {
return world;
}
public void onMessageReceived(Message msg) {
if (msg instanceof WorldInfoMessage worldInfo) {
world.setPalette(ColorPalette.fromArray(worldInfo.palette()));
}
if (msg instanceof ChunkDataMessage chunkDataMessage) {
Chunk chunk = chunkDataMessage.toChunk();
world.addChunk(chunk);
gameRenderer.getChunkRenderer().queueChunkMesh(chunk);
world.addChunk(chunkDataMessage);
}
if (msg instanceof ChunkUpdateMessage u) {
Vector3i chunkPos = new Vector3i(u.cx(), u.cy(), u.cz());
Chunk chunk = world.getChunkAt(chunkPos);
System.out.println(u);
if (chunk != null) {
chunk.setBlockAt(u.lx(), u.ly(), u.lz(), u.newBlock());
gameRenderer.getChunkRenderer().queueChunkMesh(chunk);
} else {
world.updateChunk(u);
// If we received an update for a chunk we don't have, request it!
if (world.getChunkAt(u.getChunkPos()) == null) {
communicationHandler.sendMessage(new ChunkHashMessage(u.cx(), u.cy(), u.cz(), -1));
}
}
@ -108,9 +93,16 @@ public class Client implements Runnable {
float eyeHeight = playerUpdate.crouching() ? 1.3f : 1.7f;
gameRenderer.getCamera().setPosition(playerUpdate.px(), playerUpdate.py() + eyeHeight, playerUpdate.pz());
gameRenderer.getCamera().setVelocity(playerUpdate.vx(), playerUpdate.vy(), playerUpdate.vz());
// TODO: Unload far away chunks and request close chunks we don't have.
} else {
world.playerUpdated(playerUpdate);
}
}
if (msg instanceof PlayerJoinMessage joinMessage) {
world.playerJoined(joinMessage);
}
if (msg instanceof PlayerLeaveMessage leaveMessage) {
world.playerLeft(leaveMessage);
}
}

View File

@ -1,7 +1,138 @@
package nl.andrewl.aos2_client;
import nl.andrewl.aos2_client.render.chunk.ChunkMesh;
import nl.andrewl.aos2_client.render.chunk.ChunkMeshGenerator;
import nl.andrewl.aos_core.model.Chunk;
import nl.andrewl.aos_core.model.Player;
import nl.andrewl.aos_core.model.World;
import nl.andrewl.aos_core.net.ChunkDataMessage;
import nl.andrewl.aos_core.net.PlayerJoinMessage;
import nl.andrewl.aos_core.net.PlayerLeaveMessage;
import nl.andrewl.aos_core.net.udp.ChunkUpdateMessage;
import nl.andrewl.aos_core.net.udp.PlayerUpdateMessage;
import org.joml.Vector3f;
import org.joml.Vector3i;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* A client-side extension of the world model, with information that is only
* important for the client to know about, like other players and chunk render
* queues.
*/
public class ClientWorld extends World {
private final Queue<Chunk> chunkUpdateQueue = new ConcurrentLinkedQueue<>();
private final Queue<Chunk> chunkRemovalQueue = new ConcurrentLinkedQueue<>();
private final ChunkMeshGenerator chunkMeshGenerator = new ChunkMeshGenerator();
private final Map<Chunk, ChunkMesh> chunkMeshes = new ConcurrentHashMap<>();
private final Map<Integer, Player> players = new HashMap<>();
public void playerJoined(PlayerJoinMessage joinMessage) {
Player p = joinMessage.toPlayer();
players.put(p.getId(), p);
}
public void playerLeft(PlayerLeaveMessage leaveMessage) {
players.remove(leaveMessage.id());
}
public void playerUpdated(PlayerUpdateMessage playerUpdate) {
Player p = players.get(playerUpdate.clientId());
if (p != null) {
playerUpdate.apply(p);
}
}
public Collection<Player> getPlayers() {
return players.values();
}
public void interpolatePlayers(float dt) {
Vector3f movement = new Vector3f();
for (var player : getPlayers()) {
movement.set(player.getVelocity()).mul(dt);
player.getPosition().add(movement);
}
}
@Override
public void addChunk(Chunk chunk) {
super.addChunk(chunk);
chunkUpdateQueue.add(chunk);
}
public void addChunk(ChunkDataMessage msg) {
addChunk(msg.toChunk());
}
@Override
public void removeChunk(Vector3i chunkPos) {
Chunk chunk = getChunkAt(chunkPos);
if (chunk != null) {
chunkRemovalQueue.add(chunk);
chunkUpdateQueue.remove(chunk);
}
super.removeChunk(chunkPos);
}
public void updateChunk(ChunkUpdateMessage update) {
Chunk chunk = getChunkAt(update.getChunkPos());
if (chunk != null) {
chunk.setBlockAt(update.lx(), update.ly(), update.lz(), update.newBlock());
List<Chunk> chunksToReRender = new ArrayList<>(7);
chunksToReRender.add(chunk);
// Check if neighboring chunks need to be re-rendered too.
if (update.lx() == 0) {
Chunk c = getChunkAt(update.cx() - 1, update.cy(), update.cz());
if (c != null) chunksToReRender.add(c);
}
if (update.ly() == 0) {
Chunk c = getChunkAt(update.cx(), update.cy() - 1, update.cz());
if (c != null) chunksToReRender.add(c);
}
if (update.lz() == 0) {
Chunk c = getChunkAt(update.cx(), update.cy(), update.cz() - 1);
if (c != null) chunksToReRender.add(c);
}
if (update.lx() == Chunk.SIZE - 1) {
Chunk c = getChunkAt(update.cx() + 1, update.cy(), update.cz());
if (c != null) chunksToReRender.add(c);
}
if (update.ly() == Chunk.SIZE - 1) {
Chunk c = getChunkAt(update.cx(), update.cy() + 1, update.cz());
if (c != null) chunksToReRender.add(c);
}
if (update.lz() == Chunk.SIZE - 1) {
Chunk c = getChunkAt(update.cx(), update.cy(), update.cz() + 1);
if (c != null) chunksToReRender.add(c);
}
chunkUpdateQueue.addAll(chunksToReRender);
}
}
/**
* Call this to process any queued chunk updates, and update chunk meshes.
* Only call this method on the main OpenGL context thread!
*/
public void processQueuedChunkUpdates() {
while (!chunkRemovalQueue.isEmpty()) {
Chunk chunk = chunkRemovalQueue.remove();
ChunkMesh mesh = chunkMeshes.remove(chunk);
if (mesh != null) mesh.free();
}
while (!chunkUpdateQueue.isEmpty()) {
Chunk chunk = chunkUpdateQueue.remove();
ChunkMesh mesh = new ChunkMesh(chunk, this, chunkMeshGenerator);
ChunkMesh existingMesh = chunkMeshes.get(chunk);
if (existingMesh != null) existingMesh.free();
chunkMeshes.put(chunk, mesh);
}
}
public Collection<ChunkMesh> getChunkMeshesToDraw() {
return chunkMeshes.values();
}
}

View File

@ -14,7 +14,6 @@ public class PlayerInputMouseClickCallback implements GLFWMouseButtonCallbackI {
@Override
public void invoke(long window, int button, int action, int mods) {
System.out.println("Click: " + button);
inputHandler.updateInputState(window);
}
}

View File

@ -1,10 +1,11 @@
package nl.andrewl.aos2_client.render;
import nl.andrewl.aos2_client.Camera;
import nl.andrewl.aos2_client.ClientWorld;
import nl.andrewl.aos2_client.render.chunk.ChunkRenderer;
import nl.andrewl.aos2_client.render.gui.GUIRenderer;
import nl.andrewl.aos2_client.render.gui.GUITexture;
import nl.andrewl.aos_core.model.World;
import nl.andrewl.aos2_client.render.model.Model;
import org.joml.Matrix4f;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.GL;
@ -27,30 +28,33 @@ public class GameRenderer {
private static final float Z_NEAR = 0.01f;
private static final float Z_FAR = 500f;
private final ChunkRenderer chunkRenderer;
private final GUIRenderer guiRenderer;
private ChunkRenderer chunkRenderer;
private GUIRenderer guiRenderer;
private ModelRenderer modelRenderer;
private final Camera camera;
private final World world;
private final ClientWorld world;
private Model playerModel; // Standard player model used to render all players.
private long windowHandle;
private GLFWVidMode primaryMonitorSettings;
private boolean fullscreen;
private int screenWidth = 800;
private int screenHeight = 600;
private float fov = 90f;
private final Matrix4f perspectiveTransform;
public GameRenderer(World world) {
public GameRenderer(ClientWorld world) {
this.world = world;
this.chunkRenderer = new ChunkRenderer();
this.guiRenderer = new GUIRenderer();
this.camera = new Camera();
this.perspectiveTransform = new Matrix4f();
}
public void setupWindow(GLFWCursorPosCallbackI viewCursorCallback, GLFWKeyCallbackI inputKeyCallback, GLFWMouseButtonCallbackI mouseButtonCallback) {
public void setupWindow(
GLFWCursorPosCallbackI viewCursorCallback,
GLFWKeyCallbackI inputKeyCallback,
GLFWMouseButtonCallbackI mouseButtonCallback,
boolean fullscreen,
boolean grabCursor
) {
GLFWErrorCallback.createPrint(System.err).set();
if (!glfwInit()) throw new IllegalStateException("Could not initialize GLFW.");
glfwDefaultWindowHints();
@ -58,21 +62,28 @@ public class GameRenderer {
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
long monitorId = glfwGetPrimaryMonitor();
primaryMonitorSettings = glfwGetVideoMode(monitorId);
GLFWVidMode primaryMonitorSettings = glfwGetVideoMode(monitorId);
if (primaryMonitorSettings == null) throw new IllegalStateException("Could not get information about the primary monitory.");
log.debug("Primary monitor settings: Width: {}, Height: {}", primaryMonitorSettings.width(), primaryMonitorSettings.height());
if (fullscreen) {
screenWidth = primaryMonitorSettings.width();
screenHeight = primaryMonitorSettings.height();
windowHandle = glfwCreateWindow(screenWidth, screenHeight, "Ace of Shades 2", monitorId, 0);
} else {
screenWidth = 1000;
screenHeight = 800;
windowHandle = glfwCreateWindow(screenWidth, screenHeight, "Ace of Shades 2", 0, 0);
}
if (windowHandle == 0) throw new RuntimeException("Failed to create GLFW window.");
fullscreen = true;
log.debug("Initialized GLFW window.");
// Setup callbacks.
glfwSetKeyCallback(windowHandle, inputKeyCallback);
glfwSetCursorPosCallback(windowHandle, viewCursorCallback);
glfwSetMouseButtonCallback(windowHandle, mouseButtonCallback);
if (grabCursor) {
glfwSetInputMode(windowHandle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
}
glfwSetInputMode(windowHandle, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
glfwSetCursorPos(windowHandle, 0, 0);
log.debug("Set up window callbacks.");
@ -80,7 +91,6 @@ public class GameRenderer {
glfwMakeContextCurrent(windowHandle);
glfwSwapInterval(1);
glfwShowWindow(windowHandle);
log.debug("Made window visible.");
GL.createCapabilities();
// GLUtil.setupDebugMessageCallback(System.out);
@ -90,9 +100,9 @@ public class GameRenderer {
glCullFace(GL_BACK);
log.debug("Initialized OpenGL context.");
chunkRenderer.setupShaderProgram();
this.chunkRenderer = new ChunkRenderer();
log.debug("Initialized chunk renderer.");
guiRenderer.setup();
this.guiRenderer = new GUIRenderer();
// TODO: More organized way to load textures for GUI.
try {
var crosshairTexture = new GUITexture("gui/crosshair.png");
@ -103,34 +113,13 @@ public class GameRenderer {
throw new RuntimeException(e);
}
log.debug("Initialized GUI renderer.");
updatePerspective();
this.modelRenderer = new ModelRenderer();
try {
playerModel = new Model("model/player_simple.obj", "model/simple_player.png");
} catch (IOException e) {
throw new RuntimeException(e);
}
public void setFullscreen(boolean fullscreen) {
if (windowHandle == 0) throw new IllegalStateException("Window not setup.");
long monitor = glfwGetPrimaryMonitor();
if (fullscreen) {
log.debug("Changing to fullscreen: {} x {}", primaryMonitorSettings.width(), primaryMonitorSettings.height());
glfwSetWindowMonitor(windowHandle, monitor, 0, 0, primaryMonitorSettings.width(), primaryMonitorSettings.height(), primaryMonitorSettings.refreshRate());
screenWidth = primaryMonitorSettings.width();
screenHeight = primaryMonitorSettings.height();
updatePerspective();
} else {
log.debug("Changing to windowed mode.");
screenWidth = 800;
screenHeight = 600;
int left = primaryMonitorSettings.width() / 2;
int top = primaryMonitorSettings.height() / 2;
glfwSetWindowMonitor(windowHandle, 0, left, top, screenWidth, screenHeight, primaryMonitorSettings.refreshRate());
updatePerspective();
}
this.fullscreen = fullscreen;
}
public void setSize(int width, int height) {
glfwSetWindowSize(windowHandle, width, height);
this.screenWidth = width;
this.screenHeight = height;
log.debug("Initialized model renderer.");
updatePerspective();
}
@ -144,12 +133,18 @@ public class GameRenderer {
}
/**
* Updates the rendering perspective used to render the game. Note: only
* call this after calling {@link ChunkRenderer#setupShaderProgram()}.
* Updates the rendering perspective used to render the game.
*/
private void updatePerspective() {
perspectiveTransform.setPerspective(fov, getAspectRatio(), Z_NEAR, Z_FAR);
chunkRenderer.setPerspective(perspectiveTransform);
float[] data = new float[16];
perspectiveTransform.get(data);
if (chunkRenderer != null) chunkRenderer.setPerspective(data);
if (modelRenderer != null) modelRenderer.setPerspective(data);
}
public Matrix4f getPerspectiveTransform() {
return perspectiveTransform;
}
public boolean windowShouldClose() {
@ -160,14 +155,20 @@ public class GameRenderer {
return camera;
}
public ChunkRenderer getChunkRenderer() {
return chunkRenderer;
}
public void draw() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
chunkRenderer.draw(camera, world.getChunkMeshesToDraw());
// Draw players.
modelRenderer.setView(camera.getViewTransformData());
playerModel.bind();
Matrix4f playerModelTransform = new Matrix4f();
for (var player : world.getPlayers()) {
playerModelTransform.identity().translate(player.getPosition());
modelRenderer.render(playerModel, playerModelTransform);
}
playerModel.unbind();
chunkRenderer.draw(camera, world);
guiRenderer.draw();
glfwSwapBuffers(windowHandle);
@ -175,8 +176,10 @@ public class GameRenderer {
}
public void freeWindow() {
guiRenderer.free();
chunkRenderer.free();
if (playerModel != null) playerModel.free();
if (modelRenderer != null) modelRenderer.free();
if (guiRenderer != null) guiRenderer.free();
if (chunkRenderer != null) chunkRenderer.free();
GL.destroy();
Callbacks.glfwFreeCallbacks(windowHandle);
glfwSetErrorCallback(null);

View File

@ -1,70 +0,0 @@
package nl.andrewl.aos2_client.render;
import org.joml.Matrix4f;
import static org.lwjgl.opengl.GL46.*;
public class Mesh {
private final int vboId;
private final int vaoId;
private final int eboId;
private int indexCount;
private final Matrix4f transform = new Matrix4f();
private final float[] transformData = new float[16];
public Mesh(MeshData initialData) {
this.vboId = glGenBuffers();
this.eboId = glGenBuffers();
this.vaoId = glGenVertexArrays();
load(initialData);
initVertexArrayAttributes();
}
public void load(MeshData data) {
indexCount = data.indexBuffer().limit();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, data.vertexBuffer(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.indexBuffer(), GL_STATIC_DRAW);
}
public Matrix4f getTransform() {
return transform;
}
public void updateTransform() {
transform.set(transformData);
}
public float[] getTransformData() {
return transformData;
}
/**
* Initializes this mesh's vertex array attribute settings.
*/
private void initVertexArrayAttributes() {
glBindVertexArray(vaoId);
// Vertex position floats.
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 9 * Float.BYTES, 0);
// Vertex color floats.
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, false, 9 * Float.BYTES, 3 * Float.BYTES);
// Vertex normal floats.
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, false, 9 * Float.BYTES, 6 * Float.BYTES);
}
public void draw() {
glBindVertexArray(vaoId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboId);
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);
}
public void free() {
glDeleteBuffers(vboId);
glDeleteBuffers(eboId);
glDeleteVertexArrays(vaoId);
}
}

View File

@ -1,6 +0,0 @@
package nl.andrewl.aos2_client.render;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
public record MeshData(FloatBuffer vertexBuffer, IntBuffer indexBuffer) {}

View File

@ -0,0 +1,53 @@
package nl.andrewl.aos2_client.render;
import nl.andrewl.aos2_client.Camera;
import nl.andrewl.aos2_client.render.model.Model;
import org.joml.Matrix4f;
import static org.lwjgl.opengl.GL46.*;
/**
* A renderer that handles rendering of textured models.
*/
public class ModelRenderer {
private final ShaderProgram shaderProgram;
private final int projectionUniform;
private final int viewUniform;
private final int modelUniform;
private final int textureSamplerUniform;
public ModelRenderer() {
shaderProgram = new ShaderProgram.Builder()
.withShader("shader/model/vertex.glsl", GL_VERTEX_SHADER)
.withShader("shader/model/fragment.glsl", GL_FRAGMENT_SHADER)
.build();
projectionUniform = shaderProgram.getUniform("projectionTransform");
viewUniform = shaderProgram.getUniform("viewTransform");
modelUniform = shaderProgram.getUniform("modelTransform");
textureSamplerUniform = shaderProgram.getUniform("textureSampler");
}
public void setPerspective(float[] data) {
shaderProgram.use();
glUniformMatrix4fv(projectionUniform, false, data);
shaderProgram.stopUsing();
}
public void setView(float[] data) {
shaderProgram.use();
glUniformMatrix4fv(viewUniform, false, data);
shaderProgram.stopUsing();
}
public void render(Model model, Matrix4f modelTransform) {
shaderProgram.use();
glUniformMatrix4fv(modelUniform, false, modelTransform.get(new float[16]));
glUniform1i(textureSamplerUniform, 0);
model.draw();
shaderProgram.stopUsing();
}
public void free() {
shaderProgram.free();
}
}

View File

@ -1,26 +0,0 @@
package nl.andrewl.aos2_client.render;
import org.joml.Vector3f;
import org.joml.Vector3i;
import org.lwjgl.BufferUtils;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
public class PlayerMeshGenerator {
private final FloatBuffer vertexBuffer;
private final IntBuffer indexBuffer;
private final Vector3i pos = new Vector3i();
private final Vector3f color = new Vector3f();
private final Vector3f norm = new Vector3f();
public PlayerMeshGenerator() {
vertexBuffer = BufferUtils.createFloatBuffer(1000);
indexBuffer = BufferUtils.createIntBuffer(100);
}
// public PlayerMesh generateMesh() {
//
// }
}

View File

@ -32,6 +32,10 @@ public class ShaderProgram {
glUseProgram(0);
}
public int getId() {
return id;
}
public int getUniform(String name) {
return glGetUniformLocation(id, name);
}

View File

@ -49,17 +49,16 @@ public class ChunkMesh {
* Generates and loads this chunk's mesh into the allocated OpenGL buffers.
*/
private void loadMesh(ChunkMeshGenerator meshGenerator) {
long start = System.nanoTime();
// long start = System.nanoTime();
var meshData = meshGenerator.generateMesh(chunk, world);
double dur = (System.nanoTime() - start) / 1_000_000.0;
// double dur = (System.nanoTime() - start) / 1_000_000.0;
this.indexCount = meshData.indexBuffer().limit();
// Print some debug information.
log.debug(
"Generated mesh for chunk ({}, {}, {}) in {} ms. {} vertices and {} indices.",
chunk.getPosition().x, chunk.getPosition().y, chunk.getPosition().z,
dur,
meshData.vertexBuffer().limit() / 9, indexCount
);
// log.debug(
// "Generated mesh for chunk ({}, {}, {}) in {} ms. {} vertices and {} indices.",
// chunk.getPosition().x, chunk.getPosition().y, chunk.getPosition().z,
// dur,
// meshData.vertexBuffer().limit() / 9, indexCount
// );
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, meshData.vertexBuffer(), GL_STATIC_DRAW);

View File

@ -7,7 +7,10 @@ import nl.andrewl.aos_core.model.World;
import org.joml.Matrix4f;
import org.joml.Vector3i;
import java.util.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import static org.lwjgl.opengl.GL46.*;
@ -18,17 +21,12 @@ import static org.lwjgl.opengl.GL46.*;
* be rendered each frame.
*/
public class ChunkRenderer {
private final ChunkMeshGenerator chunkMeshGenerator = new ChunkMeshGenerator();
private final Queue<Chunk> meshGenerationQueue = new ConcurrentLinkedQueue<>();
private final ShaderProgram shaderProgram;
private final int projectionTransformUniform;
private final int viewTransformUniform;
private final int chunkPositionUniform;
private ShaderProgram shaderProgram;
private int projectionTransformUniform;
private int viewTransformUniform;
private int chunkPositionUniform;
private final Map<Vector3i, ChunkMesh> chunkMeshes = new HashMap<>();
public void setupShaderProgram() {
public ChunkRenderer() {
this.shaderProgram = new ShaderProgram.Builder()
.withShader("shader/chunk/vertex.glsl", GL_VERTEX_SHADER)
.withShader("shader/chunk/fragment.glsl", GL_FRAGMENT_SHADER)
@ -38,39 +36,28 @@ public class ChunkRenderer {
this.viewTransformUniform = shaderProgram.getUniform("viewTransform");
this.chunkPositionUniform = shaderProgram.getUniform("chunkPosition");
int chunkSizeUniform = shaderProgram.getUniform("chunkSize");
// Set constant uniforms that don't change during runtime.
glUniform1i(chunkSizeUniform, Chunk.SIZE);
shaderProgram.stopUsing();
}
public void queueChunkMesh(Chunk chunk) {
meshGenerationQueue.add(chunk);
public void setPerspective(float[] data) {
shaderProgram.use();
glUniformMatrix4fv(projectionTransformUniform, false, data);
shaderProgram.stopUsing();
}
public void setPerspective(Matrix4f projectionTransform) {
glUniformMatrix4fv(projectionTransformUniform, false, projectionTransform.get(new float[16]));
}
public void draw(Camera cam, World world) {
while (!meshGenerationQueue.isEmpty()) {
Chunk chunk = meshGenerationQueue.remove();
ChunkMesh mesh = new ChunkMesh(chunk, world, chunkMeshGenerator);
ChunkMesh existingMesh = chunkMeshes.get(chunk.getPosition());
if (existingMesh != null) existingMesh.free();
chunkMeshes.put(chunk.getPosition(), mesh);
}
public void draw(Camera cam, Collection<ChunkMesh> chunkMeshes) {
shaderProgram.use();
glUniformMatrix4fv(viewTransformUniform, false, cam.getViewTransformData());
for (var mesh : chunkMeshes.values()) {
for (var mesh : chunkMeshes) {
glUniform3iv(chunkPositionUniform, mesh.getPositionData());
mesh.draw();
}
shaderProgram.stopUsing();
}
public void free() {
for (var mesh : chunkMeshes.values()) mesh.free();
chunkMeshes.clear();
meshGenerationQueue.clear();
shaderProgram.free();
}
}

View File

@ -14,20 +14,16 @@ import static org.lwjgl.opengl.GL46.*;
* Manages rendering of 2D GUI components like cross-hairs, inventory stuff, etc.
*/
public class GUIRenderer {
private int vaoId;
private int vboId;
private int vertexCount;
private ShaderProgram shaderProgram;
private int transformUniformLocation;
private final int vaoId;
private final int vboId;
private final int vertexCount;
private final ShaderProgram shaderProgram;
private final int transformUniformLocation;
private final List<GUITexture> guiTextures = new ArrayList<>();
public void addTexture(GUITexture texture) {
guiTextures.add(texture);
}
public void setup() {
public GUIRenderer() {
vaoId = glGenVertexArrays();
vboId = glGenBuffers();
FloatBuffer buffer = BufferUtils.createFloatBuffer(8);
@ -53,6 +49,10 @@ public class GUIRenderer {
shaderProgram.bindAttribute(0, "position");
}
public void addTexture(GUITexture texture) {
guiTextures.add(texture);
}
public void draw() {
shaderProgram.use();
glBindVertexArray(vaoId);

View File

@ -26,7 +26,7 @@ public class GUITexture {
textureId = glGenTextures();
glBindTexture(GL_TEXTURE_2D, textureId);
glPixelStorei(GL_UNPACK_ALIGNMENT, textureId);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
var buf = ImageUtils.decodePng(img);

View File

@ -0,0 +1,123 @@
package nl.andrewl.aos2_client.render.model;
import de.javagl.obj.Obj;
import de.javagl.obj.ObjData;
import de.javagl.obj.ObjReader;
import de.javagl.obj.ObjUtils;
import nl.andrewl.aos_core.ImageUtils;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;
import static org.lwjgl.opengl.GL46.*;
/**
* Represents a 3D model with a texture, which can be used to render one or
* more entities.
*/
public class Model {
private final int vaoId;
private final List<Integer> vboIds;
private final int eboId;
private final int indexCount;
private final int textureId;
public Model(String resource, String textureResource) throws IOException {
try (
var in = Model.class.getClassLoader().getResourceAsStream(resource);
var imageIn = Model.class.getClassLoader().getResourceAsStream(textureResource)
) {
if (in == null) throw new IOException("Could not load resource: " + resource);
if (imageIn == null) throw new IOException("Could not load texture image: " + textureResource);
Obj obj = ObjReader.read(in);
obj = ObjUtils.convertToRenderable(obj);
IntBuffer indices = ObjData.getFaceVertexIndices(obj, 3);
FloatBuffer vertices = ObjData.getVertices(obj);
FloatBuffer texCoords = ObjData.getTexCoords(obj, 2, true);
FloatBuffer normals = ObjData.getNormals(obj);
indexCount = indices.limit();
vboIds = new ArrayList<>(4);
vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
// Position data
int vboId = glGenBuffers();
vboIds.add(vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
// Normal data
vboId = glGenBuffers();
vboIds.add(vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, normals, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0);
// Texture data
vboId = glGenBuffers();
vboIds.add(vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, texCoords, GL_STATIC_DRAW);
glEnableVertexAttribArray(2); // Texture coordinates
glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, 0);
// Index data
eboId = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices, GL_STATIC_DRAW);
textureId = glGenTextures();
glBindTexture(GL_TEXTURE_2D, textureId);
BufferedImage img = ImageIO.read(imageIn);
int w = img.getWidth();
int h = img.getHeight();
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
ByteBuffer imageBuffer = ImageUtils.decodePng(img);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageBuffer);
}
}
public void bind() {
glBindVertexArray(vaoId);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboId);
}
public void draw() {
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);
}
public void unbind() {
glBindVertexArray(0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glBindTexture(GL_TEXTURE_2D, 0);
}
public void free() {
glDeleteTextures(textureId);
glDeleteBuffers(eboId);
for (var vboId : vboIds) {
glDeleteBuffers(vboId);
}
glDeleteVertexArrays(vaoId);
}
}

View File

@ -0,0 +1,13 @@
# Blender MTL File: 'player_simple.blend'
# Material Count: 1
newmtl Material.001
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd simple_player.png

View File

@ -0,0 +1,604 @@
# Blender v2.82 (sub 7) OBJ File: 'player_simple.blend'
# www.blender.org
mtllib player_simple.mtl
o Cube
v 0.307055 1.384430 -0.307055
v 0.159554 0.004036 -0.159554
v 0.307055 1.384430 0.307055
v 0.159554 0.004036 0.159554
v -0.307055 1.384430 -0.307055
v -0.159554 0.004036 -0.159554
v -0.307055 1.384430 0.307055
v -0.159554 0.004036 0.159554
v 0.000000 0.004036 -0.221565
v 0.000000 1.384430 0.426394
v 0.000000 0.004036 0.221565
v 0.000000 1.384430 -0.426394
v -0.221565 0.004036 0.000000
v 0.426394 1.384430 0.000000
v -0.426394 1.384430 0.000000
v 0.221565 0.004036 0.000000
v 0.000000 0.004036 0.000000
v 0.125637 1.521320 -0.125637
v 0.355691 0.694233 -0.355691
v -0.355691 0.694233 0.355691
v 0.355691 0.694233 0.355691
v -0.355691 0.694233 -0.355691
v 0.000000 0.694233 -0.493931
v 0.000000 0.694233 0.493931
v 0.493931 0.694233 -0.000000
v -0.493931 0.694233 -0.000000
v 0.342552 0.349135 -0.342552
v 0.342552 0.349135 0.342552
v -0.342552 0.349135 -0.342552
v 0.000000 0.349135 -0.475686
v 0.000000 0.349135 0.475686
v 0.475686 0.349135 -0.000000
v -0.475686 0.349135 -0.000000
v -0.342552 0.349135 0.342552
v -0.342552 1.039332 0.342552
v 0.342552 1.039332 -0.342552
v 0.342552 1.039332 0.342552
v -0.342552 1.039332 -0.342552
v 0.000000 1.039332 -0.475686
v 0.000000 1.039332 0.475686
v 0.475686 1.039332 -0.000000
v -0.475686 1.039332 -0.000000
v 0.324796 0.176514 -0.324796
v 0.324796 0.176514 0.324796
v -0.324796 0.176514 -0.324796
v 0.000000 0.176514 -0.451029
v 0.000000 0.176514 0.451029
v 0.451029 0.176514 -0.000000
v -0.451029 0.176514 -0.000000
v -0.324796 0.176514 0.324796
v 0.274970 0.090275 -0.274970
v 0.274970 0.090275 0.274970
v -0.274970 0.090275 -0.274970
v 0.000000 0.090275 -0.381838
v 0.000000 0.090275 0.381838
v 0.381838 0.090275 -0.000000
v -0.381838 0.090275 -0.000000
v -0.274970 0.090275 0.274970
v 0.230376 1.470570 -0.230376
v 0.230376 1.470570 0.230376
v -0.230376 1.470570 -0.230376
v -0.230376 1.470570 0.230376
v 0.000000 1.470570 0.319913
v 0.000000 1.470570 -0.319913
v 0.319913 1.470570 0.000000
v -0.319913 1.470570 0.000000
v 0.125637 1.556870 -0.125637
v 0.125637 1.521320 0.125637
v -0.125637 1.521320 -0.125637
v -0.125637 1.521320 0.125637
v 0.000000 1.521320 0.174467
v 0.000000 1.521320 -0.174467
v 0.174467 1.521320 0.000000
v -0.174467 1.521320 0.000000
v 0.169463 1.610223 -0.169463
v 0.125637 1.556870 0.125637
v -0.125637 1.556870 -0.125637
v -0.125637 1.556870 0.125637
v 0.000000 1.556870 0.174467
v 0.000000 1.556870 -0.174467
v 0.174467 1.556870 0.000000
v -0.174467 1.556870 0.000000
v 0.210794 1.686314 -0.210794
v 0.169463 1.610223 0.169463
v -0.169463 1.610223 -0.169463
v -0.169463 1.610223 0.169463
v 0.000000 1.610223 0.235325
v 0.000000 1.610223 -0.235325
v 0.235325 1.610223 0.000000
v -0.235325 1.610223 0.000000
v 0.223284 1.833569 -0.223284
v 0.210794 1.686314 0.210794
v -0.210794 1.686314 -0.210794
v -0.210794 1.686314 0.210794
v 0.000000 1.686314 0.292720
v 0.000000 1.686314 -0.292720
v 0.292720 1.686314 0.000000
v -0.292720 1.686314 0.000000
v 0.211578 1.977176 -0.211578
v 0.223284 1.833569 0.223284
v -0.223284 1.833569 -0.223284
v -0.223284 1.833569 0.223284
v 0.000000 1.833569 0.310064
v 0.000000 1.833569 -0.310064
v 0.310064 1.833569 0.000000
v -0.310064 1.833569 0.000000
v 0.172806 2.077383 -0.172806
v 0.211578 1.977176 0.211578
v -0.211578 1.977176 -0.211578
v -0.211578 1.977176 0.211578
v 0.000000 1.977176 0.293809
v 0.000000 1.977176 -0.293809
v 0.293809 1.977176 0.000000
v -0.293809 1.977176 0.000000
v 0.067534 2.131719 -0.067534
v 0.172806 2.077383 0.172806
v -0.172806 2.077383 -0.172806
v -0.172806 2.077383 0.172806
v 0.000000 2.077383 0.239968
v 0.000000 2.077383 -0.239968
v 0.239968 2.077383 0.000000
v -0.239968 2.077383 0.000000
v 0.067534 2.131719 0.067534
v -0.067534 2.131719 -0.067534
v -0.067534 2.131719 0.067534
v 0.000000 2.131719 0.093781
v 0.000000 2.131719 -0.093781
v 0.093781 2.131719 0.000000
v -0.093781 2.131719 0.000000
v 0.000000 2.131719 0.000000
vt 0.270204 0.781152
vt 0.118734 0.781152
vt 0.138824 0.736777
vt 0.252468 0.736777
vt 0.757867 0.465320
vt 0.690242 0.473338
vt 0.690321 0.364703
vt 0.757955 0.344126
vt 0.757867 0.142172
vt 0.690242 0.150190
vt 0.690321 0.041556
vt 0.757955 0.020979
vt 0.210691 0.204882
vt 0.247595 0.112545
vt 0.305645 0.164231
vt 0.305645 0.240769
vt 0.499666 0.142172
vt 0.432041 0.150190
vt 0.432120 0.041555
vt 0.499754 0.020979
vt 0.499666 0.465320
vt 0.432041 0.473338
vt 0.432120 0.364703
vt 0.499754 0.344126
vt 0.499754 0.629641
vt 0.432120 0.620631
vt 0.173786 0.297218
vt 0.252494 0.297218
vt 0.757955 0.629641
vt 0.690321 0.620631
vt 0.016446 0.672518
vt 0.016446 0.525224
vt 0.062080 0.544760
vt 0.062080 0.655271
vt 0.381919 0.534391
vt 0.381919 0.681685
vt 0.336285 0.662149
vt 0.336285 0.551638
vt 0.115736 0.245532
vt 0.115736 0.168995
vt 0.499754 0.306493
vt 0.432120 0.297484
vt 0.168888 0.112545
vt 0.757955 0.306493
vt 0.690321 0.297484
vt 0.893270 0.306425
vt 0.825604 0.309807
vt 0.825512 0.139183
vt 0.893182 0.142104
vt 0.635069 0.306425
vt 0.567403 0.309807
vt 0.567311 0.139183
vt 0.634981 0.142104
vt 0.893270 0.629572
vt 0.825604 0.632954
vt 0.825512 0.462330
vt 0.893182 0.465251
vt 0.635069 0.629572
vt 0.567403 0.632954
vt 0.567311 0.462330
vt 0.634981 0.465251
vt 0.567403 0.336488
vt 0.635069 0.344058
vt 0.567403 0.013341
vt 0.635069 0.020910
vt 0.825604 0.013341
vt 0.893270 0.020910
vt 0.825604 0.336488
vt 0.893270 0.344058
vt 0.927041 0.469228
vt 0.927124 0.354316
vt 0.927041 0.146080
vt 0.927124 0.031169
vt 0.668840 0.146080
vt 0.668923 0.031169
vt 0.668840 0.469228
vt 0.668923 0.354316
vt 0.668923 0.625032
vt 0.927124 0.625032
vt 0.668923 0.301884
vt 0.927124 0.301884
vt 0.282733 0.364011
vt 0.295787 0.392847
vt 0.135566 0.392847
vt 0.147091 0.364011
vt 0.138649 0.045752
vt 0.125594 0.016917
vt 0.285815 0.016917
vt 0.274291 0.045752
vt 0.374332 0.134826
vt 0.403985 0.122132
vt 0.403985 0.277935
vt 0.374332 0.266728
vt 0.047049 0.274937
vt 0.017396 0.287632
vt 0.017397 0.131828
vt 0.047049 0.143035
vt 0.145897 0.470132
vt 0.259541 0.470132
vt 0.232099 0.530746
vt 0.170123 0.530746
vt 0.124413 0.631713
vt 0.166266 0.676163
vt 0.228242 0.676163
vt 0.273952 0.635464
vt 0.124413 0.571445
vt 0.128161 0.425756
vt 0.279631 0.425756
vt 0.405682 0.414476
vt 0.405650 0.458926
vt 0.398680 0.458930
vt 0.398712 0.414480
vt 0.405682 0.528622
vt 0.405650 0.573072
vt 0.398680 0.573076
vt 0.398712 0.528626
vt 0.405682 0.519194
vt 0.398712 0.519197
vt 0.405682 0.633340
vt 0.398712 0.633344
vt 0.273952 0.575196
vt 0.907386 0.807523
vt 0.907386 0.747255
vt 0.933468 0.736089
vt 0.933468 0.817380
vt 0.799699 0.706556
vt 0.757846 0.751006
vt 0.731765 0.741148
vt 0.788217 0.681193
vt 0.757846 0.811274
vt 0.803557 0.851973
vt 0.793420 0.877335
vt 0.731765 0.822439
vt 0.865533 0.851973
vt 0.877016 0.877335
vt 0.413282 0.458926
vt 0.413314 0.519194
vt 0.406344 0.519197
vt 0.406312 0.458930
vt 0.421034 0.458926
vt 0.421066 0.519194
vt 0.414097 0.519197
vt 0.414065 0.458930
vt 0.421066 0.414476
vt 0.414097 0.414480
vt 0.413314 0.414476
vt 0.406344 0.414480
vt 0.783860 0.901254
vt 0.707168 0.832969
vt 0.887844 0.901254
vt 0.707168 0.731852
vt 0.871813 0.681193
vt 0.881373 0.657274
vt 0.958065 0.725559
vt 0.861676 0.706556
vt 0.059593 0.887311
vt 0.059648 0.988429
vt 0.030770 0.991625
vt 0.030712 0.884517
vt 0.997431 0.015588
vt 0.997377 0.090166
vt 0.968496 0.087372
vt 0.968554 0.008375
vt 0.997431 0.421298
vt 0.997377 0.495876
vt 0.968496 0.493081
vt 0.968554 0.414084
vt 0.997431 0.191283
vt 0.968554 0.194480
vt 0.777388 0.657274
vt 0.958065 0.826676
vt 0.940352 0.495728
vt 0.940407 0.420873
vt 0.940407 0.191512
vt 0.940352 0.090019
vt 0.968554 0.600190
vt 0.940407 0.597221
vt 0.030770 0.805520
vt 0.002569 0.887164
vt 0.002623 0.812308
vt 0.997377 0.293021
vt 0.997431 0.394138
vt 0.968554 0.397335
vt 0.968496 0.290226
vt 0.997431 0.218443
vt 0.968554 0.211229
vt 0.059648 0.812733
vt 0.997431 0.596993
vt 0.503196 0.657315
vt 0.607567 0.657315
vt 0.598599 0.679753
vt 0.513354 0.679753
vt 0.684545 0.725854
vt 0.684545 0.827347
vt 0.661471 0.818627
vt 0.661471 0.735732
vt 0.614063 0.902203
vt 0.603905 0.879765
vt 0.940407 0.015163
vt 0.002623 0.988657
vt 0.940407 0.394367
vt 0.940352 0.292873
vt 0.940407 0.218018
vt 0.576323 0.818842
vt 0.598820 0.794949
vt 0.598820 0.762553
vt 0.574250 0.740676
vt 0.455788 0.823786
vt 0.455788 0.740891
vt 0.518438 0.764569
vt 0.518438 0.796965
vt 0.518660 0.879765
vt 0.543009 0.818842
vt 0.509692 0.902203
vt 0.432714 0.833664
vt 0.432714 0.732171
vt 0.558629 0.779759
vt 0.540936 0.740676
vn -0.6110 0.7552 0.2374
vn -0.3591 0.1320 0.9239
vn -0.9239 0.1320 -0.3591
vn 0.0000 -1.0000 0.0000
vn 0.9239 0.1320 0.3591
vn 0.3591 0.1320 -0.9239
vn -0.3591 0.1320 -0.9239
vn 0.3591 0.1320 0.9239
vn 0.2374 0.7552 0.6110
vn -0.2374 0.7552 -0.6110
vn 0.9239 0.1320 -0.3591
vn -0.9239 0.1320 0.3591
vn -0.2374 0.7552 0.6110
vn -0.9309 -0.0492 0.3618
vn 0.9309 -0.0492 -0.3618
vn 0.3618 -0.0492 0.9309
vn -0.3618 -0.0492 -0.9309
vn 0.3618 -0.0492 -0.9309
vn 0.9309 -0.0492 0.3618
vn -0.9309 -0.0492 -0.3618
vn -0.3618 -0.0492 0.9309
vn -0.3591 -0.1320 0.9239
vn -0.9239 -0.1320 -0.3591
vn 0.9239 -0.1320 0.3591
vn 0.3591 -0.1320 -0.9239
vn -0.3591 -0.1320 -0.9239
vn 0.3591 -0.1320 0.9239
vn 0.9239 -0.1320 -0.3591
vn -0.9239 -0.1320 0.3591
vn -0.9309 0.0492 0.3618
vn 0.9309 0.0492 -0.3618
vn 0.3618 0.0492 0.9309
vn -0.3618 0.0492 -0.9309
vn 0.3618 0.0492 -0.9309
vn 0.9309 0.0492 0.3618
vn -0.9309 0.0492 -0.3618
vn -0.3618 0.0492 0.9309
vn -0.7464 -0.5989 0.2901
vn 0.7464 -0.5989 -0.2901
vn 0.2901 -0.5989 0.7464
vn -0.2901 -0.5989 -0.7464
vn 0.2901 -0.5989 -0.7464
vn 0.7464 -0.5989 0.2901
vn -0.7464 -0.5989 -0.2901
vn -0.2901 -0.5989 0.7464
vn -0.1811 -0.8660 0.4660
vn -0.4660 -0.8660 -0.1811
vn 0.4660 -0.8660 0.1811
vn 0.1811 -0.8660 -0.4660
vn -0.1811 -0.8660 -0.4660
vn 0.1811 -0.8660 0.4660
vn 0.4660 -0.8660 -0.1811
vn -0.4660 -0.8660 0.1811
vn 0.3268 0.9365 -0.1270
vn -0.1270 0.9365 0.3268
vn -0.3268 0.9365 -0.1270
vn 0.1270 0.9365 0.3268
vn -0.6110 0.7552 -0.2374
vn 0.6110 0.7552 0.2374
vn 0.6110 0.7552 -0.2374
vn 0.2374 0.7552 -0.6110
vn -0.3623 0.0000 0.9321
vn -0.9321 0.0000 -0.3623
vn 0.3623 0.0000 0.9321
vn -0.9321 0.0000 0.3623
vn -0.1270 0.9365 -0.3268
vn 0.1270 0.9365 -0.3268
vn 0.3268 0.9365 0.1270
vn -0.3268 0.9365 0.1270
vn -0.6386 -0.7284 0.2482
vn 0.6386 -0.7284 0.2482
vn 0.2482 -0.7284 -0.6386
vn -0.2482 -0.7284 -0.6386
vn 0.9321 0.0000 -0.3623
vn -0.3623 0.0000 -0.9321
vn 0.3623 0.0000 -0.9321
vn 0.9321 0.0000 0.3623
vn 0.2963 -0.5751 -0.7625
vn -0.2963 -0.5751 -0.7625
vn 0.7625 -0.5751 -0.2963
vn -0.2963 -0.5751 0.7625
vn 0.2482 -0.7284 0.6386
vn -0.6386 -0.7284 -0.2482
vn -0.2482 -0.7284 0.6386
vn 0.6386 -0.7284 -0.2482
vn 0.9265 -0.1091 -0.3601
vn -0.3601 -0.1091 0.9265
vn -0.9265 -0.1091 -0.3601
vn 0.3601 -0.1091 0.9265
vn 0.7625 -0.5751 0.2963
vn -0.7625 -0.5751 0.2963
vn 0.2963 -0.5751 0.7625
vn -0.7625 -0.5751 -0.2963
vn -0.9269 0.1049 -0.3603
vn 0.3603 0.1049 0.9269
vn -0.9269 0.1049 0.3603
vn 0.9269 0.1049 0.3603
vn -0.3601 -0.1091 -0.9265
vn 0.3601 -0.1091 -0.9265
vn 0.9265 -0.1091 0.3601
vn -0.9265 -0.1091 0.3601
vn 0.8334 0.4478 0.3239
vn 0.3239 0.4478 -0.8334
vn -0.3239 0.4478 -0.8334
vn 0.8334 0.4478 -0.3239
vn -0.3603 0.1049 0.9269
vn 0.9269 0.1049 -0.3603
vn -0.3603 0.1049 -0.9269
vn 0.3603 0.1049 -0.9269
vn -0.1342 0.9289 -0.3452
vn 0.3452 0.9289 -0.1342
vn -0.1342 0.9289 0.3452
vn -0.3452 0.9289 -0.1342
vn -0.8334 0.4478 0.3239
vn 0.3239 0.4478 0.8334
vn -0.8334 0.4478 -0.3239
vn -0.3239 0.4478 0.8334
vn 0.0000 1.0000 0.0000
vn 0.1342 0.9289 -0.3452
vn 0.3452 0.9289 0.1342
vn -0.3452 0.9289 0.1342
vn 0.1342 0.9289 0.3452
usemtl Material.001
s off
f 15/1/1 7/2/1 62/3/1 66/4/1
f 40/5/2 10/6/2 7/7/2 35/8/2
f 42/9/3 15/10/3 5/11/3 38/12/3
f 17/13/4 16/14/4 4/15/4 11/16/4
f 41/17/5 14/18/5 3/19/5 37/20/5
f 39/21/6 12/22/6 1/23/6 36/24/6
f 38/25/7 5/26/7 12/22/7 39/21/7
f 13/27/4 17/13/4 11/16/4 8/28/4
f 37/29/8 3/30/8 10/6/8 40/5/8
f 10/31/9 3/32/9 60/33/9 63/34/9
f 12/35/10 5/36/10 61/37/10 64/38/10
f 6/39/4 9/40/4 17/13/4 13/27/4
f 36/41/11 1/42/11 14/18/11 41/17/11
f 9/40/4 2/43/4 16/14/4 17/13/4
f 35/44/12 7/45/12 15/10/12 42/9/12
f 7/2/13 10/31/13 63/34/13 62/3/13
f 34/46/14 20/47/14 26/48/14 33/49/14
f 27/50/15 19/51/15 25/52/15 32/53/15
f 28/54/16 21/55/16 24/56/16 31/57/16
f 29/58/17 22/59/17 23/60/17 30/61/17
f 30/61/18 23/60/18 19/62/18 27/63/18
f 32/53/19 25/52/19 21/64/19 28/65/19
f 33/49/20 26/48/20 22/66/20 29/67/20
f 31/57/21 24/56/21 20/68/21 34/69/21
f 47/70/22 31/57/22 34/69/22 50/71/22
f 49/72/23 33/49/23 29/67/23 45/73/23
f 48/74/24 32/53/24 28/65/24 44/75/24
f 46/76/25 30/61/25 27/63/25 43/77/25
f 45/78/26 29/58/26 30/61/26 46/76/26
f 44/79/27 28/54/27 31/57/27 47/70/27
f 43/80/28 27/50/28 32/53/28 48/74/28
f 50/81/29 34/46/29 33/49/29 49/72/29
f 20/47/30 35/44/30 42/9/30 26/48/30
f 19/51/31 36/41/31 41/17/31 25/52/31
f 21/55/32 37/29/32 40/5/32 24/56/32
f 22/59/33 38/25/33 39/21/33 23/60/33
f 23/60/34 39/21/34 36/24/34 19/62/34
f 25/52/35 41/17/35 37/20/35 21/64/35
f 26/48/36 42/9/36 38/12/36 22/66/36
f 24/56/37 40/5/37 35/8/37 20/68/37
f 58/82/38 50/83/38 49/84/38 57/85/38
f 51/86/39 43/87/39 48/88/39 56/89/39
f 52/90/40 44/91/40 47/92/40 55/93/40
f 53/94/41 45/95/41 46/96/41 54/97/41
f 54/97/42 46/96/42 43/87/42 51/86/42
f 56/89/43 48/88/43 44/91/43 52/90/43
f 57/85/44 49/84/44 45/95/44 53/94/44
f 55/93/45 47/92/45 50/83/45 58/82/45
f 11/16/46 55/93/46 58/82/46 8/28/46
f 13/27/47 57/85/47 53/94/47 6/39/47
f 16/14/48 56/89/48 52/90/48 4/15/48
f 9/40/49 54/97/49 51/86/49 2/43/49
f 6/39/50 53/94/50 54/97/50 9/40/50
f 4/15/51 52/90/51 55/93/51 11/16/51
f 2/43/52 51/86/52 56/89/52 16/14/52
f 8/28/53 58/82/53 57/85/53 13/27/53
f 65/98/54 59/99/54 18/100/54 73/101/54
f 62/3/55 63/34/55 71/102/55 70/103/55
f 61/37/56 66/4/56 74/104/56 69/105/56
f 63/34/57 60/33/57 68/106/57 71/102/57
f 5/36/58 15/1/58 66/4/58 61/37/58
f 3/32/59 14/107/59 65/98/59 60/33/59
f 14/107/60 1/108/60 59/99/60 65/98/60
f 1/108/61 12/35/61 64/38/61 59/99/61
f 70/109/62 71/110/62 79/111/62 78/112/62
f 69/113/63 74/114/63 82/115/63 77/116/63
f 71/110/64 68/117/64 76/118/64 79/111/64
f 74/114/65 70/119/65 78/120/65 82/115/65
f 64/38/66 61/37/66 69/105/66 72/121/66
f 59/99/67 64/38/67 72/121/67 18/100/67
f 60/33/68 65/98/68 73/101/68 68/106/68
f 66/4/69 62/3/69 70/103/69 74/104/69
f 82/122/70 78/123/70 86/124/70 90/125/70
f 76/126/71 81/127/71 89/128/71 84/129/71
f 67/130/72 80/131/72 88/132/72 75/133/72
f 80/131/73 77/134/73 85/135/73 88/132/73
f 73/136/74 18/137/74 67/138/74 81/139/74
f 72/140/75 69/141/75 77/142/75 80/143/75
f 18/144/76 72/140/76 80/143/76 67/145/76
f 68/146/77 73/136/77 81/139/77 76/147/77
f 75/133/78 88/132/78 96/148/78 83/149/78
f 88/132/79 85/135/79 93/150/79 96/148/79
f 89/128/80 75/133/80 83/149/80 97/151/80
f 86/124/81 87/152/81 95/153/81 94/154/81
f 79/155/82 76/126/82 84/129/82 87/152/82
f 77/134/83 82/122/83 90/125/83 85/135/83
f 78/123/84 79/155/84 87/152/84 86/124/84
f 81/127/85 67/130/85 75/133/85 89/128/85
f 97/156/86 83/157/86 91/158/86 105/159/86
f 94/160/87 95/161/87 103/162/87 102/163/87
f 93/164/88 98/165/88 106/166/88 101/167/88
f 95/161/89 92/168/89 100/169/89 103/162/89
f 84/129/90 89/128/90 97/151/90 92/170/90
f 90/125/91 86/124/91 94/154/91 98/171/91
f 87/152/92 84/129/92 92/170/92 95/153/92
f 85/135/93 90/125/93 98/171/93 93/150/93
f 101/167/94 106/166/94 114/172/94 109/173/94
f 103/162/95 100/169/95 108/174/95 111/175/95
f 106/166/96 102/176/96 110/177/96 114/172/96
f 100/178/97 105/159/97 113/179/97 108/180/97
f 96/181/98 93/182/98 101/183/98 104/184/98
f 83/185/99 96/181/99 104/184/99 91/186/99
f 92/187/100 97/156/100 105/159/100 100/178/100
f 98/165/101 94/188/101 102/176/101 106/166/101
f 108/189/102 113/190/102 121/191/102 116/192/102
f 99/193/103 112/194/103 120/195/103 107/196/103
f 112/194/104 109/197/104 117/198/104 120/195/104
f 113/190/105 99/193/105 107/196/105 121/191/105
f 102/163/106 103/162/106 111/175/106 110/199/106
f 105/159/107 91/158/107 99/200/107 113/179/107
f 104/184/108 101/183/108 109/201/108 112/202/108
f 91/186/109 104/184/109 112/202/109 99/203/109
f 120/195/110 117/198/110 124/204/110 127/205/110
f 121/191/111 107/196/111 115/206/111 128/207/111
f 118/208/112 119/209/112 126/210/112 125/211/112
f 117/198/113 122/212/113 129/213/113 124/204/113
f 114/214/114 110/215/114 118/208/114 122/212/114
f 111/216/115 108/189/115 116/192/115 119/209/115
f 109/197/116 114/214/116 122/212/116 117/198/116
f 110/215/117 111/216/117 119/209/117 118/208/117
f 130/217/118 129/213/118 125/211/118 126/210/118
f 128/207/118 130/217/118 126/210/118 123/218/118
f 115/206/118 127/205/118 130/217/118 128/207/118
f 127/205/118 124/204/118 129/213/118 130/217/118
f 107/196/119 120/195/119 127/205/119 115/206/119
f 116/192/120 121/191/120 128/207/120 123/218/120
f 122/212/121 118/208/121 125/211/121 129/213/121
f 119/209/122 116/192/122 123/218/122 126/210/122

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -0,0 +1,20 @@
#version 460 core
in vec2 textureCoords;
in vec3 vertexNormal;
out vec4 fragmentColor;
uniform sampler2D textureSampler;
void main() {
vec4 baseColor = texture(textureSampler, textureCoords);
vec3 lightDirection = normalize(vec3(0.5, -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);
vec3 diffuseComponent = max(dot(vertexNormal * -1, lightDirection), 0.0) * lightColor;
// TODO: Add shading based on light.
// fragmentColor = vec4((ambientComponent + diffuseComponent), 1.0) * baseColor;
fragmentColor = baseColor;
}

View File

@ -0,0 +1,18 @@
#version 460 core
layout (location = 0) in vec3 vertexPositionIn;
layout (location = 1) in vec3 vertexNormalIn;
layout (location = 2) in vec2 textureCoordsIn;
uniform mat4 projectionTransform;
uniform mat4 viewTransform;
uniform mat4 modelTransform;
out vec2 textureCoords;
out vec3 vertexNormal;
void main() {
gl_Position = projectionTransform * viewTransform * modelTransform * vec4(vertexPositionIn, 1.0);
vertexNormal = vec3(modelTransform * vec4(vertexNormalIn, 1.0));
textureCoords = textureCoordsIn;
}

View File

@ -25,4 +25,14 @@ public class ImageUtils {
buf.flip();
return buf;
}
public static BufferedImage rotateClockwise90(BufferedImage src) {
int w = src.getWidth();
int h = src.getHeight();
BufferedImage dest = new BufferedImage(h, w, src.getType());
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
dest.setRGB(y, w - x - 1, src.getRGB(x, y));
return dest;
}
}

View File

@ -1,7 +1,6 @@
package nl.andrewl.aos_core.model;
import net.openhft.hashing.LongHashFunction;
import org.joml.Vector3f;
import org.joml.Vector3i;
import java.util.Random;
@ -115,6 +114,11 @@ public class Chunk {
return sb.toString();
}
@Override
public int hashCode() {
return position.hashCode();
}
public long blockHash() {
return LongHashFunction.xx3(0).hashBytes(blocks);
}

View File

@ -21,4 +21,12 @@ public record PlayerJoinMessage(
player.getOrientation().x, player.getOrientation().y
);
}
public Player toPlayer() {
Player p = new Player(id, username);
p.getPosition().set(px, py, pz);
p.getVelocity().set(vx, vy, vz);
p.getOrientation().set(ox, oy);
return p;
}
}

View File

@ -35,7 +35,6 @@ public class UdpReceiver implements Runnable {
handler.handle(msg, packet);
} catch (SocketException e) {
if (e.getMessage().equals("Socket closed")) {
System.out.println("Socket closed!");
break;
}
e.printStackTrace();

View File

@ -28,4 +28,12 @@ public record ChunkUpdateMessage(
world.getBlockAt(worldPos.x, worldPos.y, worldPos.z)
);
}
public Vector3i getChunkPos() {
return new Vector3i(cx, cy, cz);
}
public Vector3i getLocalPos() {
return new Vector3i(lx, ly, lz);
}
}

View File

@ -1,5 +1,6 @@
package nl.andrewl.aos_core.net.udp;
import nl.andrewl.aos_core.model.Player;
import nl.andrewl.record_net.Message;
/**
@ -12,4 +13,11 @@ public record PlayerUpdateMessage(
float vx, float vy, float vz,
float ox, float oy,
boolean crouching
) implements Message {}
) implements Message {
public void apply(Player p) {
p.getPosition().set(px, py, pz);
p.getVelocity().set(vx, vy, vz);
p.getOrientation().set(ox, oy);
}
}

View File

@ -91,6 +91,13 @@ public class ClientCommunicationHandler {
log.debug("Sent connect accept message.");
sendTcpMessage(new WorldInfoMessage(server.getWorld()));
// Send join info for all players that are already connected.
for (var player : server.getPlayerManager().getPlayers()) {
if (player.getId() != this.player.getId()) {
sendTcpMessage(new PlayerJoinMessage(player));
}
}
// Send chunk data.
for (var chunk : server.getWorld().getChunkMap().values()) {
sendTcpMessage(new ChunkDataMessage(chunk));
}