Added ability to render mutiple players.
This commit is contained in:
parent
6cf5b599d0
commit
833ca720f1
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
screenWidth = primaryMonitorSettings.width();
|
||||
screenHeight = primaryMonitorSettings.height();
|
||||
windowHandle = glfwCreateWindow(screenWidth, screenHeight, "Ace of Shades 2", monitorId, 0);
|
||||
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);
|
||||
glfwSetInputMode(windowHandle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
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();
|
||||
}
|
||||
|
||||
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.modelRenderer = new ModelRenderer();
|
||||
try {
|
||||
playerModel = new Model("model/player_simple.obj", "model/simple_player.png");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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) {}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
//
|
||||
// }
|
||||
}
|
|
@ -32,6 +32,10 @@ public class ShaderProgram {
|
|||
glUseProgram(0);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getUniform(String name) {
|
||||
return glGetUniformLocation(id, name);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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 |
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -16,7 +16,7 @@ public class ImageUtils {
|
|||
// ARGB format to -> RGBA
|
||||
for( int h = 0; h < height; h++ )
|
||||
for( int w = 0; w < width; w++ ) {
|
||||
int argb = image.getRGB( w, h );
|
||||
int argb = image.getRGB(w, h);
|
||||
buf.put( (byte) ( 0xFF & ( argb >> 16 ) ) );
|
||||
buf.put( (byte) ( 0xFF & ( argb >> 8 ) ) );
|
||||
buf.put( (byte) ( 0xFF & ( argb ) ) );
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue