Browse Source

100% untested heightmap implementation

testing
totallyfake 1 year ago
parent
commit
d657be44f4
8 changed files with 68 additions and 14 deletions
  1. 2
    0
      include/chunk.h
  2. 9
    2
      include/heightmap.h
  3. 5
    1
      src/chunk.cpp
  4. 7
    1
      src/graphics/voxelmodel.cpp
  5. 29
    7
      src/heightmap.cpp
  6. 3
    2
      src/scenes/testscene.cpp
  7. 3
    0
      src/terraingen.cpp
  8. 10
    1
      src/world.cpp

+ 2
- 0
include/chunk.h View File

@@ -9,6 +9,7 @@
namespace vtk {

class World;
class HeightMap;

class Chunk {
friend class World;
@@ -22,6 +23,7 @@ public:
glm::ivec3 getWorldCoords(const int& x, const int& y, const int& z);
unsigned getLightLevel(const glm::ivec3& pos);
unsigned getLightPacked(const glm::ivec3& pos);
HeightMap* getHeightMap();

void setPos(const glm::ivec3& pos);
glm::ivec3 getPos();

+ 9
- 2
include/heightmap.h View File

@@ -2,22 +2,29 @@

#include <glm/glm.hpp>
#include <array>
#include <utility>

#include "concurrentqueue.h"

namespace vtk {

class World;

class HeightMap {
public:
HeightMap(const glm::ivec2& pos);
HeightMap(const glm::ivec2& pos, World& world);
glm::ivec2 getPos();

int getHeight(const glm::ivec2& pos);
bool pushUpdate(const glm::ivec3& pos, const bool& destroyed);
void flushUpdates(); // called from worker thread
protected:
void setHeight(const::glm::ivec3& pos);
World& mWorld;
glm::ivec2 mPos;
std::array<int, (16*16)> mHeights; //stores 16*16 heightmap
moodycamel::ConcurrentQueue<glm::ivec3> mUpdateQueue;
moodycamel::ConcurrentQueue<std::pair<glm::ivec3, bool>> mUpdateQueue;
};

}

+ 5
- 1
src/chunk.cpp View File

@@ -51,7 +51,7 @@ bool Chunk::isVoxelSolid(const int& x, const int& y, const int& z) {
mPos.z * 16 + z);
}

return (getVoxelType((unsigned)x,(unsigned)y,(unsigned)z) != 0);
return !mLinkedWorld.voxelInfo.isTransparent(getVoxelType((unsigned)x, (unsigned)y, (unsigned)z));
}

