Converted World's use of glm::vec3* to glm::vec3 to allow proper checks.
parent
a62cadb408
commit
5f6c663003
|
@ -66,6 +66,6 @@ add_executable(zeus
|
|||
zeus/lua_api/LuaParser.h
|
||||
zeus/lua_api/LRegisterBlock.cpp
|
||||
zeus/lua_api/LRegisterBlock.h
|
||||
)
|
||||
zeus/engine/iVec3.h)
|
||||
|
||||
target_link_libraries(zeus ${OPENGL_gl_LIBRARY} glfw libGLEW.so pthread lua dl)
|
|
@ -22,7 +22,7 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
game->initialize(renderer);
|
||||
|
||||
boot.elapsed();
|
||||
boot.printElapsedSeconds();
|
||||
|
||||
//Game Loop
|
||||
while (!renderer->getWindow()->getShouldClose()) {
|
||||
|
@ -43,7 +43,9 @@ int main(int argc, char* argv[]) {
|
|||
game->draw();
|
||||
renderer->end();
|
||||
|
||||
// t.elapsedMs(); //Print frame time
|
||||
if (t.elapsedNs() / (double)1000000 >= 20) {
|
||||
t.printElapsedMs(); //Print frame time
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -89,4 +89,8 @@ void Camera::update() {
|
|||
up = glm::normalize(glm::cross(right, front));
|
||||
}
|
||||
|
||||
glm::vec3 *Camera::getPosition() {
|
||||
return &position;
|
||||
}
|
||||
|
||||
Camera::~Camera() = default;
|
||||
|
|
|
@ -18,10 +18,11 @@ public:
|
|||
void keyControl(bool* keys, GLfloat delta);
|
||||
void mouseControl(double deltaX, double deltaY);
|
||||
|
||||
glm::vec3* getPosition();
|
||||
|
||||
glm::mat4 calculateViewMatrix();
|
||||
|
||||
~Camera();
|
||||
|
||||
private:
|
||||
glm::vec3 position;
|
||||
|
||||
|
|
|
@ -9,26 +9,21 @@ Timer::Timer(const char* name) {
|
|||
start = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
void Timer::elapsedNs() {
|
||||
auto finish = std::chrono::high_resolution_clock::now();
|
||||
|
||||
long elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count();
|
||||
|
||||
printf("%s took %ld ns.\n", this->name, elapsed);
|
||||
}
|
||||
|
||||
void Timer::elapsedMs() {
|
||||
auto finish = std::chrono::high_resolution_clock::now();
|
||||
|
||||
double elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count() / (double)1000000;
|
||||
|
||||
printf("%s took %.2f ms.\n", this->name, elapsed);
|
||||
}
|
||||
|
||||
void Timer::elapsed() {
|
||||
long Timer::elapsedNs() {
|
||||
auto finish = std::chrono::high_resolution_clock::now();
|
||||
long elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count();
|
||||
return elapsed;
|
||||
};
|
||||
|
||||
double elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count() / (double)1000000 / (double)1000;
|
||||
|
||||
printf("%s took %.2f secs.\n", this->name, elapsed);
|
||||
void Timer::printElapsedNs() {
|
||||
printf("%s took %ld ns.\n", this->name, elapsedNs());
|
||||
}
|
||||
|
||||
void Timer::printElapsedMs() {
|
||||
printf("%s took %.2f ms.\n", this->name, elapsedNs() / (double)1000000);
|
||||
}
|
||||
|
||||
void Timer::printElapsedSeconds() {
|
||||
printf("%s took %.2f secs.\n", this->name, elapsedNs() / (double)1000000 / (double)1000);
|
||||
}
|
|
@ -12,9 +12,11 @@ class Timer {
|
|||
public:
|
||||
explicit Timer(const char* name);
|
||||
|
||||
void elapsedNs();
|
||||
void elapsedMs();
|
||||
void elapsed(); //Seconds
|
||||
long elapsedNs();
|
||||
|
||||
void printElapsedNs();
|
||||
void printElapsedMs();
|
||||
void printElapsedSeconds(); //Seconds
|
||||
private:
|
||||
const char* name;
|
||||
std::chrono::high_resolution_clock::time_point start;
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
//
|
||||
// Created by aurailus on 19/12/18.
|
||||
//
|
||||
|
||||
#ifndef ZEUS_IVEC3_H
|
||||
#define ZEUS_IVEC3_H
|
||||
|
||||
struct iVec3 {
|
||||
int x, y, z;
|
||||
|
||||
iVec3() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
}
|
||||
|
||||
iVec3(int x, int y, int z) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
// iVec3(int n) {
|
||||
// this->x = n;
|
||||
// this->y = n;
|
||||
// this->z = n;
|
||||
// }
|
||||
};
|
||||
|
||||
#endif //ZEUS_IVEC3_H
|
||||
|
||||
namespace std {
|
||||
template<> struct hash<iVec3> {
|
||||
std::size_t operator()(const iVec3 &k) const {
|
||||
return (k.x * 97 + k.y) * 89 + k.z;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct less<iVec3> {
|
||||
bool operator()(const iVec3 &a, const iVec3 &b) const {
|
||||
if (a.x < b.x) return true;
|
||||
if (a.y < b.y) return true;
|
||||
if (a.z < b.z) return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct equal_to<iVec3> {
|
||||
bool operator()(const iVec3 &a, const iVec3 &b) const {
|
||||
return (a.x == b.x && a.y == b.y && a.z == b.z);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -59,7 +59,7 @@ void MeshGenerator::build(BlockChunk* chunk, BlockAtlas* atlas,
|
|||
vertices.shrink_to_fit();
|
||||
indices.shrink_to_fit();
|
||||
|
||||
// t.elapsedMs();
|
||||
// t.printElapsedMs();
|
||||
}
|
||||
|
||||
void MeshGenerator::addFaces(glm::vec3 &offset, vector<float>* vertices, vector<unsigned int>* indices, vector<MeshPart*>* meshParts) {
|
||||
|
|
|
@ -26,16 +26,14 @@ void GameInstance::initialize(Renderer* renderer) {
|
|||
//The world requires the blockAtlas for meshing and handling inputs.
|
||||
world = new World(blockAtlas);
|
||||
|
||||
int SIZE = 16;
|
||||
for (int i = -SIZE; i < SIZE; i++) {
|
||||
for (int j = -4; j < 4; j++) {
|
||||
for (int k = -SIZE; k < SIZE; k++) {
|
||||
world->genChunk(new glm::vec3(i, j, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// genChunks(world);
|
||||
// int SIZE = 8;
|
||||
// for (int i = -SIZE; i < SIZE; i++) {
|
||||
// for (int j = -4; j < 4; j++) {
|
||||
// for (int k = -SIZE; k < SIZE; k++) {
|
||||
// world->genChunk(glm::vec3(i, j, k));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
void GameInstance::update(GLfloat deltaTime) {
|
||||
|
@ -46,6 +44,21 @@ void GameInstance::update(GLfloat deltaTime) {
|
|||
camera->mouseControl(window->getDeltaX(), window->getDeltaY());
|
||||
|
||||
world->update();
|
||||
|
||||
glm::vec3 chunk = *camera->getPosition();
|
||||
chunk.x = round(chunk.x / 16);
|
||||
chunk.y = round(chunk.y / 16);
|
||||
chunk.z = round(chunk.z / 16);
|
||||
|
||||
int SIZE = 32;
|
||||
for (int i = -SIZE; i < SIZE; i++) {
|
||||
for (int j = -4; j < 4; j++) {
|
||||
for (int k = -SIZE; k < SIZE; k++) {
|
||||
glm::vec3 adjustedPos(i + chunk.x, j + chunk.y, k + chunk.z);
|
||||
world->genChunk(adjustedPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameInstance::draw() {
|
||||
|
|
|
@ -14,12 +14,14 @@ World::World(BlockAtlas *atlas) {
|
|||
blockAtlas = atlas;
|
||||
}
|
||||
|
||||
void World::genChunk(glm::vec3* pos) {
|
||||
chunkGenQueue.insert(pos);
|
||||
void World::genChunk(glm::vec3 pos) {
|
||||
if (!blockChunks.count(pos)) {
|
||||
chunkGenQueue.insert(pos);
|
||||
}
|
||||
}
|
||||
|
||||
void World::newChunk(glm::vec3* pos, BlockChunk *c) {
|
||||
blockChunks.insert(std::pair<glm::vec3*, BlockChunk*>(pos, c));
|
||||
void World::newChunk(glm::vec3 pos, BlockChunk *c) {
|
||||
blockChunks.insert(std::pair<glm::vec3, BlockChunk*>(pos, c));
|
||||
meshGenQueue.insert(pos);
|
||||
}
|
||||
|
||||
|
@ -34,9 +36,9 @@ void chunkGenThread(World::ChunkThreadData *t) {
|
|||
for (int ind = 0; ind < 4096; ind++) {
|
||||
ArrayTrans3D::indAssignVec(ind, &innerPos);
|
||||
|
||||
pos.x = innerPos.x + t->pos->x * CHUNK_SIZE;
|
||||
pos.y = innerPos.y + t->pos->y * CHUNK_SIZE;
|
||||
pos.z = innerPos.z + t->pos->z * CHUNK_SIZE;
|
||||
pos.x = innerPos.x + t->pos.x * CHUNK_SIZE;
|
||||
pos.y = innerPos.y + t->pos.y * CHUNK_SIZE;
|
||||
pos.z = innerPos.z + t->pos.z * CHUNK_SIZE;
|
||||
|
||||
double val = p.noise(pos.x / (double) 32, pos.z / (double) 32, 0) * 16 - pos.y;
|
||||
|
||||
|
@ -53,23 +55,19 @@ void meshGenThread(World::MeshThreadData *t) {
|
|||
t->done = true;
|
||||
}
|
||||
|
||||
void World::update() {
|
||||
int done = 0;
|
||||
//Generate block chunks
|
||||
void World::handleChunkGenQueue() {
|
||||
//Finish Block Gen threads
|
||||
for (auto iter = chunkGenThreads.begin(); iter != chunkGenThreads.end(); ) {
|
||||
ChunkThreadData* threadData = (*iter);
|
||||
|
||||
//If the threadData is done, create a BlockChunk and delete the threadData.
|
||||
if (threadData->done) {
|
||||
done++;
|
||||
// blockChunks.insert(std::pair<glm::vec3*, BlockChunk*>(threadData->pos, threadData->chunk));
|
||||
newChunk(threadData->pos, threadData->chunk);
|
||||
|
||||
delete threadData;
|
||||
|
||||
iter = chunkGenThreads.erase(iter);
|
||||
}
|
||||
//Otherwise ignore it and move to the next BlockChunk
|
||||
//Otherwise ignore it and move to the next BlockChunk
|
||||
else {
|
||||
iter++;
|
||||
}
|
||||
|
@ -80,7 +78,7 @@ void World::update() {
|
|||
//Get and remove the first position from the vector.
|
||||
auto it = chunkGenQueue.begin();
|
||||
chunkGenQueue.erase(chunkGenQueue.begin());
|
||||
glm::vec3* pos = (*it);
|
||||
glm::vec3 pos = (*it);
|
||||
|
||||
//Create a thread for it and add the threadData to the chunkGenThreads vector
|
||||
auto t = new ChunkThreadData(pos, blockAtlas);
|
||||
|
@ -89,12 +87,15 @@ void World::update() {
|
|||
t->thread = thread;
|
||||
chunkGenThreads.push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
void World::handleMeshGenQueue() {
|
||||
//Run through all of the active generation threads, and finish and remove the ones that are ready to be finished.
|
||||
//Then, spin up new threads when there is space in the meshGenThreads array and there are chunks waiting to be meshed.
|
||||
|
||||
//Create MeshChunks for the finished threads.
|
||||
Timer applyGlobal("Applying Meshes");
|
||||
|
||||
for (auto iter = meshGenThreads.begin(); iter != meshGenThreads.end(); ) {
|
||||
MeshThreadData* threadData = (*iter);
|
||||
|
||||
|
@ -104,22 +105,24 @@ void World::update() {
|
|||
|
||||
auto meshChunk = new MeshChunk();
|
||||
meshChunk->build(threadData->vertices, threadData->indices);
|
||||
meshChunk->setPosition(*(threadData->pos) * glm::vec3(CHUNK_SIZE));
|
||||
|
||||
meshChunks.insert(std::pair<glm::vec3*, MeshChunk*>(threadData->pos, meshChunk));
|
||||
glm::vec3 pos = glm::vec3(threadData->pos.x * CHUNK_SIZE, threadData->pos.y * CHUNK_SIZE, threadData->pos.z * CHUNK_SIZE);
|
||||
meshChunk->setPosition(pos);
|
||||
|
||||
// apply.elapsedMs();
|
||||
meshChunks.insert(std::pair<glm::vec3, MeshChunk*>(threadData->pos, meshChunk));
|
||||
|
||||
// apply.printElapsedMs();
|
||||
|
||||
delete threadData;
|
||||
iter = meshGenThreads.erase(iter);
|
||||
}
|
||||
//Otherwise ignore it and move to the next MeshChunk
|
||||
//Otherwise ignore it and move to the next MeshChunk
|
||||
else {
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
// applyGlobal.elapsedMs();
|
||||
// applyGlobal.printElapsedMs();
|
||||
|
||||
//Begin processing queued chunks if there are chunks to be processed and there's room for more threads.
|
||||
while (!meshGenQueue.empty() && meshGenThreads.size() < MAX_MESH_GEN_THREADS) {
|
||||
|
@ -127,7 +130,7 @@ void World::update() {
|
|||
//Get and remove the first position from the vector.
|
||||
auto it = meshGenQueue.begin();
|
||||
meshGenQueue.erase(meshGenQueue.begin());
|
||||
glm::vec3* pos = (*it);
|
||||
glm::vec3 pos = (*it);
|
||||
|
||||
//Create a thread for it and add the threadData to the meshGenThreads vector
|
||||
auto t = new MeshThreadData(pos, blockChunks.at(pos), blockAtlas);
|
||||
|
@ -138,11 +141,16 @@ void World::update() {
|
|||
}
|
||||
}
|
||||
|
||||
std::map<glm::vec3*, MeshChunk*>* World::getMeshChunks() {
|
||||
void World::update() {
|
||||
handleChunkGenQueue();
|
||||
handleMeshGenQueue();
|
||||
}
|
||||
|
||||
std::unordered_map<glm::vec3, MeshChunk*, World::vec3cmp>* World::getMeshChunks() {
|
||||
return &meshChunks;
|
||||
}
|
||||
|
||||
World::MeshThreadData::MeshThreadData(glm::vec3 *pos, BlockChunk *chunk, BlockAtlas *atlas) {
|
||||
World::MeshThreadData::MeshThreadData(glm::vec3 pos, BlockChunk *chunk, BlockAtlas *atlas) {
|
||||
this->pos = pos;
|
||||
this->chunk = chunk;
|
||||
this->atlas = atlas;
|
||||
|
@ -152,15 +160,13 @@ World::MeshThreadData::MeshThreadData(glm::vec3 *pos, BlockChunk *chunk, BlockAt
|
|||
}
|
||||
|
||||
World::MeshThreadData::~MeshThreadData() {
|
||||
//Not delete this->pos because it is used in the MeshChunk and BlockChunk vectors.
|
||||
//delete pos
|
||||
delete vertices;
|
||||
delete indices;
|
||||
//Delete the thread, when the deconstructor is called, the thread is done.
|
||||
delete thread;
|
||||
}
|
||||
|
||||
World::ChunkThreadData::ChunkThreadData(glm::vec3 *pos, BlockAtlas *atlas) {
|
||||
World::ChunkThreadData::ChunkThreadData(glm::vec3 pos, BlockAtlas *atlas) {
|
||||
this->pos = pos;
|
||||
this->atlas = atlas;
|
||||
this->done = false;
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
#ifndef GLPROJECT_WORLD_H
|
||||
#define GLPROJECT_WORLD_H
|
||||
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <iostream>
|
||||
#include <gtc/type_ptr.hpp>
|
||||
#include <vec3.hpp>
|
||||
#include <thread>
|
||||
#include <bits/unordered_map.h>
|
||||
|
||||
#include "BlockChunk.h"
|
||||
#include "MeshChunk.h"
|
||||
|
@ -18,24 +18,30 @@
|
|||
|
||||
class World {
|
||||
public:
|
||||
struct vec3cmp {
|
||||
size_t operator()(const glm::vec3& k)const {
|
||||
return std::hash<float>()(k.x) ^ std::hash<float>()(k.y) ^ std::hash<float>()(k.z);
|
||||
}
|
||||
};
|
||||
|
||||
World();
|
||||
explicit World(BlockAtlas* atlas);
|
||||
|
||||
void genChunk(glm::vec3* pos);
|
||||
void newChunk(glm::vec3* pos, BlockChunk* c);
|
||||
void genChunk(glm::vec3 pos);
|
||||
void newChunk(glm::vec3 pos, BlockChunk* c);
|
||||
|
||||
void update();
|
||||
|
||||
std::map<glm::vec3*, MeshChunk*>* getMeshChunks();
|
||||
std::unordered_map<glm::vec3, MeshChunk*, vec3cmp>* getMeshChunks();
|
||||
|
||||
~World() = default;
|
||||
|
||||
struct MeshThreadData {
|
||||
MeshThreadData(glm::vec3* pos, BlockChunk* chunk, BlockAtlas* atlas);
|
||||
MeshThreadData(glm::vec3 pos, BlockChunk* chunk, BlockAtlas* atlas);
|
||||
|
||||
std::thread* thread;
|
||||
|
||||
glm::vec3* pos;
|
||||
glm::vec3 pos;
|
||||
BlockChunk* chunk;
|
||||
BlockAtlas* atlas;
|
||||
|
||||
|
@ -48,11 +54,11 @@ public:
|
|||
};
|
||||
|
||||
struct ChunkThreadData {
|
||||
ChunkThreadData(glm::vec3* pos, BlockAtlas* atlas);
|
||||
ChunkThreadData(glm::vec3 pos, BlockAtlas* atlas);
|
||||
|
||||
std::thread* thread;
|
||||
|
||||
glm::vec3* pos;
|
||||
glm::vec3 pos;
|
||||
BlockAtlas* atlas;
|
||||
|
||||
bool done;
|
||||
|
@ -62,22 +68,22 @@ public:
|
|||
~ChunkThreadData();
|
||||
};
|
||||
private:
|
||||
//Note to self:
|
||||
//The same glm::vec3 pointer is used for the blockChunk and meshChunk maps. If discarding a block/meshChunk, keep
|
||||
//this in mind. If this needs to be changed later change the 'update' method.
|
||||
std::map<glm::vec3*, BlockChunk*> blockChunks;
|
||||
std::map<glm::vec3*, MeshChunk*> meshChunks;
|
||||
std::unordered_map<glm::vec3, BlockChunk*, vec3cmp> blockChunks;
|
||||
std::unordered_map<glm::vec3, MeshChunk*, vec3cmp> meshChunks;
|
||||
|
||||
void handleChunkGenQueue();
|
||||
void handleMeshGenQueue();
|
||||
|
||||
//TODO: Replace this BiQueueThreadArray model with a BiQueueThreadPool model (it's in the name)
|
||||
|
||||
//Chunk Gen BiQueue Variables
|
||||
const int MAX_CHUNK_GEN_THREADS = 16;
|
||||
std::unordered_set<glm::vec3*> chunkGenQueue;
|
||||
const int MAX_CHUNK_GEN_THREADS = 32;
|
||||
std::unordered_set<glm::vec3, vec3cmp> chunkGenQueue;
|
||||
std::vector<ChunkThreadData*> chunkGenThreads;
|
||||
|
||||
//Mesh Gen BiQueue Variables
|
||||
const int MAX_MESH_GEN_THREADS = 64;
|
||||
std::unordered_set<glm::vec3*> meshGenQueue;
|
||||
const int MAX_MESH_GEN_THREADS = 32;
|
||||
std::unordered_set<glm::vec3, vec3cmp> meshGenQueue;
|
||||
std::vector<MeshThreadData*> meshGenThreads;
|
||||
|
||||
BlockAtlas* blockAtlas;
|
||||
|
|
Loading…
Reference in New Issue