Added held block, and cleaned up object rendering.

This commit is contained in:
Andrew Lalis 2022-07-18 15:35:19 +02:00
parent 8bd88b849c
commit dc092e3b8f
24 changed files with 826 additions and 247 deletions

View File

@ -48,10 +48,14 @@ public class Camera {
} }
public void setToPlayer(Player p) { public void setToPlayer(Player p) {
position.set(p.getPosition()); position.set(p.getEyePosition());
velocity.set(p.getVelocity()); velocity.set(p.getVelocity());
} }
public void setOrientationToPlayer(Player p) {
orientation.set(p.getOrientation());
}
public Matrix4f getViewTransform() { public Matrix4f getViewTransform() {
return viewTransform; return viewTransform;
} }

View File

@ -29,7 +29,7 @@ public class Client implements Runnable {
private final ClientConfig config; private final ClientConfig config;
private final CommunicationHandler communicationHandler; private final CommunicationHandler communicationHandler;
private final InputHandler inputHandler; private final InputHandler inputHandler;
private final GameRenderer gameRenderer; private GameRenderer gameRenderer;
private final ClientWorld world; private final ClientWorld world;
private ClientPlayer player; private ClientPlayer player;
@ -39,7 +39,6 @@ public class Client implements Runnable {
this.communicationHandler = new CommunicationHandler(this); this.communicationHandler = new CommunicationHandler(this);
this.inputHandler = new InputHandler(this, communicationHandler); this.inputHandler = new InputHandler(this, communicationHandler);
this.world = new ClientWorld(); this.world = new ClientWorld();
this.gameRenderer = new GameRenderer(config.display, world);
} }
public ClientConfig getConfig() { public ClientConfig getConfig() {
@ -68,6 +67,7 @@ public class Client implements Runnable {
return; return;
} }
gameRenderer = new GameRenderer(config.display, player, world);
gameRenderer.setupWindow( gameRenderer.setupWindow(
new PlayerViewCursorCallback(config.input, this, gameRenderer.getCamera(), communicationHandler), new PlayerViewCursorCallback(config.input, this, gameRenderer.getCamera(), communicationHandler),
new PlayerInputKeyCallback(inputHandler), new PlayerInputKeyCallback(inputHandler),
@ -103,22 +103,19 @@ public class Client implements Runnable {
if (playerUpdate.clientId() == player.getId()) { if (playerUpdate.clientId() == player.getId()) {
player.getPosition().set(playerUpdate.px(), playerUpdate.py(), playerUpdate.pz()); player.getPosition().set(playerUpdate.px(), playerUpdate.py(), playerUpdate.pz());
player.getVelocity().set(playerUpdate.vx(), playerUpdate.vy(), playerUpdate.vz()); player.getVelocity().set(playerUpdate.vx(), playerUpdate.vy(), playerUpdate.vz());
player.setCrouching(playerUpdate.crouching());
if (gameRenderer != null) {
gameRenderer.getCamera().setToPlayer(player); gameRenderer.getCamera().setToPlayer(player);
// TODO: Add getEyeHeight() and isCrouching() to main Player class. }
float eyeHeight = playerUpdate.crouching() ? 1.3f : 1.7f;
gameRenderer.getCamera().getPosition().y += eyeHeight;
} else { } else {
world.playerUpdated(playerUpdate); world.playerUpdated(playerUpdate);
} }
} else if (msg instanceof ClientInventoryMessage inventoryMessage) { } else if (msg instanceof ClientInventoryMessage inventoryMessage) {
player.setInventory(inventoryMessage.inv()); player.setInventory(inventoryMessage.inv());
System.out.println("Got inventory!");
} else if (msg instanceof InventorySelectedStackMessage selectedStackMessage) { } else if (msg instanceof InventorySelectedStackMessage selectedStackMessage) {
player.getInventory().setSelectedIndex(selectedStackMessage.index()); player.getInventory().setSelectedIndex(selectedStackMessage.index());
System.out.println("Selected item stack: " + player.getInventory().getSelectedItemStack().getType().getName());
} else if (msg instanceof ItemStackMessage itemStackMessage) { } else if (msg instanceof ItemStackMessage itemStackMessage) {
player.getInventory().getItemStacks().set(itemStackMessage.index(), itemStackMessage.stack()); player.getInventory().getItemStacks().set(itemStackMessage.index(), itemStackMessage.stack());
System.out.println("Item stack updated: " + itemStackMessage.index());
} else if (msg instanceof PlayerJoinMessage joinMessage) { } else if (msg instanceof PlayerJoinMessage joinMessage) {
world.playerJoined(joinMessage); world.playerJoined(joinMessage);
} else if (msg instanceof PlayerLeaveMessage leaveMessage) { } else if (msg instanceof PlayerLeaveMessage leaveMessage) {

View File

@ -1,15 +1,16 @@
package nl.andrewl.aos2_client; package nl.andrewl.aos2_client;
import nl.andrewl.aos2_client.model.OtherPlayer;
import nl.andrewl.aos2_client.render.chunk.ChunkMesh; import nl.andrewl.aos2_client.render.chunk.ChunkMesh;
import nl.andrewl.aos2_client.render.chunk.ChunkMeshGenerator; import nl.andrewl.aos2_client.render.chunk.ChunkMeshGenerator;
import nl.andrewl.aos_core.model.world.Chunk;
import nl.andrewl.aos_core.model.Player; import nl.andrewl.aos_core.model.Player;
import nl.andrewl.aos_core.model.world.Chunk;
import nl.andrewl.aos_core.model.world.World; import nl.andrewl.aos_core.model.world.World;
import nl.andrewl.aos_core.net.world.ChunkDataMessage;
import nl.andrewl.aos_core.net.client.PlayerJoinMessage; import nl.andrewl.aos_core.net.client.PlayerJoinMessage;
import nl.andrewl.aos_core.net.client.PlayerLeaveMessage; import nl.andrewl.aos_core.net.client.PlayerLeaveMessage;
import nl.andrewl.aos_core.net.world.ChunkUpdateMessage;
import nl.andrewl.aos_core.net.client.PlayerUpdateMessage; import nl.andrewl.aos_core.net.client.PlayerUpdateMessage;
import nl.andrewl.aos_core.net.world.ChunkDataMessage;
import nl.andrewl.aos_core.net.world.ChunkUpdateMessage;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.Vector3i; import org.joml.Vector3i;
@ -28,11 +29,16 @@ public class ClientWorld extends World {
private final ChunkMeshGenerator chunkMeshGenerator = new ChunkMeshGenerator(); private final ChunkMeshGenerator chunkMeshGenerator = new ChunkMeshGenerator();
private final Map<Chunk, ChunkMesh> chunkMeshes = new ConcurrentHashMap<>(); private final Map<Chunk, ChunkMesh> chunkMeshes = new ConcurrentHashMap<>();
private final Map<Integer, Player> players = new HashMap<>(); private final Map<Integer, OtherPlayer> players = new HashMap<>();
public void playerJoined(PlayerJoinMessage joinMessage) { public void playerJoined(PlayerJoinMessage joinMessage) {
Player p = joinMessage.toPlayer(); Player p = joinMessage.toPlayer();
players.put(p.getId(), p); OtherPlayer op = new OtherPlayer(p.getId(), p.getUsername());
op.getPosition().set(p.getPosition());
op.getVelocity().set(p.getVelocity());
op.getOrientation().set(p.getOrientation());
op.setHeldItemId(joinMessage.selectedItemId());
players.put(op.getId(), op);
} }
public void playerLeft(PlayerLeaveMessage leaveMessage) { public void playerLeft(PlayerLeaveMessage leaveMessage) {
@ -40,13 +46,15 @@ public class ClientWorld extends World {
} }
public void playerUpdated(PlayerUpdateMessage playerUpdate) { public void playerUpdated(PlayerUpdateMessage playerUpdate) {
Player p = players.get(playerUpdate.clientId()); OtherPlayer p = players.get(playerUpdate.clientId());
if (p != null) { if (p != null) {
playerUpdate.apply(p); playerUpdate.apply(p);
p.setHeldItemId(playerUpdate.selectedItemId());
p.updateModelTransform();
} }
} }
public Collection<Player> getPlayers() { public Collection<OtherPlayer> getPlayers() {
return players.values(); return players.values();
} }
@ -55,6 +63,7 @@ public class ClientWorld extends World {
for (var player : getPlayers()) { for (var player : getPlayers()) {
movement.set(player.getVelocity()).mul(dt); movement.set(player.getVelocity()).mul(dt);
player.getPosition().add(movement); player.getPosition().add(movement);
player.updateModelTransform();
} }
} }

View File

@ -52,7 +52,7 @@ public class PlayerViewCursorCallback implements GLFWCursorPosCallbackI {
client.getPlayer().getOrientation().x - dx * config.mouseSensitivity, client.getPlayer().getOrientation().x - dx * config.mouseSensitivity,
client.getPlayer().getOrientation().y - dy * config.mouseSensitivity client.getPlayer().getOrientation().y - dy * config.mouseSensitivity
); );
camera.setOrientation(client.getPlayer().getOrientation().x, client.getPlayer().getOrientation().y); camera.setOrientationToPlayer(client.getPlayer());
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
if (lastOrientationUpdateSentAt + ORIENTATION_UPDATE_LIMIT < now) { if (lastOrientationUpdateSentAt + ORIENTATION_UPDATE_LIMIT < now) {
ForkJoinPool.commonPool().submit(() -> comm.sendDatagramPacket(new ClientOrientationState( ForkJoinPool.commonPool().submit(() -> comm.sendDatagramPacket(new ClientOrientationState(

View File

@ -1,13 +1,18 @@
package nl.andrewl.aos2_client.model; package nl.andrewl.aos2_client.model;
import nl.andrewl.aos2_client.Camera;
import nl.andrewl.aos_core.model.Player; import nl.andrewl.aos_core.model.Player;
import nl.andrewl.aos_core.model.item.Inventory; import nl.andrewl.aos_core.model.item.Inventory;
import org.joml.Matrix4f;
import java.util.ArrayList; import java.util.ArrayList;
public class ClientPlayer extends Player { public class ClientPlayer extends Player {
private final Inventory inventory; private final Inventory inventory;
private final Matrix4f heldItemTransform = new Matrix4f();
private final float[] heldItemTransformData = new float[16];
public ClientPlayer(int id, String username) { public ClientPlayer(int id, String username) {
super(id, username); super(id, username);
this.inventory = new Inventory(new ArrayList<>(), 0); this.inventory = new Inventory(new ArrayList<>(), 0);
@ -22,4 +27,17 @@ public class ClientPlayer extends Player {
this.inventory.getItemStacks().addAll(inv.getItemStacks()); this.inventory.getItemStacks().addAll(inv.getItemStacks());
this.inventory.setSelectedIndex(inv.getSelectedIndex()); this.inventory.setSelectedIndex(inv.getSelectedIndex());
} }
public void updateHeldItemTransform(Camera cam) {
heldItemTransform.identity()
.translate(cam.getPosition())
.rotate((float) (cam.getOrientation().x + Math.PI), Camera.UP)
.rotate(-cam.getOrientation().y + (float) Math.PI / 2, Camera.RIGHT)
.translate(-0.35f, -0.4f, 1f);
heldItemTransform.get(heldItemTransformData);
}
public float[] getHeldItemTransformData() {
return heldItemTransformData;
}
} }

View File

@ -0,0 +1,77 @@
package nl.andrewl.aos2_client.model;
import nl.andrewl.aos2_client.Camera;
import nl.andrewl.aos_core.model.Player;
import nl.andrewl.aos_core.model.item.ItemTypes;
import org.joml.Matrix4f;
import org.joml.Vector3f;
/**
* An extension of the player class with only the information needed to display
* other players in the game, without needing to hold any sensitive info.
*/
public class OtherPlayer extends Player {
/**
* The item id of this player's held item.
*/
private int heldItemId;
/**
* The value of block that the player has selected. We use this to show
* what color of block the player is holding.
*/
private byte selectedBlockValue;
/**
* The transformation used to render this player in the world.
*/
private final Matrix4f modelTransform = new Matrix4f();
private final float[] modelTransformData = new float[16];
private final Matrix4f heldItemTransform = new Matrix4f();
private final float[] heldItemTransformData = new float[16];
public OtherPlayer(int id, String username) {
super(id, username);
this.heldItemId = ItemTypes.RIFLE.getId();
}
public int getHeldItemId() {
return heldItemId;
}
public void setHeldItemId(int heldItemId) {
this.heldItemId = heldItemId;
}
@Override
public void setPosition(Vector3f position) {
super.setPosition(position);
updateModelTransform();
}
@Override
public void setOrientation(float x, float y) {
super.setOrientation(x, y);
updateModelTransform();
}
public void updateModelTransform() {
modelTransform.identity()
.translate(position)
.rotate(orientation.x, Camera.UP);
modelTransform.get(modelTransformData);
heldItemTransform.set(modelTransform)
.translate(0.5f, 1.1f, -0.5f)
.rotate((float) Math.PI, Camera.UP);
heldItemTransform.get(heldItemTransformData);
}
public float[] getModelTransformData() {
return modelTransformData;
}
public float[] getHeldItemTransformData() {
return heldItemTransformData;
}
}

View File

@ -3,13 +3,18 @@ package nl.andrewl.aos2_client.render;
import nl.andrewl.aos2_client.Camera; import nl.andrewl.aos2_client.Camera;
import nl.andrewl.aos2_client.ClientWorld; import nl.andrewl.aos2_client.ClientWorld;
import nl.andrewl.aos2_client.config.ClientConfig; import nl.andrewl.aos2_client.config.ClientConfig;
import nl.andrewl.aos2_client.model.ClientPlayer;
import nl.andrewl.aos2_client.render.chunk.ChunkRenderer; import nl.andrewl.aos2_client.render.chunk.ChunkRenderer;
import nl.andrewl.aos2_client.render.gui.GUIRenderer; import nl.andrewl.aos2_client.render.gui.GUIRenderer;
import nl.andrewl.aos2_client.render.gui.GUITexture; import nl.andrewl.aos2_client.render.gui.GUITexture;
import nl.andrewl.aos2_client.render.model.Model; import nl.andrewl.aos2_client.render.model.Model;
import nl.andrewl.aos_core.model.item.BlockItemStack;
import nl.andrewl.aos_core.model.item.ItemTypes;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.lwjgl.glfw.*; import org.lwjgl.glfw.*;
import org.lwjgl.opengl.GL; import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GLUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -34,9 +39,13 @@ public class GameRenderer {
private GUIRenderer guiRenderer; private GUIRenderer guiRenderer;
private ModelRenderer modelRenderer; private ModelRenderer modelRenderer;
private final Camera camera; private final Camera camera;
private final ClientPlayer clientPlayer;
private final ClientWorld world; private final ClientWorld world;
private Model playerModel; // Standard player model used to render all players.
// Standard models for various game components.
private Model playerModel;
private Model rifleModel; private Model rifleModel;
private Model blockModel;
private long windowHandle; private long windowHandle;
private int screenWidth = 800; private int screenWidth = 800;
@ -44,10 +53,12 @@ public class GameRenderer {
private final Matrix4f perspectiveTransform; private final Matrix4f perspectiveTransform;
public GameRenderer(ClientConfig.DisplayConfig config, ClientWorld world) { public GameRenderer(ClientConfig.DisplayConfig config, ClientPlayer clientPlayer, ClientWorld world) {
this.config = config; this.config = config;
this.clientPlayer = clientPlayer;
this.world = world; this.world = world;
this.camera = new Camera(); this.camera = new Camera();
camera.setToPlayer(clientPlayer);
this.perspectiveTransform = new Matrix4f(); this.perspectiveTransform = new Matrix4f();
} }
@ -118,6 +129,7 @@ public class GameRenderer {
try { try {
playerModel = new Model("model/player_simple.obj", "model/simple_player.png"); playerModel = new Model("model/player_simple.obj", "model/simple_player.png");
rifleModel = new Model("model/rifle.obj", "model/rifle.png"); rifleModel = new Model("model/rifle.obj", "model/rifle.png");
blockModel = new Model("model/block.obj", "model/block.png");
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -156,24 +168,41 @@ public class GameRenderer {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
chunkRenderer.draw(camera, world.getChunkMeshesToDraw()); chunkRenderer.draw(camera, world.getChunkMeshesToDraw());
// Draw players. // Draw models. Use one texture at a time for efficiency.
modelRenderer.setView(camera.getViewTransformData()); modelRenderer.start(camera.getViewTransformData());
clientPlayer.updateHeldItemTransform(camera);
playerModel.bind(); playerModel.bind();
Matrix4f modelTransform = new Matrix4f();
for (var player : world.getPlayers()) { for (var player : world.getPlayers()) {
modelTransform.identity().translate(player.getPosition()); // TODO: set aspect color based on player team color
modelRenderer.render(playerModel, modelTransform); modelRenderer.setAspectColor(new Vector3f(0.8f, 0.4f, 0));
modelRenderer.render(playerModel, player.getModelTransformData());
} }
playerModel.unbind(); playerModel.unbind();
rifleModel.bind(); rifleModel.bind();
if (clientPlayer.getInventory().getSelectedItemStack().getType().getId() == ItemTypes.RIFLE.getId()) {
modelRenderer.render(rifleModel, clientPlayer.getHeldItemTransformData());
}
for (var player : world.getPlayers()) { for (var player : world.getPlayers()) {
modelTransform.identity() if (player.getHeldItemId() == ItemTypes.RIFLE.getId()) {
.translate(player.getPosition()) modelRenderer.render(rifleModel, player.getHeldItemTransformData());
.rotate((float) (player.getOrientation().x - Math.PI / 2), Camera.UP) }
.translate(0, 0, -0.45f);
modelRenderer.render(rifleModel, modelTransform);
} }
rifleModel.unbind(); rifleModel.unbind();
blockModel.bind();
if (clientPlayer.getInventory().getSelectedItemStack().getType().getId() == ItemTypes.BLOCK.getId()) {
BlockItemStack stack = (BlockItemStack) clientPlayer.getInventory().getSelectedItemStack();
modelRenderer.setAspectColor(world.getPalette().getColor(stack.getSelectedValue()));
modelRenderer.render(blockModel, clientPlayer.getHeldItemTransformData());
}
modelRenderer.setAspectColor(new Vector3f(0.5f, 0.5f, 0.5f));
for (var player : world.getPlayers()) {
if (player.getHeldItemId() == ItemTypes.BLOCK.getId()) {
modelRenderer.render(blockModel, player.getHeldItemTransformData());
}
}
blockModel.unbind();
modelRenderer.end();
guiRenderer.draw(); guiRenderer.draw();

View File

@ -1,8 +1,8 @@
package nl.andrewl.aos2_client.render; package nl.andrewl.aos2_client.render;
import nl.andrewl.aos2_client.Camera;
import nl.andrewl.aos2_client.render.model.Model; import nl.andrewl.aos2_client.render.model.Model;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Vector3f;
import static org.lwjgl.opengl.GL46.*; import static org.lwjgl.opengl.GL46.*;
@ -15,15 +15,18 @@ public class ModelRenderer {
private final int viewUniform; private final int viewUniform;
private final int modelUniform; private final int modelUniform;
private final int textureSamplerUniform; private final int textureSamplerUniform;
private final int colorUniform;
public ModelRenderer() { public ModelRenderer() {
shaderProgram = new ShaderProgram.Builder() shaderProgram = new ShaderProgram.Builder()
.withShader("shader/model/vertex.glsl", GL_VERTEX_SHADER) .withShader("shader/model/vertex.glsl", GL_VERTEX_SHADER)
.withShader("shader/model/fragment.glsl", GL_FRAGMENT_SHADER) .withShader("shader/model/fragment.glsl", GL_FRAGMENT_SHADER)
.build(); .build();
// System.out.println(glGetProgramInfoLog(shaderProgram.getId())); // Enable for debugging!
projectionUniform = shaderProgram.getUniform("projectionTransform"); projectionUniform = shaderProgram.getUniform("projectionTransform");
viewUniform = shaderProgram.getUniform("viewTransform"); viewUniform = shaderProgram.getUniform("viewTransform");
modelUniform = shaderProgram.getUniform("modelTransform"); modelUniform = shaderProgram.getUniform("modelTransform");
colorUniform = shaderProgram.getUniform("aspectColor");
textureSamplerUniform = shaderProgram.getUniform("textureSampler"); textureSamplerUniform = shaderProgram.getUniform("textureSampler");
} }
@ -33,17 +36,27 @@ public class ModelRenderer {
shaderProgram.stopUsing(); shaderProgram.stopUsing();
} }
public void setView(float[] data) { public void start(float[] viewTransformData) {
shaderProgram.use(); shaderProgram.use();
glUniformMatrix4fv(viewUniform, false, data); glUniformMatrix4fv(viewUniform, false, viewTransformData);
shaderProgram.stopUsing(); glUniform1i(textureSamplerUniform, 0);
}
public void setAspectColor(Vector3f color) {
glUniform3f(colorUniform, color.x, color.y, color.z);
} }
public void render(Model model, Matrix4f modelTransform) { public void render(Model model, Matrix4f modelTransform) {
shaderProgram.use();
glUniformMatrix4fv(modelUniform, false, modelTransform.get(new float[16])); glUniformMatrix4fv(modelUniform, false, modelTransform.get(new float[16]));
glUniform1i(textureSamplerUniform, 0);
model.draw(); model.draw();
}
public void render(Model model, float[] transformData) {
glUniformMatrix4fv(modelUniform, false, transformData);
model.draw();
}
public void end() {
shaderProgram.stopUsing(); shaderProgram.stopUsing();
} }

View File

@ -0,0 +1,13 @@
# Blender MTL File: 'block.blend'
# Material Count: 1
newmtl Material
Ns 323.999994
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 block.png

View File

@ -0,0 +1,46 @@
# Blender v2.82 (sub 7) OBJ File: 'block.blend'
# www.blender.org
mtllib block.mtl
o Cube
v 0.258936 0.258936 -0.258936
v 0.258936 -0.258936 -0.258936
v 0.258936 0.258936 0.258936
v 0.258936 -0.258936 0.258936
v -0.258936 0.258936 -0.258936
v -0.258936 -0.258936 -0.258936
v -0.258936 0.258936 0.258936
v -0.258936 -0.258936 0.258936
vt 0.875000 0.500000
vt 0.625000 0.750000
vt 0.625000 0.500000
vt 0.375000 1.000000
vt 0.375000 0.750000
vt 0.625000 0.000000
vt 0.375000 0.250000
vt 0.375000 0.000000
vt 0.375000 0.500000
vt 0.125000 0.750000
vt 0.125000 0.500000
vt 0.625000 0.250000
vt 0.875000 0.750000
vt 0.625000 1.000000
vn 0.0000 1.0000 0.0000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 -1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
usemtl Material
s off
f 5/1/1 3/2/1 1/3/1
f 3/2/2 8/4/2 4/5/2
f 7/6/3 6/7/3 8/8/3
f 2/9/4 8/10/4 6/11/4
f 1/3/5 4/5/5 2/9/5
f 5/12/6 2/9/6 6/7/6
f 5/1/1 7/13/1 3/2/1
f 3/2/2 7/14/2 8/4/2
f 7/6/3 5/12/3 6/7/3
f 2/9/4 4/5/4 8/10/4
f 1/3/5 3/2/5 4/5/5
f 5/12/6 1/3/6 2/9/6

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

View File

@ -2,149 +2,488 @@
# www.blender.org # www.blender.org
mtllib rifle.mtl mtllib rifle.mtl
o Cube o Cube
v 0.169557 1.084944 -0.055830 v -0.055830 -0.083336 -0.339545
v 0.169557 0.937055 -0.055830 v 0.055830 0.064553 -0.339545
v 0.169557 1.084944 0.055830 v 0.024118 0.058681 0.281275
v 0.169557 0.937055 0.055830 v -0.073945 -0.076680 -0.221085
v -0.451262 1.079071 -0.024118 v 0.073945 -0.076680 -0.221085
v -0.451262 1.030835 -0.024118 v -0.073945 0.071209 -0.221085
v -0.451262 1.079071 0.024118 v 0.073945 0.071209 0.110935
v -0.451262 1.030835 0.024118 v 0.073945 -0.076680 0.110935
v 0.051097 0.943710 -0.073945 v -0.073945 0.071209 0.110935
v 0.051097 1.091599 0.073945 v -0.024118 0.010445 0.916188
v 0.051097 0.943710 0.073945 v 0.024118 0.058681 0.916188
v 0.051097 1.091599 -0.073945 v 0.024118 0.010445 0.916188
v -0.280923 0.943710 -0.073945 v -0.037043 0.013549 -0.510121
v -0.280923 1.091599 0.073945 v 0.037043 0.013549 -0.510121
v -0.280923 0.943710 0.073945 v 0.037043 -0.122075 -0.483943
v -0.280923 1.091599 -0.073945 v -0.073945 0.071209 0.064744
v -0.835438 1.079071 -0.024118 v -0.073945 -0.076680 0.064744
v -0.835438 1.030835 -0.024118 v 0.073945 0.071209 0.064744
v -0.835438 1.079071 0.024118 v 0.026525 0.081393 0.110935
v -0.835438 1.030835 0.024118 v -0.026525 0.081393 0.110935
v 0.340133 1.033939 -0.037043 v 0.026525 0.081393 0.064744
v 0.313955 0.898315 -0.037043 v 0.007063 0.088219 0.093989
v 0.340133 1.033939 0.037043 v -0.007063 0.088219 0.093989
v 0.313955 0.898315 0.037043 v -0.007063 0.088219 0.081690
vt 0.558335 0.340476 v 0.007063 0.088219 0.081690
vt 0.683269 0.472604 v 0.007063 0.098418 0.093989
vt 0.494855 0.472604 v 0.007063 0.107623 0.093989
vt 0.045283 0.471847 v -0.007063 0.107623 0.093989
vt 0.139168 0.342889 v 0.016748 0.107464 0.081690
vt 0.233148 0.480641 v 0.016748 0.107464 0.093989
vt 0.825161 0.646216 v 0.013188 0.113425 0.081690
vt 0.763706 0.942145 v 0.013188 0.113425 0.093989
vt 0.763706 0.646216 v 0.016899 0.120137 0.081690
vt 0.723305 0.156537 v 0.016899 0.120137 0.093989
vt 0.888641 0.248599 v 0.013339 0.116811 0.081690
vt 0.700226 0.248599 v 0.013339 0.116811 0.093989
vt 0.197905 0.831321 v 0.055830 -0.083336 -0.339545
vt 0.058321 0.958172 v -0.055830 0.064553 -0.339545
vt 0.010040 0.822527 v 0.024118 0.010445 0.281275
vt 0.444089 0.260592 v -0.024118 0.058681 0.281275
vt 0.253228 0.176906 v -0.024118 0.010445 0.281275
vt 0.441093 0.168112 v 0.073945 0.071209 -0.221085
vt 0.288471 0.527586 v -0.073945 -0.076680 0.110935
vt 0.476336 0.518792 v -0.024118 0.058681 0.916188
vt 0.888641 0.504352 v -0.037043 -0.122075 -0.483943
vt 0.700226 0.504352 v 0.073945 -0.076680 0.064744
vt 0.200901 0.738841 v -0.026525 0.081393 0.064744
vt 0.494855 0.731177 v 0.002394 0.083283 0.911546
vt 0.660191 0.823714 v -0.002394 0.083283 0.911546
vt 0.517934 0.823714 v 0.002394 0.083283 0.905405
vt 0.382356 0.656544 v 0.007063 0.098418 0.081690
vt 0.013036 0.730047 v -0.007063 0.098418 0.081690
vt 0.683269 0.731177 v -0.002394 0.083283 0.905405
vt 0.899885 0.156741 v -0.002394 0.066154 0.905405
vt 0.961339 0.119119 v 0.007063 0.107623 0.081690
vt 0.961339 0.156741 v -0.007063 0.107623 0.081690
vt 0.619789 0.041284 v 0.002394 0.066154 0.905405
vt 0.619789 0.340476 v -0.007063 0.098418 0.093989
vt 0.358393 0.958172 v -0.002394 0.066154 0.911546
vt 0.321080 0.659412 v 0.002394 0.066154 0.911546
vt 0.077892 0.340021 v 0.006013 0.061853 0.916188
vt 0.176481 0.044129 v -0.006013 0.061853 0.916188
vt 0.995753 0.112578 v 0.006013 0.061853 0.900762
vt 0.901367 0.004848 v -0.006013 0.061853 0.900762
vt 0.995753 0.004848 v -0.024118 0.010445 0.650025
vt 0.301509 0.041261 v 0.024118 0.010445 0.900762
vt 0.476337 0.053554 v -0.024118 0.058681 0.900762
vt 0.841627 0.040571 v 0.024118 0.058681 0.900762
vt 0.865562 0.156537 v -0.016748 0.107464 0.081690
vt 0.541869 0.958716 v -0.016748 0.107464 0.093989
vt 0.825161 0.942145 v -0.013188 0.113425 0.081690
vt 0.233148 0.945879 v -0.013188 0.113425 0.093989
vt 0.256224 0.269386 v -0.016899 0.120137 0.081690
vt 0.899885 0.119119 v -0.016899 0.120137 0.093989
vt 0.558335 0.041284 v -0.013339 0.116811 0.081690
vt 0.419669 0.955304 v -0.013339 0.116811 0.093989
vt 0.115206 0.041261 vt 0.806012 0.053958
vt 0.901367 0.112578 vt 0.748428 0.163602
vt 0.747240 0.040571 vt 0.751210 0.053937
vt 0.636255 0.958716 vt 0.041029 0.557417
vn -0.0734 0.9973 0.0000 vt 0.125909 0.451045
vn -0.2807 0.0000 0.9598 vt 0.211449 0.564648
vn 0.0000 -1.0000 0.0000 vt 0.562131 0.935764
vn -0.0561 -0.9984 0.0000 vt 0.506385 0.945629
vn 0.1095 0.0000 0.9940 vt 0.506385 0.775418
vn 0.1512 0.0000 -0.9885 vt 0.469736 0.135848
vn 0.0000 0.0000 -1.0000 vt 0.619715 0.212082
vn 0.1512 0.0000 0.9885 vt 0.448801 0.212082
vn 0.0561 0.9984 0.0000 vt 0.179526 0.854016
vn -0.4554 -0.8903 0.0000 vt 0.052864 0.958716
vn -0.2807 0.0000 -0.9598 vt 0.009105 0.846785
vn 0.0000 0.0000 1.0000 vt 0.402849 0.222306
vn 0.0000 1.0000 0.0000 vt 0.229660 0.153215
vt 0.400080 0.145984
vt 0.257528 0.412943
vt 0.427948 0.405712
vt 0.619715 0.394869
vt 0.448801 0.394869
vt 0.182294 0.777694
vt 0.992309 0.202522
vt 0.842330 0.126305
vt 0.971374 0.126305
vt 0.448801 0.424408
vt 0.562131 0.539603
vt 0.506385 0.539603
vt 0.346464 0.548955
vt 0.261584 0.442583
vt 0.432004 0.435352
vt 0.036973 0.587056
vt 0.207393 0.594287
vt 0.692682 0.163602
vt 0.635098 0.053958
vt 0.689900 0.053937
vt 0.816212 0.502096
vt 0.871958 0.533137
vt 0.816212 0.533137
vt 0.920658 0.472528
vt 0.938486 0.460871
vt 0.938486 0.472522
vt 0.345277 0.948817
vt 0.402217 0.956357
vt 0.346631 0.958715
vt 0.124722 0.051183
vt 0.181662 0.043643
vt 0.180307 0.053541
vt 0.903176 0.494624
vt 0.817556 0.407043
vt 0.903176 0.407043
vt 0.273419 0.041284
vt 0.432004 0.051451
vt 0.577068 0.040721
vt 0.598780 0.135848
vt 0.949661 0.016642
vt 0.992309 0.386460
vt 0.821394 0.202523
vt 0.011874 0.770463
vt 0.619715 0.424408
vt 0.751210 0.024212
vt 0.712392 0.035103
vt 0.689900 0.024212
vt 0.806012 0.024233
vt 0.635098 0.024233
vt 0.919326 0.502555
vt 0.907558 0.437900
vt 0.919326 0.407384
vt 0.889321 0.514164
vt 0.875107 0.520727
vt 0.875107 0.514164
vt 0.712392 0.043018
vt 0.728718 0.043018
vt 0.728718 0.035103
vt 0.920495 0.498808
vt 0.934710 0.492244
vt 0.934710 0.498808
vt 0.921515 0.410410
vt 0.933300 0.419500
vt 0.921515 0.419500
vt 0.908689 0.514146
vt 0.920476 0.523236
vt 0.908689 0.523236
vt 0.920496 0.455641
vt 0.934711 0.446550
vt 0.934711 0.455641
vt 0.920476 0.514146
vt 0.931114 0.523236
vt 0.889321 0.520727
vt 0.875107 0.526651
vt 0.931114 0.514146
vt 0.930930 0.507913
vt 0.937820 0.510204
vt 0.950641 0.423442
vt 0.958397 0.425830
vt 0.943753 0.425733
vt 0.920496 0.446550
vt 0.934732 0.442609
vt 0.943937 0.419500
vt 0.947046 0.503547
vt 0.935853 0.495031
vt 0.947046 0.495681
vt 0.943469 0.456445
vt 0.947583 0.464367
vt 0.943469 0.464360
vt 0.890600 0.522124
vt 0.904814 0.513969
vt 0.904814 0.522125
vt 0.945577 0.507816
vt 0.941733 0.510107
vt 0.951326 0.515109
vt 0.947413 0.507194
vt 0.951326 0.507194
vt 0.880640 0.510209
vt 0.887737 0.499186
vt 0.887737 0.510209
vt 0.926018 0.438452
vt 0.933116 0.427429
vt 0.933116 0.438452
vt 0.939537 0.438328
vt 0.945070 0.427305
vt 0.945070 0.438328
vt 0.899681 0.508026
vt 0.894148 0.511978
vt 0.894148 0.508026
vt 0.943937 0.410410
vt 0.933300 0.410410
vt 0.948907 0.447304
vt 0.943526 0.441894
vt 0.948907 0.439565
vt 0.938486 0.441224
vt 0.875269 0.512981
vt 0.893097 0.512981
vt 0.920495 0.486320
vt 0.920495 0.492244
vt 0.945070 0.473548
vt 0.939537 0.484569
vt 0.939537 0.473548
vt 0.939453 0.440614
vt 0.943119 0.460004
vt 0.939453 0.471655
vt 0.851034 0.500054
vt 0.871958 0.502096
vt 0.938486 0.473583
vt 0.920658 0.485228
vt 0.920658 0.473577
vt 0.948873 0.455740
vt 0.943524 0.450330
vt 0.948873 0.448001
vt 0.930930 0.529469
vt 0.692682 0.562256
vt 0.290879 0.551313
vt 0.378844 0.785569
vt 0.070324 0.448687
vt 0.958397 0.404080
vt 0.950641 0.406468
vt 0.943753 0.404177
vt 0.934732 0.459582
vt 0.894403 0.507465
vt 0.905596 0.498949
vt 0.905596 0.506814
vt 0.949619 0.427165
vt 0.945504 0.435087
vt 0.945504 0.427172
vt 0.950203 0.494281
vt 0.935989 0.486125
vt 0.950203 0.486125
vt 0.937820 0.527178
vt 0.945577 0.529566
vt 0.945495 0.481323
vt 0.949409 0.473409
vt 0.949409 0.481324
vt 0.562131 0.945629
vt 0.211449 0.948549
vt 0.232429 0.229537
vt 0.920658 0.460877
vt 0.126076 0.041284
vt 0.817556 0.494624
vt 0.491448 0.040721
vt 0.864042 0.016642
vt 0.821394 0.386460
vt 0.907558 0.472039
vt 0.889321 0.526651
vt 0.954554 0.423539
vt 0.920518 0.442609
vt 0.935853 0.502896
vt 0.947583 0.456452
vt 0.890600 0.513969
vt 0.947413 0.515109
vt 0.880640 0.499186
vt 0.926018 0.427429
vt 0.939537 0.427305
vt 0.899681 0.511978
vt 0.943526 0.444975
vt 0.920658 0.441224
vt 0.934710 0.486320
vt 0.945070 0.484569
vt 0.943119 0.452265
vt 0.837136 0.500054
vt 0.938486 0.485234
vt 0.943524 0.453411
vt 0.748428 0.562256
vt 0.954554 0.406371
vt 0.920518 0.459582
vt 0.894403 0.499599
vt 0.949619 0.435080
vt 0.935989 0.494281
vt 0.941733 0.527275
vt 0.945495 0.473408
vn -0.2081 0.9691 0.1322
vn 0.9598 0.0000 0.2807
vn 0.0000 -1.0000 -0.0000
vn 0.0000 -0.9984 0.0561
vn 0.9940 0.0000 -0.1095
vn -0.9885 0.0000 -0.1512
vn -1.0000 0.0000 0.0000 vn -1.0000 0.0000 0.0000
vn 0.9819 -0.1895 0.0000 vn 0.9885 0.0000 -0.1512
vn 0.1227 -0.0237 -0.9922 vn 0.0000 0.9984 -0.0561
vn -0.2591 -0.9658 0.0000 vn 0.0000 -0.8903 0.4554
vn 0.2865 0.9581 0.0000 vn -0.9598 0.0000 0.2807
vn 0.1227 -0.0237 0.9922 vn 1.0000 0.0000 0.0000
vn 0.1095 0.0000 -0.9940 vn 0.2081 0.9691 0.1322
vn 0.0000 0.0000 1.0000
vn -0.1726 0.9850 0.0000
vn 0.0000 -0.1895 -0.9819
vn -0.9922 -0.0237 -0.1227
vn 0.0000 -0.9658 0.2591
vn 0.0000 0.9581 -0.2865
vn 0.0000 1.0000 0.0000
vn 0.0000 0.9276 -0.3736
vn -0.2100 0.9777 0.0000
vn 0.2100 0.9777 0.0000
vn 0.0000 -0.0000 -1.0000
vn 0.0000 0.9276 0.3736
vn -0.3309 0.9437 0.0000
vn 0.3309 0.9437 0.0000
vn -0.6877 0.7260 0.0000
vn 0.6826 -0.7308 0.0000
vn -0.6827 0.7307 0.0000
vn 0.9999 -0.0119 0.0000
vn -0.9990 0.0444 0.0000
vn 0.0000 0.9912 0.1322
vn 0.0000 0.7336 0.6796
vn -0.7651 0.6439 -0.0000
vn 0.7651 0.6439 0.0000
vn 0.1726 0.9850 0.0000
vn 0.0000 0.7336 -0.6796
vn 0.6877 0.7260 0.0000
vn -0.6826 -0.7308 0.0000
vn 0.6827 0.7307 0.0000
vn -0.9999 -0.0119 0.0000
vn 0.9990 0.0444 0.0000
vn 0.9922 -0.0237 -0.1227
vn -0.9940 0.0000 -0.1095
usemtl Material usemtl Material
s off s off
f 5/1/1 14/2/1 16/3/1 f 9/1/1 40/2/1 20/3/1
f 14/4/2 8/5/2 15/6/2 f 7/4/2 39/5/2 8/6/2
f 8/7/3 18/8/3 6/9/3 f 66/7/3 10/8/3 65/9/3
f 2/10/4 11/11/4 9/12/4 f 1/10/4 5/11/4 4/12/4
f 4/13/5 23/14/5 3/15/5 f 37/13/5 14/14/5 2/15/5
f 9/16/6 1/17/6 2/18/6 f 4/16/6 38/17/6 1/18/6
f 16/19/7 9/16/7 13/20/7 f 16/19/7 4/16/7 17/20/7
f 9/12/3 15/21/3 13/22/3 f 4/12/3 46/21/3 17/22/3
f 3/15/8 11/23/8 4/13/8 f 2/15/8 5/23/8 37/13/8
f 12/24/9 3/25/9 1/26/9 f 6/24/9 2/25/9 38/26/9
f 13/22/10 8/7/10 6/9/10 f 43/27/10 39/28/10 41/29/10
f 6/27/11 16/19/11 13/20/11 f 41/30/11 9/31/11 43/32/11
f 10/28/12 15/6/12 11/23/12 f 18/33/12 8/6/12 46/34/12
f 16/3/13 10/29/13 12/24/13 f 3/35/13 7/36/13 19/37/13
f 19/30/14 18/31/14 20/32/14 f 11/38/14 10/39/14 12/40/14
f 5/1/13 19/33/13 7/34/13 f 44/41/15 64/42/15 67/43/15
f 6/27/7 17/35/7 5/36/7 f 67/44/7 10/45/7 44/46/7
f 7/37/12 20/38/12 8/5/12 f 68/47/12 12/48/12 66/49/12
f 21/39/15 24/40/15 22/41/15 f 13/50/16 15/51/16 45/52/16
f 2/18/16 21/42/16 22/43/16 f 1/18/17 13/53/17 45/54/17
f 2/10/17 24/44/17 4/45/17 f 1/10/18 15/55/18 37/56/18
f 3/25/18 21/46/18 1/26/18 f 2/25/19 13/57/19 38/26/19
f 5/1/1 7/34/1 14/2/1 f 16/58/20 42/59/20 6/24/20
f 14/4/2 7/37/2 8/5/2 f 42/60/12 46/34/12 5/23/12
f 8/7/3 20/47/3 18/8/3 f 17/22/3 8/61/3 43/27/3
f 2/10/4 4/45/4 11/11/4 f 9/31/7 17/20/7 43/32/7
f 4/13/19 24/48/19 23/14/19 f 47/62/21 25/63/21 21/64/21
f 9/16/6 12/49/6 1/17/6 f 9/1/22 47/62/22 16/65/22
f 16/19/7 12/49/7 9/16/7 f 18/66/23 19/37/23 7/36/23
f 9/12/3 11/11/3 15/21/3 f 16/67/24 21/68/24 18/69/24
f 3/15/8 10/28/8 11/23/8 f 23/70/7 52/71/7 24/72/7
f 12/24/9 10/29/9 3/25/9 f 20/3/25 22/73/25 23/74/25
f 13/22/10 15/21/10 8/7/10 f 20/3/26 24/75/26 47/62/26
f 6/27/11 5/36/11 16/19/11 f 21/64/27 22/73/27 19/37/27
f 10/28/12 14/4/12 15/6/12 f 25/76/12 26/77/12 22/78/12
f 16/3/13 14/2/13 10/29/13 f 24/79/24 51/80/24 25/81/24
f 19/30/14 17/50/14 18/31/14 f 22/82/14 58/83/14 23/84/14
f 5/1/13 17/51/13 19/33/13 f 28/85/20 55/86/20 56/87/20
f 6/27/7 18/52/7 17/35/7 f 26/88/14 28/89/14 58/83/14
f 7/37/12 19/53/12 20/38/12 f 58/90/7 56/91/7 52/71/7
f 21/39/15 23/54/15 24/40/15 f 27/92/14 30/93/14 32/94/14
f 2/18/20 1/17/20 21/42/20 f 31/95/24 33/96/24 29/97/24
f 2/10/17 22/55/17 24/44/17 f 27/98/28 31/99/28 55/86/28
f 3/25/18 23/56/18 21/46/18 f 55/100/24 29/97/24 51/80/24
f 51/101/29 30/102/29 26/103/29
f 33/104/30 36/105/30 34/106/30
f 29/107/31 34/108/31 30/109/31
f 32/94/14 34/110/14 36/111/14
f 32/112/32 35/113/32 31/114/32
f 19/37/33 40/2/33 3/35/33
f 57/115/12 48/116/12 60/117/12
f 59/118/7 53/119/7 54/120/7
f 60/121/14 49/122/14 59/123/14
f 53/124/20 48/125/20 50/126/20
f 56/127/24 51/80/24 52/128/24
f 61/129/34 59/130/34 62/131/34
f 64/132/35 59/118/35 54/120/35
f 63/133/36 60/117/36 61/134/36
f 55/135/12 26/77/12 51/136/12
f 54/137/24 50/138/24 57/139/24
f 67/140/24 63/141/24 68/142/24
f 11/38/14 62/143/14 44/144/14
f 68/145/37 61/146/37 11/147/37
f 64/148/38 57/149/38 63/150/38
f 39/28/3 65/9/3 41/29/3
f 28/89/14 70/151/14 58/83/14
f 40/2/20 68/152/20 3/35/20
f 40/153/7 65/154/7 67/44/7
f 3/155/12 66/49/12 39/5/12
f 73/156/24 71/157/24 69/158/24
f 71/159/39 28/85/39 56/87/39
f 69/158/24 56/127/24 52/128/24
f 70/160/40 52/161/40 58/162/40
f 76/163/41 73/164/41 74/165/41
f 74/166/42 69/167/42 70/168/42
f 72/169/14 74/170/14 70/151/14
f 75/171/43 72/172/43 71/173/43
f 7/4/2 3/155/2 39/5/2
f 66/7/3 12/174/3 10/8/3
f 1/10/4 37/56/4 5/11/4
f 37/13/44 15/175/44 14/14/44
f 4/16/6 6/176/6 38/17/6
f 16/19/7 6/176/7 4/16/7
f 4/12/3 5/11/3 46/21/3
f 2/15/8 42/60/8 5/23/8
f 6/24/9 42/59/9 2/25/9
f 43/27/10 8/61/10 39/28/10
f 41/30/11 40/153/11 9/31/11
f 18/33/12 7/4/12 8/6/12
f 11/38/14 44/144/14 10/39/14
f 44/41/15 62/177/15 64/42/15
f 67/44/7 65/154/7 10/45/7
f 68/47/12 11/178/12 12/48/12
f 13/50/16 14/179/16 15/51/16
f 1/18/45 38/17/45 13/53/45
f 1/10/18 45/180/18 15/55/18
f 2/25/19 14/181/19 13/57/19
f 16/58/20 18/182/20 42/59/20
f 42/60/12 18/33/12 46/34/12
f 17/22/3 46/21/3 8/61/3
f 9/31/7 16/19/7 17/20/7
f 47/62/21 24/75/21 25/63/21
f 9/1/22 20/3/22 47/62/22
f 18/66/23 21/64/23 19/37/23
f 16/67/24 47/183/24 21/68/24
f 23/70/7 58/90/7 52/71/7
f 20/3/25 19/37/25 22/73/25
f 20/3/26 23/74/26 24/75/26
f 21/64/27 25/63/27 22/73/27
f 25/76/12 51/136/12 26/77/12
f 24/79/24 52/128/24 51/80/24
f 22/82/14 26/88/14 58/83/14
f 28/85/20 27/98/20 55/86/20
f 26/88/14 27/92/14 28/89/14
f 58/90/7 28/184/7 56/91/7
f 27/92/14 26/88/14 30/93/14
f 31/95/24 35/185/24 33/96/24
f 27/98/28 32/186/28 31/99/28
f 55/100/24 31/95/24 29/97/24
f 51/101/29 29/187/29 30/102/29
f 33/104/30 35/188/30 36/105/30
f 29/107/31 33/189/31 34/108/31
f 32/94/14 30/93/14 34/110/14
f 32/112/32 36/190/32 35/113/32
f 19/37/33 20/3/33 40/2/33
f 57/115/12 50/191/12 48/116/12
f 59/118/7 49/192/7 53/119/7
f 60/121/14 48/193/14 49/122/14
f 53/124/20 49/194/20 48/125/20
f 56/127/24 55/100/24 51/80/24
f 61/129/34 60/195/34 59/130/34
f 64/132/35 62/196/35 59/118/35
f 63/133/36 57/115/36 60/117/36
f 55/135/12 27/197/12 26/77/12
f 54/137/24 53/198/24 50/138/24
f 67/140/24 64/199/24 63/141/24
f 11/38/14 61/200/14 62/143/14
f 68/145/37 63/201/37 61/146/37
f 64/148/38 54/202/38 57/149/38
f 39/28/3 66/7/3 65/9/3
f 28/89/14 72/169/14 70/151/14
f 40/2/20 67/203/20 68/152/20
f 40/153/7 41/30/7 65/154/7
f 3/155/12 68/47/12 66/49/12
f 73/156/24 75/204/24 71/157/24
f 71/159/39 72/205/39 28/85/39
f 69/158/24 71/157/24 56/127/24
f 70/160/40 69/206/40 52/161/40
f 76/163/41 75/207/41 73/164/41
f 74/166/42 73/208/42 69/167/42
f 72/169/14 76/209/14 74/170/14
f 75/171/43 76/210/43 72/172/43

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -5,10 +5,15 @@ in vec3 vertexNormal;
out vec4 fragmentColor; out vec4 fragmentColor;
uniform vec3 aspectColor;
uniform sampler2D textureSampler; uniform sampler2D textureSampler;
void main() { void main() {
vec4 baseColor = texture(textureSampler, textureCoords); vec4 baseColor = texture(textureSampler, textureCoords);
vec4 templateColor = vec4(0.0, 1.0, 0.0, 1.0);
if (baseColor == templateColor) {
baseColor = vec4(aspectColor, 1.0);
}
vec3 lightDirection = normalize(vec3(0.5, -1.0, -0.5));// TODO: Add this via a uniform. 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 lightColor = vec3(1.0, 1.0, 0.9); // TODO: Add this via a uniform.

View File

@ -11,6 +11,13 @@ import static org.joml.Math.*;
* know. * know.
*/ */
public class Player { public class Player {
public static final float HEIGHT = 1.8f;
public static final float HEIGHT_CROUCH = 1.4f;
public static final float EYE_HEIGHT = HEIGHT - 0.1f;
public static final float EYE_HEIGHT_CROUCH = HEIGHT_CROUCH - 0.1f;
public static final float WIDTH = 0.75f;
public static final float RADIUS = WIDTH / 2f;
/** /**
* The player's position. This is the position of their feet. So if a * The player's position. This is the position of their feet. So if a
* player is standing on a block at y=5 (block occupies space from 4 to 5) * player is standing on a block at y=5 (block occupies space from 4 to 5)
@ -35,6 +42,12 @@ public class Player {
*/ */
protected final Vector2f orientation; protected final Vector2f orientation;
/**
* Whether this player is crouching or not. This affects the player's
* height, eye-level, speed, and accuracy.
*/
protected boolean crouching = false;
/** /**
* A vector that's internally re-computed each time the player's * A vector that's internally re-computed each time the player's
* orientation changes, and represents unit vector pointing in the * orientation changes, and represents unit vector pointing in the
@ -87,6 +100,14 @@ public class Player {
viewVector.set(sin(orientation.x) * cos(y), -sin(y), cos(orientation.x) * cos(y)).normalize(); viewVector.set(sin(orientation.x) * cos(y), -sin(y), cos(orientation.x) * cos(y)).normalize();
} }
public boolean isCrouching() {
return crouching;
}
public void setCrouching(boolean crouching) {
this.crouching = crouching;
}
public String getUsername() { public String getUsername() {
return username; return username;
} }
@ -107,4 +128,20 @@ public class Player {
cos(x) cos(x)
).normalize(); ).normalize();
} }
public float getEyeHeight() {
return crouching ? EYE_HEIGHT_CROUCH : EYE_HEIGHT;
}
public Vector3f getEyePosition() {
return new Vector3f(
position.x,
position.y + getEyeHeight(),
position.z
);
}
public float getCurrentHeight() {
return crouching ? HEIGHT_CROUCH : HEIGHT;
}
} }

View File

@ -1,6 +1,7 @@
package nl.andrewl.aos_core.net.client; package nl.andrewl.aos_core.net.client;
import nl.andrewl.aos_core.model.Player; import nl.andrewl.aos_core.model.Player;
import nl.andrewl.aos_core.model.item.ItemTypes;
import nl.andrewl.record_net.Message; import nl.andrewl.record_net.Message;
/** /**
@ -11,14 +12,18 @@ public record PlayerJoinMessage(
int id, String username, int id, String username,
float px, float py, float pz, float px, float py, float pz,
float vx, float vy, float vz, float vx, float vy, float vz,
float ox, float oy float ox, float oy,
boolean crouching,
int selectedItemId
) implements Message { ) implements Message {
public PlayerJoinMessage(Player player) { public PlayerJoinMessage(Player player) {
this( this(
player.getId(), player.getUsername(), player.getId(), player.getUsername(),
player.getPosition().x, player.getPosition().y, player.getPosition().z, player.getPosition().x, player.getPosition().y, player.getPosition().z,
player.getVelocity().x, player.getVelocity().y, player.getVelocity().z, player.getVelocity().x, player.getVelocity().y, player.getVelocity().z,
player.getOrientation().x, player.getOrientation().y player.getOrientation().x, player.getOrientation().y,
player.isCrouching(),
ItemTypes.BLOCK.getId()
); );
} }

View File

@ -20,5 +20,6 @@ public record PlayerUpdateMessage(
p.getPosition().set(px, py, pz); p.getPosition().set(px, py, pz);
p.getVelocity().set(vx, vy, vz); p.getVelocity().set(vx, vy, vz);
p.getOrientation().set(ox, oy); p.getOrientation().set(ox, oy);
p.setCrouching(crouching);
} }
} }

BIN
design/block.blend Normal file

Binary file not shown.

BIN
design/block.blend1 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -2,30 +2,30 @@
# www.blender.org # www.blender.org
mtllib rifle.mtl mtllib rifle.mtl
o Cube o Cube
v 0.169557 1.084944 -0.055830 v 0.055830 0.064553 0.339545
v 0.169557 0.937055 -0.055830 v 0.055830 -0.083336 0.339545
v 0.169557 1.084944 0.055830 v -0.055830 0.064553 0.339545
v 0.169557 0.937055 0.055830 v -0.055830 -0.083336 0.339545
v -0.451262 1.079071 -0.024118 v 0.024118 0.058681 -0.281275
v -0.451262 1.030835 -0.024118 v 0.024118 0.010445 -0.281275
v -0.451262 1.079071 0.024118 v -0.024118 0.058681 -0.281275
v -0.451262 1.030835 0.024118 v -0.024118 0.010445 -0.281275
v 0.051097 0.943710 -0.073945 v 0.073945 -0.076680 0.221085
v 0.051097 1.091599 0.073945 v -0.073944 0.071209 0.221085
v 0.051097 0.943710 0.073945 v -0.073944 -0.076680 0.221085
v 0.051097 1.091599 -0.073945 v 0.073945 0.071209 0.221085
v -0.280923 0.943710 -0.073945 v 0.073945 -0.076680 -0.110935
v -0.280923 1.091599 0.073945 v -0.073945 0.071209 -0.110935
v -0.280923 0.943710 0.073945 v -0.073945 -0.076680 -0.110935
v -0.280923 1.091599 -0.073945 v 0.073945 0.071209 -0.110935
v -0.835438 1.079071 -0.024118 v 0.024118 0.058681 -0.665451
v -0.835438 1.030835 -0.024118 v 0.024118 0.010445 -0.665451
v -0.835438 1.079071 0.024118 v -0.024118 0.058681 -0.665451
v -0.835438 1.030835 0.024118 v -0.024118 0.010445 -0.665451
v 0.340133 1.033939 -0.037043 v 0.037043 0.013549 0.510121
v 0.313955 0.898315 -0.037043 v 0.037043 -0.122075 0.483943
v 0.340133 1.033939 0.037043 v -0.037042 0.013549 0.510121
v 0.313955 0.898315 0.037043 v -0.037042 -0.122075 0.483943
vt 0.558335 0.340476 vt 0.558335 0.340476
vt 0.683269 0.472604 vt 0.683269 0.472604
vt 0.494855 0.472604 vt 0.494855 0.472604
@ -82,26 +82,26 @@ vt 0.115206 0.041261
vt 0.901367 0.112578 vt 0.901367 0.112578
vt 0.747240 0.040571 vt 0.747240 0.040571
vt 0.636255 0.958716 vt 0.636255 0.958716
vn -0.0734 0.9973 0.0000 vn -0.0000 0.9973 -0.0733
vn -0.2807 0.0000 0.9598 vn -0.9598 0.0000 -0.2807
vn 0.0000 -1.0000 0.0000 vn 0.0000 -1.0000 -0.0000
vn -0.0561 -0.9984 0.0000 vn 0.0000 -0.9984 -0.0561
vn 0.1095 0.0000 0.9940 vn -0.9940 0.0000 0.1095
vn 0.1512 0.0000 -0.9885 vn 0.9885 0.0000 0.1512
vn 0.0000 0.0000 -1.0000 vn 1.0000 0.0000 -0.0000
vn 0.1512 0.0000 0.9885 vn -0.9885 0.0000 0.1512
vn 0.0561 0.9984 0.0000 vn 0.0000 0.9984 0.0561
vn -0.4554 -0.8903 0.0000 vn 0.0000 -0.8903 -0.4554
vn -0.2807 0.0000 -0.9598 vn 0.9598 0.0000 -0.2807
vn 0.0000 0.0000 1.0000
vn 0.0000 1.0000 0.0000
vn -1.0000 0.0000 0.0000 vn -1.0000 0.0000 0.0000
vn 0.9819 -0.1895 0.0000 vn 0.0000 1.0000 0.0000
vn 0.1227 -0.0237 -0.9922 vn 0.0000 0.0000 -1.0000
vn -0.2591 -0.9658 0.0000 vn 0.0000 -0.1895 0.9819
vn 0.2865 0.9581 0.0000 vn 0.9922 -0.0237 0.1227
vn 0.1227 -0.0237 0.9922 vn 0.0000 -0.9658 -0.2591
vn 0.1095 0.0000 -0.9940 vn 0.0000 0.9581 0.2865
vn -0.9922 -0.0237 0.1227
vn 0.9940 0.0000 0.1095
usemtl Material usemtl Material
s off s off
f 5/1/1 14/2/1 16/3/1 f 5/1/1 14/2/1 16/3/1

View File

@ -19,13 +19,6 @@ import java.util.ArrayList;
public class ServerPlayer extends Player { public class ServerPlayer extends Player {
private static final Logger log = LoggerFactory.getLogger(ServerPlayer.class); private static final Logger log = LoggerFactory.getLogger(ServerPlayer.class);
public static final float HEIGHT = 1.8f;
public static final float HEIGHT_CROUCH = 1.4f;
public static final float EYE_HEIGHT = HEIGHT - 0.1f;
public static final float EYE_HEIGHT_CROUCH = HEIGHT_CROUCH - 0.1f;
public static final float WIDTH = 0.75f;
public static final float RADIUS = WIDTH / 2f;
private final PlayerActionManager actionManager; private final PlayerActionManager actionManager;
private final Inventory inventory; private final Inventory inventory;

View File

@ -71,6 +71,11 @@ public class PlayerActionManager {
tickBlockAction(now, server, world); tickBlockAction(now, server, world);
} }
if (player.isCrouching() != lastInputState.crouching()) {
player.setCrouching(lastInputState.crouching());
updated = true;
}
tickMovement(dt, world, server.getConfig().physics); tickMovement(dt, world, server.getConfig().physics);
} }
@ -82,9 +87,7 @@ public class PlayerActionManager {
stack.getAmount() < stack.getType().getMaxAmount() && stack.getAmount() < stack.getType().getMaxAmount() &&
now - lastBlockRemovedAt > server.getConfig().actions.blockRemoveCooldown * 1000 now - lastBlockRemovedAt > server.getConfig().actions.blockRemoveCooldown * 1000
) { ) {
Vector3f eyePos = new Vector3f(player.getPosition()); var hit = world.getLookingAtPos(player.getEyePosition(), player.getViewVector(), 10);
eyePos.y += getEyeHeight();
var hit = world.getLookingAtPos(eyePos, player.getViewVector(), 10);
if (hit != null) { if (hit != null) {
world.setBlockAt(hit.pos().x, hit.pos().y, hit.pos().z, (byte) 0); world.setBlockAt(hit.pos().x, hit.pos().y, hit.pos().z, (byte) 0);
lastBlockRemovedAt = now; lastBlockRemovedAt = now;
@ -99,9 +102,7 @@ public class PlayerActionManager {
stack.getAmount() > 0 && stack.getAmount() > 0 &&
now - lastBlockPlacedAt > server.getConfig().actions.blockPlaceCooldown * 1000 now - lastBlockPlacedAt > server.getConfig().actions.blockPlaceCooldown * 1000
) { ) {
Vector3f eyePos = new Vector3f(player.getPosition()); var hit = world.getLookingAtPos(player.getEyePosition(), player.getViewVector(), 10);
eyePos.y += getEyeHeight();
var hit = world.getLookingAtPos(eyePos, player.getViewVector(), 10);
if (hit != null) { if (hit != null) {
Vector3i placePos = new Vector3i(hit.pos()); Vector3i placePos = new Vector3i(hit.pos());
placePos.add(hit.norm()); placePos.add(hit.norm());
@ -226,7 +227,7 @@ public class PlayerActionManager {
float playerBodyMinX = playerPos.x - RADIUS; float playerBodyMinX = playerPos.x - RADIUS;
float playerBodyMaxX = playerPos.x + RADIUS; float playerBodyMaxX = playerPos.x + RADIUS;
float playerBodyMinY = playerPos.y; float playerBodyMinY = playerPos.y;
float playerBodyMaxY = playerPos.y + getCurrentHeight(); float playerBodyMaxY = playerPos.y + player.getCurrentHeight();
// Compute the bounds of all blocks the player is intersecting with. // Compute the bounds of all blocks the player is intersecting with.
int minX = (int) Math.floor(playerBodyMinX); int minX = (int) Math.floor(playerBodyMinX);
@ -243,7 +244,7 @@ public class PlayerActionManager {
var position = player.getPosition(); var position = player.getPosition();
var velocity = player.getVelocity(); var velocity = player.getVelocity();
final Vector3f nextTickPosition = new Vector3f(position).add(movement); final Vector3f nextTickPosition = new Vector3f(position).add(movement);
float height = getCurrentHeight(); float height = player.getCurrentHeight();
float delta = 0.00001f; float delta = 0.00001f;
final Vector3f stepSize = new Vector3f(movement).normalize(1.0f); final Vector3f stepSize = new Vector3f(movement).normalize(1.0f);
// The number of steps we'll make towards the next tick position. // The number of steps we'll make towards the next tick position.
@ -373,12 +374,4 @@ public class PlayerActionManager {
} }
} }
} }
public float getCurrentHeight() {
return lastInputState.crouching() ? HEIGHT_CROUCH : HEIGHT;
}
public float getEyeHeight() {
return lastInputState.crouching() ? EYE_HEIGHT_CROUCH : EYE_HEIGHT;
}
} }