|
@@ -0,0 +1,204 @@
|
|
|
+#include <cmath>
|
|
|
+
|
|
|
+#include "client/World.h"
|
|
|
+#include "client/rendering/Engine.h"
|
|
|
+#include "client/rendering/Mesh.h"
|
|
|
+#include "common/BlockStorage.h"
|
|
|
+#include "rendering/FileTexture.h"
|
|
|
+#include "utils/List.h"
|
|
|
+#include "utils/Logger.h"
|
|
|
+#include "utils/Random.h"
|
|
|
+
|
|
|
+static BlockStorage blocks{7, 7};
|
|
|
+static List<Entity*> entities;
|
|
|
+static Mesh mesh;
|
|
|
+static FileTexture texture;
|
|
|
+static bool dirty = true;
|
|
|
+
|
|
|
+bool World::init() {
|
|
|
+ mesh.init();
|
|
|
+ Error error = texture.load("resources/textures.png", 4);
|
|
|
+ if(error.has()) {
|
|
|
+ LOG_ERROR(error.message);
|
|
|
+ }
|
|
|
+ return error.has();
|
|
|
+}
|
|
|
+
|
|
|
+void World::addEntity(Entity* e) {
|
|
|
+ entities.add(e);
|
|
|
+}
|
|
|
+
|
|
|
+void World::removeEntity(Entity* e) {
|
|
|
+ for(int i = 0; i < entities.getLength(); i++) {
|
|
|
+ if(entities[i] == e) {
|
|
|
+ entities.removeBySwap(i);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static List<Box> getBoxes(const Box& box) {
|
|
|
+ int minX = floorf(box.getMin()[0]);
|
|
|
+ int minY = floorf(box.getMin()[1]);
|
|
|
+ int minZ = floorf(box.getMin()[2]);
|
|
|
+ int maxX = floorf(box.getMax()[0]);
|
|
|
+ int maxY = floorf(box.getMax()[1]);
|
|
|
+ int maxZ = floorf(box.getMax()[2]);
|
|
|
+
|
|
|
+ List<Box> boxes;
|
|
|
+ for(int x = minX; x <= maxX; x++) {
|
|
|
+ for(int y = minY; y <= maxY; y++) {
|
|
|
+ for(int z = minZ; z <= maxZ; z++) {
|
|
|
+ Block::addBoxes(blocks.get(x, y, z), boxes,
|
|
|
+ Vector3(static_cast<float>(x),
|
|
|
+ static_cast<float>(y),
|
|
|
+ static_cast<float>(z)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return boxes;
|
|
|
+}
|
|
|
+
|
|
|
+static Vector3 limitMove(const Entity& e, Vector3 move) {
|
|
|
+ Box box = e.getBox();
|
|
|
+ List<Box> boxes = getBoxes(box.expand(move));
|
|
|
+ if(boxes.getLength() == 0) {
|
|
|
+ return move;
|
|
|
+ }
|
|
|
+ Vector3 realMove;
|
|
|
+
|
|
|
+ constexpr float step = 0.05f;
|
|
|
+ while(move[0] != 0.0f || move[1] != 0.0f || move[2] != 0.0f) {
|
|
|
+ for(int i = 0; i < 3; i++) {
|
|
|
+ Vector3 old = realMove;
|
|
|
+ if(move[i] > step) {
|
|
|
+ realMove[i] += step;
|
|
|
+ move[i] -= step;
|
|
|
+ } else if(move[i] < -step) {
|
|
|
+ realMove[i] -= step;
|
|
|
+ move[i] += step;
|
|
|
+ } else if(move[i] != 0.0f) {
|
|
|
+ realMove[i] += move[i];
|
|
|
+ move[i] = 0.0f;
|
|
|
+ }
|
|
|
+ Box moved = box.offset(realMove);
|
|
|
+ for(const Box& box : boxes) {
|
|
|
+ if(box.collidesWith(moved)) {
|
|
|
+ move[i] = 0.0f;
|
|
|
+ realMove = old;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return realMove;
|
|
|
+}
|
|
|
+
|
|
|
+void World::tick() {
|
|
|
+ for(Entity* e : entities) {
|
|
|
+ e->tick();
|
|
|
+ if(!e->skip) {
|
|
|
+ Vector3 move = limitMove(*e, e->getVelocity());
|
|
|
+ e->move(move);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static bool isAir(int x, int y, int z) {
|
|
|
+ return blocks.get(x, y, z) == 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void addCube(TypedBuffer<Triangle>& buffer, float x, float y, float z) {
|
|
|
+ Vector3 v000(x, y, z);
|
|
|
+ Vector3 v001(x, y, z + 1);
|
|
|
+ Vector3 v010(x, y + 1, z);
|
|
|
+ Vector3 v011(x, y + 1, z + 1);
|
|
|
+ Vector3 v100(x + 1, y, z);
|
|
|
+ Vector3 v101(x + 1, y, z + 1);
|
|
|
+ Vector3 v110(x + 1, y + 1, z);
|
|
|
+ Vector3 v111(x + 1, y + 1, z + 1);
|
|
|
+
|
|
|
+ Vector2 t1(0.1875f, 0.0f);
|
|
|
+ Vector2 t2(0.25f, 0.0f);
|
|
|
+ Vector2 t3(0.25f, 0.0625f);
|
|
|
+ Vector2 t4(0.1875f, 0.0625f);
|
|
|
+
|
|
|
+ if(isAir(x, y - 1, z)) {
|
|
|
+ Vector2 tb(0.125f, 0.0625f);
|
|
|
+ buffer.add(Triangle(Vertex(v000, Vector2(0.125f, 0.0f)),
|
|
|
+ Vertex(v100, t1), Vertex(v001, tb)));
|
|
|
+ buffer.add(
|
|
|
+ Triangle(Vertex(v100, t1), Vertex(v101, t4), Vertex(v001, tb)));
|
|
|
+ }
|
|
|
+ if(isAir(x, y + 1, z)) {
|
|
|
+ Vector2 tt(0.3125f, 0.0f);
|
|
|
+ buffer.add(
|
|
|
+ Triangle(Vertex(v010, t2), Vertex(v011, t3), Vertex(v110, tt)));
|
|
|
+ buffer.add(Triangle(Vertex(v110, tt), Vertex(v011, t3),
|
|
|
+ Vertex(v111, Vector2(0.3125f, 0.0625f))));
|
|
|
+ }
|
|
|
+ if(isAir(x - 1, y, z)) {
|
|
|
+ buffer.add(
|
|
|
+ Triangle(Vertex(v000, t4), Vertex(v001, t3), Vertex(v010, t1)));
|
|
|
+ buffer.add(
|
|
|
+ Triangle(Vertex(v001, t3), Vertex(v011, t2), Vertex(v010, t1)));
|
|
|
+ }
|
|
|
+ if(isAir(x + 1, y, z)) {
|
|
|
+ buffer.add(
|
|
|
+ Triangle(Vertex(v100, t3), Vertex(v110, t2), Vertex(v101, t4)));
|
|
|
+ buffer.add(
|
|
|
+ Triangle(Vertex(v101, t4), Vertex(v110, t2), Vertex(v111, t1)));
|
|
|
+ }
|
|
|
+ if(isAir(x, y, z + 1)) {
|
|
|
+ buffer.add(
|
|
|
+ Triangle(Vertex(v001, t4), Vertex(v101, t3), Vertex(v011, t1)));
|
|
|
+ buffer.add(
|
|
|
+ Triangle(Vertex(v111, t2), Vertex(v011, t1), Vertex(v101, t3)));
|
|
|
+ }
|
|
|
+ if(isAir(x, y, z - 1)) {
|
|
|
+ buffer.add(
|
|
|
+ Triangle(Vertex(v000, t3), Vertex(v010, t2), Vertex(v100, t4)));
|
|
|
+ buffer.add(
|
|
|
+ Triangle(Vertex(v110, t1), Vertex(v100, t4), Vertex(v010, t2)));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void rebuildRenderData() {
|
|
|
+ TypedBuffer<Triangle> buffer(100);
|
|
|
+ for(int x = 0; x < blocks.getSize(); x++) {
|
|
|
+ for(int y = 0; y < blocks.getHeight(); y++) {
|
|
|
+ for(int z = 0; z < blocks.getSize(); z++) {
|
|
|
+ if(!isAir(x, y, z)) {
|
|
|
+ addCube(buffer, x, y, z);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ mesh.build(buffer);
|
|
|
+ LOG_DEBUG("world render update");
|
|
|
+}
|
|
|
+
|
|
|
+void World::render() {
|
|
|
+ if(dirty) {
|
|
|
+ rebuildRenderData();
|
|
|
+ dirty = false;
|
|
|
+ }
|
|
|
+ texture.bindTo(0);
|
|
|
+ for(int x = -1; x <= 1; x++) {
|
|
|
+ for(int z = -1; z <= 1; z++) {
|
|
|
+ Engine::matrix
|
|
|
+ .translateTo(blocks.getSize() * x, 0.0f, blocks.getSize() * z)
|
|
|
+ .update();
|
|
|
+ mesh.draw();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int World::getHeight() {
|
|
|
+ return blocks.getHeight();
|
|
|
+}
|
|
|
+
|
|
|
+void World::setBlock(int x, int y, int z, Block::Id block) {
|
|
|
+ dirty = true;
|
|
|
+ blocks.set(x, y, z, block);
|
|
|
+}
|