From 1055bb3b273f1250757f5687cf9c35ed39e5ae1a Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 4 Mar 2022 17:52:13 +0300 Subject: [PATCH] Fixed gravity --- voxel_engine.cpp | 326 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+) create mode 100644 voxel_engine.cpp diff --git a/voxel_engine.cpp b/voxel_engine.cpp new file mode 100644 index 00000000..0b2e3b30 --- /dev/null +++ b/voxel_engine.cpp @@ -0,0 +1,326 @@ +// Install dependencies: +// sudo apt install libgl-dev libglew-dev libglfw3-dev libpng-dev libglm-dev +#include +#include + +#define GLEW_STATIC +#include +#include + +#include +#include + +// GLM +#include +#include +#include + +using namespace glm; + +#include "graphics/Shader.h" +#include "graphics/Texture.h" +#include "graphics/Mesh.h" +#include "graphics/VoxelRenderer.h" +#include "graphics/LineBatch.h" +#include "window/Window.h" +#include "window/Events.h" +#include "window/Camera.h" +#include "loaders/png_loading.h" +#include "voxels/voxel.h" +#include "voxels/Chunk.h" +#include "voxels/Chunks.h" +#include "voxels/Block.h" +#include "voxels/WorldGenerator.h" +#include "voxels/ChunksController.h" +#include "files/files.h" +#include "files/WorldFiles.h" +#include "lighting/LightSolver.h" +#include "lighting/Lightmap.h" +#include "lighting/Lighting.h" +#include "physics/Hitbox.h" +#include "physics/PhysicsSolver.h" + +#include "Assets.h" +#include "objects/Player.h" + +#include "declarations.h" +#include "world_render.h" + + +// Save all world data to files +void write_world(WorldFiles* wfile, Chunks* chunks){ + for (unsigned int i = 0; i < chunks->volume; i++){ + Chunk* chunk = chunks->chunks[i]; + if (chunk == nullptr) + continue; + wfile->put((const char*)chunk->voxels, chunk->x, chunk->z); + } + + wfile->write(); +} + +// Deleting world data from memory +void close_world(WorldFiles* wfile, Chunks* chunks){ + delete chunks; + delete wfile; +} + +#define CROUCH_SPEED_MUL 0.25f +#define CROUCH_SHIFT_Y -0.2f +#define RUN_SPEED_MUL 1.5f +#define CROUCH_ZOOM 0.9f +#define RUN_ZOOM 1.1f +#define C_ZOOM 0.1f +#define ZOOM_SPEED 16.0f +#define DEFAULT_AIR_DAMPING 0.1f +#define PLAYER_NOT_ONGROUND_DAMPING 10.0f +#define CAMERA_SHAKING_OFFSET 0.025f +#define CAMERA_SHAKING_OFFSET_Y 0.031f +#define CAMERA_SHAKING_SPEED 1.6f +#define CAMERA_SHAKING_DELTA_K 10.0f +#define FLIGHT_SPEED_MUL 5.0f +#define JUMP_FORCE 7.0f + +void update_controls(PhysicsSolver* physics, + Chunks* chunks, + Player* player, + float delta){ + + if (Events::jpressed(GLFW_KEY_ESCAPE)){ + Window::setShouldClose(true); + } + if (Events::jpressed(GLFW_KEY_TAB)){ + Events::toogleCursor(); + } + + for (int i = 1; i < 10; i++){ + if (Events::jpressed(GLFW_KEY_0+i)){ + player->choosenBlock = i; + } + } + + // Controls + Camera* camera = player->camera; + Hitbox* hitbox = player->hitbox; + bool sprint = Events::pressed(GLFW_KEY_LEFT_CONTROL); + bool shift = Events::pressed(GLFW_KEY_LEFT_SHIFT) && hitbox->grounded && !sprint; + bool zoom = Events::pressed(GLFW_KEY_C); + + float speed = player->speed; + if (player->flight){ + speed *= FLIGHT_SPEED_MUL; + } + int substeps = (int)(delta * 1000); + substeps = (substeps <= 0 ? 1 : (substeps > 100 ? 100 : substeps)); + physics->step(chunks, hitbox, delta, substeps, shift, player->flight ? 0.0f : 1.0f); + camera->position.x = hitbox->position.x; + camera->position.y = hitbox->position.y + 0.5f; + camera->position.z = hitbox->position.z; + + // Camera shaking + player->interpVel = player->interpVel * (1.0f - delta * 5) + hitbox->velocity * delta * 0.1f; + if (hitbox->grounded && player->interpVel.y < 0.0f){ + player->interpVel.y *= -30.0f; + } + float factor = hitbox->grounded ? length(vec2(hitbox->velocity.x, hitbox->velocity.z)) : 0.0f; + player->cameraShakingTimer += delta * factor * CAMERA_SHAKING_SPEED; + float shakeTimer = player->cameraShakingTimer; + player->cameraShaking = player->cameraShaking * (1.0f - delta * CAMERA_SHAKING_DELTA_K) + factor * delta * CAMERA_SHAKING_DELTA_K; + camera->position += camera->right * sin(shakeTimer) * CAMERA_SHAKING_OFFSET * player->cameraShaking; + camera->position += camera->up * abs(cos(shakeTimer)) * CAMERA_SHAKING_OFFSET_Y * player->cameraShaking; + camera->position -= min(player->interpVel * 0.05f, 1.0f); + + if (Events::jpressed(GLFW_KEY_F)){ + player->flight = !player->flight; + } + + // Field of view manipulations + float dt = min(1.0f, delta * ZOOM_SPEED); + if (dt > 1.0f) + dt = 1.0f; + float zoomValue = 1.0f; + if (shift){ + speed *= CROUCH_SPEED_MUL; + camera->position.y += CROUCH_SHIFT_Y; + zoomValue = CROUCH_ZOOM; + } else if (sprint){ + speed *= RUN_SPEED_MUL; + zoomValue = RUN_ZOOM; + } + if (zoom) + zoomValue *= C_ZOOM; + camera->zoom = zoomValue * dt + camera->zoom * (1.0f - dt); + + if (Events::pressed(GLFW_KEY_SPACE) && hitbox->grounded){ + hitbox->velocity.y = JUMP_FORCE; + } + + vec3 dir(0,0,0); + if (Events::pressed(GLFW_KEY_W)){ + dir.x += camera->dir.x; + dir.z += camera->dir.z; + } + if (Events::pressed(GLFW_KEY_S)){ + dir.x -= camera->dir.x; + dir.z -= camera->dir.z; + } + if (Events::pressed(GLFW_KEY_D)){ + dir.x += camera->right.x; + dir.z += camera->right.z; + } + if (Events::pressed(GLFW_KEY_A)){ + dir.x -= camera->right.x; + dir.z -= camera->right.z; + } + + hitbox->linear_damping = DEFAULT_AIR_DAMPING; + if (player->flight){ + hitbox->linear_damping = PLAYER_NOT_ONGROUND_DAMPING; + hitbox->velocity.y *= 1.0f - delta * 9; + if (Events::pressed(GLFW_KEY_SPACE)){ + hitbox->velocity.y += speed * delta * 9; + } + if (Events::pressed(GLFW_KEY_LEFT_SHIFT)){ + hitbox->velocity.y -= speed * delta * 9; + } + } + if (length(dir) > 0.0f){ + dir = normalize(dir); + + if (!hitbox->grounded) + hitbox->linear_damping = PLAYER_NOT_ONGROUND_DAMPING; + + hitbox->velocity.x += dir.x * speed * delta * 9; + hitbox->velocity.z += dir.z * speed * delta * 9; + } + + if (Events::_cursor_locked){ + player->camY += -Events::deltaY / Window::height * 2; + player->camX += -Events::deltaX / Window::height * 2; + + if (player->camY < -radians(89.0f)){ + player->camY = -radians(89.0f); + } + if (player->camY > radians(89.0f)){ + player->camY = radians(89.0f); + } + + camera->rotation = mat4(1.0f); + camera->rotate(player->camY, player->camX, 0); + } +} + +void update_interaction(Chunks* chunks, PhysicsSolver* physics, Player* player, Lighting* lighting){ + Camera* camera = player->camera; + vec3 end; + vec3 norm; + vec3 iend; + voxel* vox = chunks->rayCast(camera->position, camera->front, 10.0f, end, norm, iend); + if (vox != nullptr){ + lineBatch->box(iend.x+0.5f, iend.y+0.5f, iend.z+0.5f, 1.005f,1.005f,1.005f, 0,0,0,0.5f); + + if (Events::jclicked(GLFW_MOUSE_BUTTON_1)){ + int x = (int)iend.x; + int y = (int)iend.y; + int z = (int)iend.z; + chunks->set(x,y,z, 0); + lighting->onBlockSet(x,y,z,0); + } + if (Events::jclicked(GLFW_MOUSE_BUTTON_2)){ + int x = (int)(iend.x)+(int)(norm.x); + int y = (int)(iend.y)+(int)(norm.y); + int z = (int)(iend.z)+(int)(norm.z); + if (!physics->isBlockInside(x,y,z, player->hitbox)){ + chunks->set(x, y, z, player->choosenBlock); + lighting->onBlockSet(x,y,z, player->choosenBlock); + } + } + } +} + +int WIDTH = 1280; +int HEIGHT = 720; + + +int main() { + setup_definitions(); + + Window::initialize(WIDTH, HEIGHT, "Window 2.0"); + Events::initialize(); + + std::cout << "-- loading assets" << std::endl; + Assets* assets = new Assets(); + int result = initialize_assets(assets); + if (result){ + delete assets; + Window::terminate(); + return result; + } + std::cout << "-- loading world" << std::endl; + + Camera *camera = new Camera(vec3(-320,255,32), radians(90.0f)); + WorldFiles *wfile = new WorldFiles("world/", REGION_VOL * (CHUNK_VOL * 2 + 8)); + Chunks *chunks = new Chunks(34,1,34, 0,0,0); + + + Player* player = new Player(vec3(camera->position), 4.0f, camera); + wfile->readPlayer(player); + camera->rotation = mat4(1.0f); + camera->rotate(player->camY, player->camX, 0); + + std::cout << "-- preparing systems" << std::endl; + + VoxelRenderer renderer(1024*1024); + PhysicsSolver physics(vec3(0,-9.8f*2.0f,0)); + Lighting lighting(chunks); + + init_renderer(); + + ChunksController chunksController(chunks, &lighting); + + float lastTime = glfwGetTime(); + float delta = 0.0f; + + long frame = 0; + + bool occlusion = false; + + glfwSwapInterval(1); + + std::cout << "-- initializing finished" << std::endl; + + while (!Window::isShouldClose()){ + frame++; + float currentTime = glfwGetTime(); + delta = currentTime - lastTime; + lastTime = currentTime; + + if (Events::jpressed(GLFW_KEY_O)){ + occlusion = !occlusion; + } + + update_controls(&physics, chunks, player, delta); + update_interaction(chunks, &physics, player, &lighting); + + chunks->setCenter(wfile, camera->position.x,0,camera->position.z); + chunksController._buildMeshes(&renderer, frame); + chunksController.loadVisible(wfile); + + draw_world(camera, assets, chunks, occlusion); + + Window::swapBuffers(); + Events::pullEvents(); + } + std::cout << "-- saving world" << std::endl; + + wfile->writePlayer(player); + write_world(wfile, chunks); + close_world(wfile, chunks); + + std::cout << "-- shutting down" << std::endl; + + delete assets; + finalize_renderer(); + Window::terminate(); + return 0; +}