123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- #include "world.h"
- #include "chunk.h"
- #include "threadpool.h"
-
- #include <cmath>
- #include <iostream>
- #include <thread>
-
- #include <GL/glew.h>
- #include <GL/gl.h>
-
- #define GLM_FORCE_RADIANS
- #include <glm/glm.hpp>
- #include <glm/gtc/type_ptr.hpp>
- #include <glm/gtc/matrix_transform.hpp>
-
- namespace vtk {
-
- World::World() {
- chunkSize = 16;
- voxelSize = 1.0f;
- voxelInfo.linkedWorld = this;
- voxelMath.linkedWorld = this;
- rebuildThreadActive = false;
- mLoadThreadActive = false;
- }
-
- bool World::isVoxelSolid(const int& x, const int& y, const int& z) {
- auto chunkPos = glm::ivec3(floor((float)x / (float)chunkSize),
- floor((float)y / (float)chunkSize),
- floor((float)z / (float)chunkSize));
- auto chunk = getChunk(chunkPos);
- if (chunk) //block is in nonexistant chunk
- return true;
-
- int relPosX = x - chunkPos.x * chunkSize;
- int relPosY = y - chunkPos.y * chunkSize;
- int relPosZ = z - chunkPos.z * chunkSize;
-
- if (!chunk->isLoaded()) return true;
- return chunk->isVoxelSolid(relPosX, relPosY, relPosZ);
- }
-
- bool World::setVoxelType(const int& x, const int& y, const int& z, const unsigned& type, const bool& updateChunk) {
- auto chunkPos = glm::ivec3(floor((float)x / (float)chunkSize), floor((float)y / (float)chunkSize), floor((float)z / (float)chunkSize));
- auto chunk = getChunk(chunkPos);
- if (!chunk) return false;
-
- int relPosX = x - chunkPos.x * chunkSize;
- int relPosY = y - chunkPos.y * chunkSize;
- int relPosZ = z - chunkPos.z * chunkSize;
-
- chunk->setVoxelType(relPosX, relPosY, relPosZ, type, updateChunk);
- return true;
- }
-
- unsigned World::getVoxelType(const glm::ivec3& pos) {
- auto chunkPos = glm::ivec3(floor((float)pos.x / (float)chunkSize),
- floor((float)pos.y / (float)chunkSize),
- floor((float)pos.z / (float)chunkSize));
- Chunk* chunk;
- if (!mChunks.find(chunkPos, chunk)) {
- return 0;
- }
-
- int relPosX = pos.x - chunkPos.x * chunkSize;
- int relPosY = pos.y - chunkPos.y * chunkSize;
- int relPosZ = pos.z - chunkPos.z * chunkSize;
-
- return chunk->getVoxelType((unsigned)relPosX, (unsigned)relPosY, (unsigned)relPosZ);
- }
-
-
- Chunk* World::makeChunk(const int& x, const int& y, const int& z, bool insertAfter) {
- auto pos = glm::ivec3(x, y, z);
-
- Chunk* chunk;
- if (mChunks.find(pos, chunk)) { //chunk already exists
- return chunk;
- }
-
- chunk = new Chunk(*this);
- chunk->setPos(pos);
-
- if (insertAfter) insertChunk(chunk);
- return chunk;
- }
-
- bool World::generateChunk(const int& x, const int& y, const int& z) {
- auto chunkMade = makeChunk(x,y,z, false);
- if (chunkMade != nullptr) {
- terrain.generateChunk(chunkMade);
- //queue this chunk for geometry update
- queueChunkUpdate(x,y,z);
-
- //queue the neighboring 6 chunks. the queue functions throws them out
- // if they don't exist
- queueChunkUpdate(x+1,y,z);
- queueChunkUpdate(x-1,y,z);
- queueChunkUpdate(x,y+1,z);
- queueChunkUpdate(x,y-1,z);
- queueChunkUpdate(x,y,z+1);
- queueChunkUpdate(x,y,z-1);
- }
- insertChunk(chunkMade);
- return chunkMade;
- }
-
- bool World::insertChunk(Chunk* chunk) {
- mChunks.insert(chunk->getPos(), chunk);
- mChunkMeshes.emplace(chunk->getPos(), ChunkMesh(*this, chunk->getPos()));
- return true;
- }
-
-
- Chunk* World::getChunk(const glm::ivec3& pos) {
- Chunk* chunk;
- if (mChunks.find(pos, chunk)) return chunk;
- else return nullptr;
- }
-
- void World::queueChunkUpdate(const int& x, const int& y, const int& z, const bool& back) {
- queueChunkUpdate(glm::ivec3(x,y,z));
- }
-
- void World::queueChunkUpdate(const glm::ivec3& pos, const bool& back) {
- if (!getChunk(pos)) return; //chunk doesn't exist
- for (auto& i : mChunkUpdateQueue) {
- if (i == pos) return; //chunk is already in queue, we don't need to update multiple times
- }
-
- if (back) {
- mChunkUpdateQueue.push_back(pos);
- } else {
- mChunkUpdateQueue.push_front(pos);
- }
- }
-
- void World::queueChunkLoad(const glm::ivec3 &pos) {
- if (getChunk(pos)) return; //chunk already exists
- for (auto& i : mChunkLoadQueue) {
- if (i == pos) return;
- }
-
- makeChunk(pos.x, pos.y, pos.z);
- mChunkLoadQueue.push_back(pos);
- }
-
- void World::draw() {
- for (auto& i : mChunkMeshes) {
- glm::mat4 modelMat = glm::translate(glm::mat4(), glm::vec3((float)i.first.x * 16,
- (float)i.first.y * 16,
- (float)i.first.z * 16
- ));
-
- glUniformMatrix4fv(modelMatUni, 1, GL_FALSE, glm::value_ptr(modelMat));
- i.second.draw();
- }
- }
-
- void World::update() {
- if (!rebuildThreadActive && !mChunkUpdateQueue.empty( )) {
- auto updatefunc = [&]() {
- while (!mChunkUpdateQueue.empty()) {
- auto& pos = mChunkUpdateQueue.back();
- auto& mesh = mChunkMeshes.find(pos)->second;
- mChunkUpdateQueue.pop_back();
- if (!mesh.rebuildChunkGeometry())
- queueChunkUpdate(pos);
- }
- rebuildThreadActive = false;
- };
-
- rebuildThreadActive = true;
- ThreadPool::getInstance().addJob(updatefunc);
- }
-
- if (!mLoadThreadActive && !mChunkLoadQueue.empty()) {
- auto loadFunc = [&]() {
- while (!mChunkLoadQueue.empty()) {
- auto& pos = mChunkLoadQueue.back();
- generateChunk(pos.x, pos.y, pos.z);
- mChunkLoadQueue.pop_back();
- }
- mLoadThreadActive = false;
- };
-
- mLoadThreadActive = true;
- ThreadPool::getInstance().addJob(loadFunc);
- }
- }
-
- void World::forceGlobalGeometryUpdate() {
- int chunkCount = 1;
- chunkCount = 1;
- for (auto& i : mChunkMeshes) {
- std::cout << "\rUpdating chunk geometry, but better (" << chunkCount << "/" << mChunkMeshes.size() << ")" << std::flush;
- i.second.rebuildChunkGeometry();
- i.second.updateGeometry();
- ++chunkCount;
- }
- }
-
- void World::queueChunkLoadsAroundPoint(const glm::vec3 &point, const int &chunkRadius) {
- glm::ivec3 chunkPoint = point / 16.0f;
- for (int z = -chunkRadius; z <= chunkRadius; ++z) {
- for (int x = -chunkRadius; x <= chunkRadius; ++x) {
- if (z*z + x*x <= chunkRadius * chunkRadius) {
- for (int y = 0; y < 8; ++y) {
- queueChunkLoad(glm::ivec3(x + chunkPoint.x, y, z + chunkPoint.z));
- }
- }
- }
- }
- }
-
- }
|