180 lines
5.6 KiB
C++
Executable File
180 lines
5.6 KiB
C++
Executable File
#include "Deer/VoxelWorld.h"
|
|
#include "Deer/Voxels/Chunk.h"
|
|
#include "Deer/Application.h"
|
|
|
|
#include "Deer/Components.h"
|
|
#include "Deer/Voxels/VoxelWorldData.h"
|
|
|
|
#include "DeerRender/Render/Render.h"
|
|
#include "DeerRender/Render/RenderUtils.h"
|
|
#include "DeerRender/Render/Texture.h"
|
|
#include "DeerRender/Voxels/VoxelWorldRenderData.h"
|
|
|
|
#include "Deer/Log.h"
|
|
#include "glm/glm.hpp"
|
|
#include "glm/gtc/matrix_transform.hpp"
|
|
#include "glm/gtc/matrix_inverse.hpp"
|
|
|
|
namespace Deer {
|
|
void VoxelWorld::bakeAmbientLight(int minX, int maxX, int minZ, int maxZ) {
|
|
int xPos = minX;
|
|
for (; xPos <= maxX; xPos++) {
|
|
int zPos = minZ;
|
|
for (; zPos <= maxZ; zPos++) {
|
|
LayerVoxel layer = readLayerVoxel(xPos, zPos);
|
|
uint16_t maxHeight = layer.height;
|
|
uint16_t minHeight = layer.ambient_light_height;
|
|
|
|
if (minHeight > layer.height)
|
|
minHeight = layer.height;
|
|
|
|
uint16_t maxHeightSorroundings = maxHeight;
|
|
for (int i = 0; i < 8; i++) {
|
|
int checkX = xPos + LAYER_CHECK_DIRS(X_AXIS, i);
|
|
int checkZ = zPos + LAYER_CHECK_DIRS(Y_AXIS, i);
|
|
|
|
LayerVoxel layer = readLayerVoxel(checkX, checkZ);
|
|
if (layer.height > maxHeightSorroundings)
|
|
maxHeightSorroundings = layer.height;
|
|
}
|
|
|
|
maxHeightSorroundings++;
|
|
if (maxHeightSorroundings >= CHUNK_SIZE_Y * worldProps.chunkSizeY)
|
|
maxHeightSorroundings = CHUNK_SIZE_Y * worldProps.chunkSizeY - 1;
|
|
|
|
ChunkID chunkID;
|
|
ChunkVoxelID chunkVoxelID;
|
|
|
|
// Depending if it's an edge we will add to queue to propagate the light
|
|
bool isPositionEdge =
|
|
(xPos == minX) || (xPos == maxX) ||
|
|
(zPos == minZ) || (zPos == maxZ);
|
|
|
|
if (xPos == 0 || zPos == 0 || xPos == CHUNK_SIZE_X * worldProps.chunkSizeX - 1
|
|
|| zPos == CHUNK_SIZE_Z * worldProps.chunkSizeZ - 1)
|
|
isPositionEdge = false;
|
|
|
|
// All light voxelsInfo under the max height must be put to 0 ambient light and above to 255
|
|
// I think this is optional
|
|
|
|
int yPos = minHeight;
|
|
if (!isPositionEdge) {
|
|
// Empty the ilumination
|
|
for (; yPos < maxHeight; yPos++) {
|
|
extractChunkCordinates(xPos, yPos, zPos, chunkID, chunkVoxelID);
|
|
Chunk& chunk = chunks[worldProps.getWorldChunkID(chunkID)];
|
|
VoxelLight& voxelLight = chunk.modLight(chunkVoxelID);
|
|
|
|
voxelLight.ambient_light = 0;
|
|
}
|
|
} else {
|
|
// Add to queue
|
|
for (; yPos < maxHeight; yPos++) {
|
|
extractChunkCordinates(xPos, yPos, zPos, chunkID, chunkVoxelID);
|
|
Chunk& chunk = chunks[worldProps.getWorldChunkID(chunkID)];
|
|
VoxelLight voxelLight = chunk.readLight(chunkVoxelID);
|
|
|
|
if (voxelLight.ambient_light > 0)
|
|
ambientLightPropagation.push(VoxelCordinates(xPos, yPos, zPos));
|
|
}
|
|
}
|
|
|
|
// Fill with light voxelsInfo and add queue to update light propagation
|
|
for (; yPos < maxHeightSorroundings; yPos++) {
|
|
extractChunkCordinates(xPos, yPos, zPos, chunkID, chunkVoxelID);
|
|
Chunk& chunk = chunks[worldProps.getWorldChunkID(chunkID)];
|
|
VoxelLight& voxelLight = chunk.modLight(chunkVoxelID);
|
|
|
|
voxelLight.ambient_light = 255;
|
|
ambientLightPropagation.push(VoxelCordinates(xPos, yPos, zPos));
|
|
}
|
|
|
|
modLayerVoxel(xPos, zPos).ambient_light_height = CHUNK_SIZE_Y * worldProps.chunkSizeY;
|
|
}
|
|
}
|
|
|
|
//Resolve ambient light propagation
|
|
while (!ambientLightPropagation.empty()) {
|
|
resolveNextAmbientLightPropagation();
|
|
}
|
|
}
|
|
|
|
void VoxelWorld::bakeAmbientLightFromPoint(int x, int z) {
|
|
int minX = x - 16;
|
|
int maxX = x + 16;
|
|
|
|
int minZ = z - 16;
|
|
int maxZ = z + 16;
|
|
|
|
minX = (minX < 0) ? 0 : minX;
|
|
maxX = (maxX >= worldProps.chunkSizeX * CHUNK_SIZE_X) ? worldProps.chunkSizeX * CHUNK_SIZE_X - 1 : maxX;
|
|
|
|
minZ = (minZ < 0) ? 0 : minZ;
|
|
maxZ = (maxZ >= worldProps.chunkSizeZ * CHUNK_SIZE_Z) ? worldProps.chunkSizeZ * CHUNK_SIZE_Z - 1 : maxZ;
|
|
|
|
bakeAmbientLight(minX, maxX, minZ, maxZ);
|
|
}
|
|
|
|
void VoxelWorld::resolveNextAmbientLightPropagation() {
|
|
VoxelCordinates position = ambientLightPropagation.front();
|
|
ambientLightPropagation.pop();
|
|
|
|
LayerVoxel& layerVoxel = modLayerVoxel(position.x, position.z);
|
|
|
|
if (layerVoxel.ambient_light_height > position.y)
|
|
layerVoxel.ambient_light_height = position.y;
|
|
|
|
VoxelLight currentLight = readLight(position);
|
|
bool solidCheck[6] = { false };
|
|
// Check for every simple dir
|
|
for (int i = 0; i < 6; i++) {
|
|
VoxelCordinates next(
|
|
position.x + NORMAL_DIR(X_AXIS, i),
|
|
position.y + NORMAL_DIR(Y_AXIS, i),
|
|
position.z + NORMAL_DIR(Z_AXIS, i)
|
|
);
|
|
|
|
Voxel nextVoxel = readVoxel(next);
|
|
solidCheck[i] = nextVoxel.isVoxelType();
|
|
if (solidCheck[i])
|
|
continue;
|
|
|
|
VoxelLight& nextLight = modLight(next);
|
|
int nextLightMinValue = currentLight.ambient_light - LIGHT_PROPAGATION_SIMPLE_FALL;
|
|
|
|
if (nextLight.ambient_light < nextLightMinValue) {
|
|
nextLight.ambient_light = nextLightMinValue;
|
|
ambientLightPropagation.push(next);
|
|
}
|
|
}
|
|
|
|
return;
|
|
// TODO
|
|
// Check for every complex dir
|
|
for (int i = 0; i < 6; i++) {
|
|
int cDir0 = LIGHT_PROPAGATION_COMPLEX_DIR(0, i);
|
|
int cDir1 = LIGHT_PROPAGATION_COMPLEX_DIR(1, i);
|
|
|
|
if (solidCheck[cDir0] || solidCheck[cDir1])
|
|
continue;
|
|
|
|
VoxelCordinates next(
|
|
NORMAL_DIR(X_AXIS, cDir0) + NORMAL_DIR(X_AXIS, cDir1),
|
|
NORMAL_DIR(Y_AXIS, cDir0) + NORMAL_DIR(Y_AXIS, cDir1),
|
|
NORMAL_DIR(Z_AXIS, cDir0) + NORMAL_DIR(Z_AXIS, cDir1)
|
|
);
|
|
|
|
Voxel nextVoxel = readVoxel(next);
|
|
if (nextVoxel.isVoxelType())
|
|
continue;
|
|
|
|
VoxelLight& nextLight = modLight(next);
|
|
int nextLightMinValue = currentLight.ambient_light - LIGHT_PROPAGATION_COMPLEX_FALL;
|
|
|
|
if (nextLight.ambient_light < nextLightMinValue) {
|
|
nextLight.ambient_light = nextLightMinValue;
|
|
ambientLightPropagation.push(next);
|
|
}
|
|
}
|
|
}
|
|
} |