void Chunk::setVoxelType(const int& x, const int& y, const int& z, const unsigned& type, const bool& update) {
@@ -95,6 +95,10 @@ unsigned Chunk::getLightPacked(const glm::ivec3 &pos) {
return 0xFFFFFFFF;
}

HeightMap* Chunk::getHeightMap() {
return mLinkedWorld.getHeightMap(glm::ivec2(mPos.x,mPos.z));
}

void Chunk::setPos(const glm::ivec3& pos) {
mPos = pos;
}

+ 7
- 1
src/graphics/voxelmodel.cpp View File

@@ -151,7 +151,13 @@ void VoxelModel::getFaceLighting(std::vector<unsigned>& lighting, const FaceDire
for (auto& i : face_vec) {
//TODO: Find a more elegant solution that a big switch case with if statements
//TODO: handle interpolation for verts that aren't on an edge

/*
A brief explanation of the following code
it looks at the position of each vertice in the face mesh, checks which corner it is
closeest too, and then ges the average of the 4 adjacent light values with the
average4 lambda
*/
unsigned vx = (i >> 8) & 0xF;
unsigned vy = (i >> 4) & 0xF;
unsigned vz = i & 0xF;

+ 29
- 7
src/heightmap.cpp View File

@@ -1,11 +1,15 @@
#include "heightmap.h"
#include "world.h"

namespace vtk {

HeightMap::HeightMap(const glm::ivec2& pos) :
mPos(pos)
HeightMap::HeightMap(const glm::ivec2& pos, World& world) :
mPos(pos),
mWorld(world)
{
for (int i = 0; i < mHeights.size(); ++i) {
mHeights[i] = 0x7FFFFFFF;
}
}

glm::ivec2 HeightMap::getPos() {
@@ -18,15 +22,33 @@ int HeightMap::getHeight(const glm::ivec2 &pos) {
}

bool HeightMap::pushUpdate(const glm::ivec3 &pos, const bool &destroyed) {
return mUpdateQueue.try_enqueue(pos);
return mUpdateQueue.try_enqueue(std::make_pair(pos, destroyed));
}

void HeightMap::flushUpdates() {
glm::ivec3 pos;
while (mUpdateQueue.try_dequeue(pos)) {
std::pair<glm::ivec3, bool> updateItem;
while (mUpdateQueue.try_dequeue(updateItem)) {
glm::ivec3& pos = updateItem.first;
int index = pos.x + (16 * pos.y);
mHeights[index] = pos.z;
int height = getHeight(glm::ivec2(pos.x, pos.z));
if (updateItem.second) { // if destroyed
if(height <= pos.y) { // if voxel is at the top of the heightmap
// search downward until the next solid voxel is reached
glm::ivec3 searchPos(pos.x + (mPos.x * 16), pos.y, pos.z + (mPos.y * 16));
while(mWorld.isVoxelSolid(searchPos.x, searchPos.y, searchPos.z)) {
--searchPos.y;
}
setHeight(searchPos);
}
} else { // if placed
if (height < pos.y)
setHeight(pos);
}
}
}

void HeightMap::setHeight(const glm::ivec3& pos) {
mHeights[pos.x + (16 * pos.z)] = pos.y;
}

}

+ 3
- 2
src/scenes/testscene.cpp View File

@@ -111,8 +111,9 @@ void TestScene::init() {
world.voxelInfo.setAllTextureIndexes(2, 1);
world.voxelInfo.setTextureIndex(2, FaceDirection::TOP, 2);

//world.voxelInfo.setTransparent(1, false);
//world.voxelInfo.setTransparent(2, false);
world.voxelInfo.setTransparent(0, true);
world.voxelInfo.setTransparent(1, false);
world.voxelInfo.setTransparent(2, false);

std::cout << std::endl;


+ 3
- 0
src/terraingen.cpp View File

@@ -22,6 +22,7 @@
#include "terrain/noise.h"
#include "terrain/ygradient.h"
#include "terrain/yturbulence.h"
#include "heightmap.h"

#include <iostream>
#include <time.h>
@@ -56,7 +57,9 @@ void TerrainGen::generateChunk(Chunk* chunk) {
} else {// block above is air
chunk->setVoxelType(i,j,k,1);
}
chunk->getHeightMap()->pushUpdate(glm::ivec3(i,(chunkPos.y * 16) + j, k),false);
} else {
chunk->getHeightMap()->pushUpdate(glm::ivec3(i,(chunkPos.y * 16) + j, k), true);
chunk->setVoxelType(i,j,k,0);
}
}

+ 10
- 1
src/world.cpp View File

@@ -129,7 +129,7 @@ HeightMap* World::getHeightMap(const glm::ivec2& pos) {
}

//else make a new one, add to map, and return
heightMap = new HeightMap(pos);
heightMap = new HeightMap(pos, *this);
mHeightMaps.insert(pos, heightMap);
return heightMap;
}
@@ -143,6 +143,8 @@ void World::queueChunkUpdate(const glm::ivec3& pos, const bool& highpriority) {
if (!chunk || chunk->isQueuedForMeshRebuild()) return;
chunk->setQueuedForMeshRebuild(true);

mHeightMapUpdateQueue.enqueue(glm::ivec2(pos.x, pos.z));
if (highpriority) { // queue for higher rebuild priority
mMeshUpdateQueueSoon.enqueue(pos);
return;
@@ -181,6 +183,12 @@ void World::update() {
mMeshUpdateQueue.size_approx() > 0)) {
auto updatefunc = [&]() {
glm::ivec3 pos;
glm::ivec2 hm_pos;
while (mHeightMapUpdateQueue.try_dequeue(hm_pos)) {
auto heightMap = getHeightMap(hm_pos);
heightMap->flushUpdates();
}
while (mMeshUpdateQueueSoon.try_dequeue(pos)) {
ChunkMesh* mesh;
mChunkMeshes.find(pos, mesh);
@@ -198,6 +206,7 @@ void World::update() {
}
getChunk(pos)->setQueuedForMeshRebuild(false);
}

rebuildThreadActive = false;
};


Loading…
Cancel
Save