Commit for 2020.07.17.7z

This commit is contained in:
mrq 2020-07-17 00:00:00 -05:00
parent 830566ab5f
commit e3e28a8910
7 changed files with 550 additions and 40 deletions

View File

@ -10,7 +10,7 @@ layout (location = 0) out vec4 outFragColor;
void fog( inout vec3 i ) { void fog( inout vec3 i ) {
vec3 color = vec3( 0, 0, 0 ); vec3 color = vec3( 0, 0, 0 );
float inner = 8, outer = 64; float inner = 8, outer = 32;
float distance = length(-inPositionEye); float distance = length(-inPositionEye);
float factor = (distance - inner) / (outer - inner); float factor = (distance - inner) / (outer - inner);
factor = clamp( factor, 0.0, 1.0 ); factor = clamp( factor, 0.0, 1.0 );
@ -46,7 +46,7 @@ void phong( inout vec3 i ) {
void main() { void main() {
outFragColor = texture(samplerColor, inUv); outFragColor = texture(samplerColor, inUv);
// phong(outFragColor.rgb); phong(outFragColor.rgb);
fog(outFragColor.rgb); fog(outFragColor.rgb);
// outFragColor.rgb = mix( outFragColor.rgb, inColor.rgb, inColor.a ); // outFragColor.rgb = mix( outFragColor.rgb, inColor.rgb, inColor.a );
outFragColor.rgb = outFragColor.rgb * inColor.rgb; outFragColor.rgb = outFragColor.rgb * inColor.rgb;

View File

@ -84,7 +84,7 @@ void ext::TerrainGenerator::generate( ext::Region& region ){
} }
*/ */
std::string base = region.getParent().getComponent<uf::Serializer>()["_config"]["hash"].asString(); std::string base = region.getParent().getComponent<uf::Serializer>()["_config"]["hash"].asString();
std::string filename = "./data/save/regions/" + base + "/" + std::to_string(location.x) + "." + std::to_string(location.y) + "." + std::to_string(location.z) + ".json"; std::string filename = "./data/save/" + base + "/regions/" + std::to_string(location.x) + "." + std::to_string(location.y) + "." + std::to_string(location.z) + ".json";
// old region, load save // old region, load save
if ( uf::string::exists( filename ) ) { if ( uf::string::exists( filename ) ) {
uf::Serializer save; save.readFromFile(filename); uf::Serializer save; save.readFromFile(filename);
@ -123,6 +123,22 @@ void ext::TerrainGenerator::generate( ext::Region& region ){
} }
// load failed / new region // load failed / new region
} }
// maze
/*
{
ext::Maze& maze = this->m_terrain->getComponent<ext::Maze>();
int ROW = this->m_location.z + (maze.WIDTH / 2) - 1;
int COL = this->m_location.x + (maze.LENGTH / 2) - 1;
auto value = maze( ROW, COL, 0 );
bool east = value & ext::Maze::EAST; // ROW + 1 < maze.WIDTH ? maze( ROW + 1, COL, 1 ) : 0;
bool west = value & ext::Maze::WEST; // ROW - 1 > 0 ? maze( ROW - 1, COL, 1 ) : 0;
bool north = value & ext::Maze::NORTH; // COL + 1 < maze.LENGTH ? maze( ROW, COL + 1, 1 ) : 0;
bool south = value & ext::Maze::SOUTH; // COL - 1 > 0 ? maze( ROW, COL - 1, 1 ) : 0;
std::cout << ROW << ", " << COL << " = " << value << "\t" << east << " " << west << " " << north << " " << south << std::endl;
}
*/
if ( this->m_voxels.id.rle.empty() ) { if ( this->m_voxels.id.rle.empty() ) {
double maxValue = 0.0; double maxValue = 0.0;
double base = 0; double base = 0;
@ -131,9 +147,9 @@ void ext::TerrainGenerator::generate( ext::Region& region ){
ext::TerrainVoxel::light_t raw_lighting[this->m_size.x][this->m_size.y][this->m_size.z]; ext::TerrainVoxel::light_t raw_lighting[this->m_size.x][this->m_size.y][this->m_size.z];
double raw_noise[this->m_size.x][this->m_size.y][this->m_size.z]; double raw_noise[this->m_size.x][this->m_size.y][this->m_size.z];
for ( int y = 0; y < this->m_size.y; ++y ) for ( uint y = 0; y < this->m_size.y; ++y )
for ( int z = 0; z < this->m_size.z; ++z ) for ( uint z = 0; z < this->m_size.z; ++z )
for ( int x = 0; x < this->m_size.x; ++x ) { for ( uint x = 0; x < this->m_size.x; ++x ) {
pod::Vector3d position = { pod::Vector3d position = {
transform.position.x - half_x, transform.position.y - half_y, transform.position.z - half_z transform.position.x - half_x, transform.position.y - half_y, transform.position.z - half_z
}; };
@ -145,14 +161,13 @@ void ext::TerrainGenerator::generate( ext::Region& region ){
} }
for ( int y = 0; y < this->m_size.y; ++y ) for ( uint y = 0; y < this->m_size.y; ++y )
for ( int z = 0; z < this->m_size.z; ++z ) for ( uint z = 0; z < this->m_size.z; ++z )
for ( int x = 0; x < this->m_size.x; ++x ) for ( uint x = 0; x < this->m_size.x; ++x )
base += raw_noise[x][y][z] / maxValue; base += raw_noise[x][y][z] / maxValue;
base /= this->m_size.x * this->m_size.y * this->m_size.z; base /= this->m_size.x * this->m_size.y * this->m_size.z;
uint partitions = this->m_modulus; uint partitions = this->m_modulus;
struct { struct {
ext::TerrainVoxel::uid_t floor = ext::TerrainVoxelFloor().uid(); ext::TerrainVoxel::uid_t floor = ext::TerrainVoxelFloor().uid();
@ -165,18 +180,32 @@ void ext::TerrainGenerator::generate( ext::Region& region ){
this->m_voxels.id.raw.reserve( this->m_size.x * this->m_size.y * this->m_size.z ); this->m_voxels.id.raw.reserve( this->m_size.x * this->m_size.y * this->m_size.z );
this->m_voxels.lighting.raw.reserve( this->m_size.x * this->m_size.y * this->m_size.z ); this->m_voxels.lighting.raw.reserve( this->m_size.x * this->m_size.y * this->m_size.z );
std::size_t i = 0;
ext::Maze& maze = this->m_terrain->getComponent<ext::Maze>();
int LABYRINTH = ext::Maze::FLOOR | ext::Maze::CEIL;
{
int ROW = this->m_location.z + (maze.WIDTH / 2) - 1;
int COL = this->m_location.x + (maze.LENGTH / 2) - 1;
if ( ROW >= 0 && ROW < maze.WIDTH && COL >= 0 && COL < maze.LENGTH )
LABYRINTH = maze( ROW, COL, 0 );
}
std::size_t i = 0;
for ( uint y = 0; y < this->m_size.y; ++y ) { for ( uint y = 0; y < this->m_size.y; ++y ) {
for ( uint z = 0; z < this->m_size.z; ++z ) { for ( uint z = 0; z < this->m_size.z; ++z ) {
for ( uint x = 0; x < this->m_size.x; ++x ) { for ( uint x = 0; x < this->m_size.x; ++x ) {
ext::TerrainVoxel::uid_t voxel = 0; ext::TerrainVoxel::uid_t voxel = 0;
/*
if ( y <= 4 ) voxel = atlas.floor;
*/
double e = raw_noise[x][y][z] / maxValue; double e = raw_noise[x][y][z] / maxValue;
// generate walls if wall exists in maze
if ( LABYRINTH & ext::Maze::EAST ) if ( x == 0 ) voxel = atlas.wall;
if ( LABYRINTH & ext::Maze::WEST ) if ( x == this->m_size.x - 1 ) voxel = atlas.wall;
if ( LABYRINTH & ext::Maze::NORTH ) if ( z == 0 ) voxel = atlas.wall;
if ( LABYRINTH & ext::Maze::SOUTH ) if ( z == this->m_size.z - 1 ) voxel = atlas.wall;
if ( LABYRINTH & ext::Maze::FLOOR ) if ( y == 0 ) voxel = atlas.floor;
if ( LABYRINTH & ext::Maze::CEIL ) if ( y == this->m_size.y - 1 ) voxel = atlas.ceiling;
/*
// if ( (x) % (this->m_size.x / partitions) == 0 ) voxel = atlas.wall; // if ( (x) % (this->m_size.x / partitions) == 0 ) voxel = atlas.wall;
// if ( (z) % (this->m_size.z / partitions) == 0 ) voxel = atlas.wall; // if ( (z) % (this->m_size.z / partitions) == 0 ) voxel = atlas.wall;
if ( (x + 1) % (this->m_size.x / partitions) == 0 ) voxel = atlas.wall; if ( (x + 1) % (this->m_size.x / partitions) == 0 ) voxel = atlas.wall;
@ -195,7 +224,7 @@ void ext::TerrainGenerator::generate( ext::Region& region ){
} else { } else {
// if ( x == half_x && y == 4 && z == half_z ) voxel = atlas.lava; // if ( x == half_x && y == 4 && z == half_z ) voxel = atlas.lava;
} }
*/
auto light = ext::TerrainVoxel::atlas(voxel).light(); auto light = ext::TerrainVoxel::atlas(voxel).light();
if ( light < 0x1111 ) light = 0x1111; if ( light < 0x1111 ) light = 0x1111;
@ -226,7 +255,7 @@ void ext::TerrainGenerator::writeToFile() {
uf::Serializer serializer; uf::Serializer serializer;
std::string base = this->m_terrain ? this->m_terrain->getComponent<uf::Serializer>()["_config"]["hash"].asString() : "UNKNOWN"; std::string base = this->m_terrain ? this->m_terrain->getComponent<uf::Serializer>()["_config"]["hash"].asString() : "UNKNOWN";
std::string filename = "./data/save/regions/" + base + "/" + std::to_string(this->m_location.x) + "." + std::to_string(this->m_location.y) + "." + std::to_string(this->m_location.z) + ".json"; std::string filename = "./data/save/" + base + "/regions/" + std::to_string(this->m_location.x) + "." + std::to_string(this->m_location.y) + "." + std::to_string(this->m_location.z) + ".json";
{ {
// encode as base64, json safe // encode as base64, json safe
serializer["voxels"]["id"]["base64"] = uf::base64::encode( this->m_voxels.id.rle ); serializer["voxels"]["id"]["base64"] = uf::base64::encode( this->m_voxels.id.rle );
@ -347,7 +376,7 @@ ext::TerrainVoxel::light_t ext::TerrainGenerator::getLight( int x, int y, int z
ext::Region* region = terrain.at( location ); ext::Region* region = terrain.at( location );
if ( !region ) { if ( !region ) {
// std::cout << "Out of bounds Region("<< location.x << ", " << location.y << ", " << location.z <<") @ getLight( " << x << ", " << y << ", " << z << " ) " << std::endl; // std::cout << "Out of bounds Region("<< location.x << ", " << location.y << ", " << location.z <<") @ getLight( " << x << ", " << y << ", " << z << " ) " << std::endl;
return 0x0000; return 0xFFFF;
} }
return region->getComponent<ext::TerrainGenerator>().getLight( x, y, z ); return region->getComponent<ext::TerrainGenerator>().getLight( x, y, z );
} }

436
ext/world/terrain/maze.cpp Normal file
View File

@ -0,0 +1,436 @@
#include "Maze.h"
#include <iostream>
#include <vector>
#include <set>
#include <tuple>
#include <map>
#include <random>
#include <time.h>
#include <numeric>
void ext::Maze::initialize(int columns, int rows, int floors, double horizontal_bias, double vertical_bias) {
/* The Maze class contructor
* Input:
* int columns - Set the number of columns in the maze. Correspond to the X axis (length).
* int rows - Set the number of rows in the maze. Correspond to the Y axis (width).
* int floors - Set the number of floors in the maze. Correspond to the Z axis (height).
*
* All three must be larger than 1.
*
* double horizontal_bias - Sets the likelihood of a passage between rooms on the same row.
* double vertical_bias - Sets the likelihood of a passage between rooms in the same column.
*
* Both must be between 0 and 1 exclusive.
* Higher number gives higher likelihood of a passage.
*
* Output:
* Maze object
*/
if (rows < 1 || columns < 1 || floors < 1){
std::cout << "A maze must have dimensions greater than zero.\n";
throw std::invalid_argument("A maze must have dimensions greater than zero.\n");
}
LENGTH = columns;
WIDTH = rows;
HEIGHT = floors;
if (horizontal_bias <= 0 || horizontal_bias >= 1 || vertical_bias <= 0 || vertical_bias >= 1){
std::cout << "Biases must be between 0 and 1 exclusive.\n";
throw std::invalid_argument("Biases must be between 0 and 1 exclusive.\n");
}
EAST_WALL_THRESHOLD = horizontal_bias;
SOUTH_WALL_THRESHOLD = vertical_bias;
//Creating a vector of all rooms.
cells.assign(LENGTH*WIDTH*HEIGHT, -1);
// seed
seed = time(NULL);
// Give each room a different set number (ascending).
// (Which is used during maze generation)
std::iota(std::begin(cells), std::end(cells), 0);
};
int ext::Maze::get(int i, int col, int floor){
// Gets the value stored at row i, column j, level k, in cells;
return cells.at(col + LENGTH*i + LENGTH*WIDTH*floor);
}
void ext::Maze::set(int row, int col, int floor, int val){
// Set the value of cell at (row, col, floor) to val
cells[col + LENGTH*row + LENGTH*WIDTH*floor] = val;
return;
}
void ext::Maze::build(){
/* This function generates a maze.
*
* It uses sets to keep track of areas created by removing walls.
* Initially each room has it's own set, known by it's room value.
* The room sets grows as walls are removed and sets joined.
* To keep track, each room value is mapped to itself, or the room value it has joined.
* The mapping and sets are reset at each floor.
*
* Summary:
* It goes through each cell, removing the walls randomly.
* (First WEST to EAST, then NORTH to SOUTH, then DOWN to UP.
* Just as one write in English, putting each new page on top of the other)
* If a wall is between two rooms in the same set, it is not removed.
*
* Each room value denote which set it belongs to
*
* Each wall removed is stored in as a passage between the two rooms.
* (The rooms position is stored in ext::Maze::passages)
*
* If the current room value is not mapped, then map it to itself.
* Set current room value to it's mapped value.
*
* Add the room to the set given by room value
*
* If a EASTERN wall is removed, then:
* - The set of the connected room is added to the set of this room.
* - The set of the connected room is deleted.
* - Map the connected room value to the current room value.
* - Change the connected room value to the current room value.
* - Add connected room to set.
*
* If a SOUTHERN wall is removed, then:
* - Change the connected room value to the current room value.
* - Add the connected room to set.
*
* After all the rooms of the current floor has been visited:
* - Go through each set, pick a random room, and make a passage up.
* - Clear the sets, and mapping.
*
* On the last floor, each set on each row must have a passage south.
*
* On the last row on the last floor, passages between unconnected sets are removed.
*
* Finally each room value is set according to which walls remain. (Including floor and ceiling)
*/
// The room sets
std::map<std::size_t, std::vector<pos>> room_set;
// The mapping of connected rooms
std::map<int, int> merged_room_sets;
int room_value;
int east_room_value;
int south_room_value;
// To get different mazes each time
srand(seed);
for (int floor = 0; floor < HEIGHT - 1; floor++){ // Go through each floor but the last.
for (int row = 0; row < WIDTH; row++){ // Go through each row
for(int col = 0; col < LENGTH; col++){ // Go through each element in row (Each column)
room_value = get(row, col, floor);
// If this room value is mapped to another, get that value: else map value to itself
if(merged_room_sets.find(room_value) != merged_room_sets.end()){
room_value = merged_room_sets[room_value];
} else {
merged_room_sets[room_value] = room_value;
}
// If not the last cell in row, store eastern room value
if (col<LENGTH-1){
//Is the eastern room value mapped?
east_room_value = (merged_room_sets.find(get(row, col+1, floor))!=merged_room_sets.end()) ?
// Yes: Use mapped value
merged_room_sets[get(row, col+1, floor)] :
// No: Use stored value
get(row, col+1, floor);
}
// If not the last row, store southern room value
if (row < WIDTH-1){
//Is the southern room value mapped?
south_room_value = (merged_room_sets.find(get(row + 1, col, floor))!=merged_room_sets.end()) ?
// Yes: Use mapped value
merged_room_sets[get(row + 1, col, floor)] :
// No: Use stored value
get(row + 1, col, floor);
}
// Add this room to the set of room value
room_set[room_value].push_back(std::make_tuple(row, col, floor));
//If last room in row, skip (don't remove eastern boundary wall)
if(col == LENGTH - 1){}
// If this and eastern room not in same set, maybe remove wall
else if((rand() < EAST_WALL_THRESHOLD * RAND_MAX) && (room_value != east_room_value)){
// EASTERN WALL REMOVED
// Get set of eastern room
std::vector<pos> next_room_position_set = room_set[get(row, col+1, floor)];
// Add set of eastern room to this set.
room_set[room_value].insert(room_set[room_value].end(), next_room_position_set.begin(), next_room_position_set.end() );
// Remove eastern room set
room_set.erase(get(row, col+1, floor));
// Map eastern room value to this room value.
merged_room_sets[get(row,col+1,floor)] = room_value;
// Set eastern room value to this
set(row, col+1, floor, room_value);
// Add the new horizontal passage created.
passages.push_back(std::make_tuple(row, col, floor, row, col+1, floor));
} // Else the eastern wall remain
// Don't remove southern boundary wall.
if(row == WIDTH - 1){}
// If current and southern room is not in same set, then maybe remove wall
else if(rand() < SOUTH_WALL_THRESHOLD * RAND_MAX && room_value != south_room_value){
// Set southern room value to this one
set(row+1, col, floor, room_value);
// Add the newly created vertical passage.
passages.push_back(std::make_tuple(row, col, floor, row+1, col, floor));
} //Else wall down remain
} // All rooms in this row has been visited
} // All rows on this floor has been visited
// Clear room set mapping
merged_room_sets.clear();
// Go through all sets this floor
for(auto entry : room_set)
{
auto group = entry.second;
int x, y, z;
// Picking out a random room in each group
// Room position saved in matrix notation (i, j, k = y, x, z)
std::tie(y, x, z) = group.at(rand() % group.size());
// Only one passage up for each group. To avoid graph cycles
passages.push_back(std::make_tuple(y, x, z, y, x, z+1));
}
// Passages up have been set. Clearing room groups for next floor.
room_set.clear();
}// Finished with all but last floor
int floor = HEIGHT - 1;
std::set<int> can_go_south;
//deal with last floor, but leave the last row
for(int row = 0; row < WIDTH - 1; row++){
for(int col = 0; col<LENGTH; col++){
room_value = get(row, col, floor);
// If this room value is mapped to another, get that value: else map value to itself
if(merged_room_sets.find(room_value) != merged_room_sets.end()){
room_value = merged_room_sets[room_value];
} else {
merged_room_sets[room_value] = room_value;
}
// If not the last cell in row, get eastern room value
if (col<LENGTH-1){
east_room_value = (merged_room_sets.find(get(row, col+1, floor)) != merged_room_sets.end()) ?
merged_room_sets[get(row, col+1, floor)] : get(row, col+1, floor);
}
// Get southern room value
south_room_value = (merged_room_sets.find(get(row + 1, col, floor)) != merged_room_sets.end()) ?
merged_room_sets[get(row + 1, col, floor)] : get(row + 1, col, floor);
// Try and make passage east
if(col == LENGTH -1){}
else if((rand() < EAST_WALL_THRESHOLD * RAND_MAX) && (room_value != east_room_value)){
passages.push_back(std::make_tuple(row, col, floor, row, col+1, floor));
merged_room_sets[east_room_value] = room_value;
set(row, col+1, floor, room_value);
}
// Try and make passage south
if( ( (rand() < SOUTH_WALL_THRESHOLD * RAND_MAX)
|| (can_go_south.find(room_value) == can_go_south.end()) ) // Make sure all sets this row have a passage down
&& (room_value != south_room_value))
{
passages.push_back(std::make_tuple(row, col, floor, row+1, col, floor));
merged_room_sets[south_room_value] = room_value;
set(row+1, col, floor, room_value);
can_go_south.insert(room_value);
}
}
can_go_south.clear();
}
// Go through the last row on the last floor
int row = WIDTH - 1;
for (int col = 0; col < LENGTH - 1; col++)
{
// Get room values
room_value = get(row, col, floor);
if(merged_room_sets.find(room_value) != merged_room_sets.end()){
room_value = merged_room_sets[room_value];
} else {
merged_room_sets[room_value] = room_value;
}
// Get eastern room value
east_room_value = (merged_room_sets.find(get(row, col+1, floor))!=merged_room_sets.end()) ?
merged_room_sets[get(row, col+1, floor)] : get(row, col+1, floor);
// If this and eastern room is in different sets
if(room_value != east_room_value)
{
// Make passage and merge sets
passages.push_back(std::make_tuple(row, col, floor, row, col+1, floor));
merged_room_sets[east_room_value] = room_value;
set(row, col+1, floor, room_value);
}
}
// Calculate the room values based on remaining walls (and floors & ceilings)
ext::Maze::calculate();
};
void ext::Maze::calculate(){
/* This function set each room value according to the remaining walls in that room.
* The walls are represented as bits of a 8-bit int.
* Floor = 0000 0001
* Eastern wall = 0000 0010
* Northern wall = 0000 0100
* Western wall = 0000 1000
* Southern wall = 0001 0000
* Ceiling = 0010 0000
*/
cells.clear();
// 63 = 0011 1111 = all walls, floor, and ceiling
cells.assign(LENGTH*WIDTH*HEIGHT, 63);
int row_from, row_to,
col_from, col_to,
lvl_from, lvl_to;
uint8_t cell_num_to;
uint8_t cell_num_from;
// Go through all passages
for(auto pass : passages){
std::tie(row_from, col_from, lvl_from,
row_to, col_to, lvl_to ) = pass;
cell_num_from = get(row_from, col_from, lvl_from);
cell_num_to = get(row_to, col_to, lvl_to);
// North to South passage
if(row_from != row_to){
set(row_from, col_from, lvl_from, cell_num_from & ~(SOUTH));
set(row_to, col_to, lvl_to, cell_num_to & ~(NORTH));
// West to East passage
} else if (col_from != col_to){
set(row_from, col_from, lvl_from, cell_num_from & ~(EAST));
set(row_to, col_to, lvl_to, cell_num_to & ~(WEST));
// Passage Up
} else if(lvl_from != lvl_to){
set(row_from, col_from, lvl_from, cell_num_from & ~(CEIL));
set(row_to, col_to, lvl_to, cell_num_to & ~(FLOOR));
}
// Else the passage is in several directions and in this case discarded
}
}
void ext::Maze::print(){
/* Print the maze to std::cout
*
* Prints floor in ascending order (top floor last)
* | - represent vertical and horizontal walls respectively
* + is the room corners
* U D B represent stairs up, down, and both, respectively
*
* ext::Maze::passages s used, so remember to run ext::Maze::build first.
*/
// Maze map canvas
std::string map_drawing[2 * WIDTH + 1][HEIGHT];
std::string wall_row = "+";
std::string room_row = "|";
// Make a row of walls and rooms
for (int col = 0; col < LENGTH; col++){
wall_row.append("-+");
room_row.append(" |");
}
// Drawing initial map
for (int floor = 0; floor < HEIGHT; floor++){
map_drawing[2*WIDTH][floor] = wall_row;
for (int row = 0; row < WIDTH; row++){
map_drawing[2*row][floor] = wall_row;
map_drawing[2*row + 1][floor] = room_row;
}
}
// Making passages
for ( auto pass : passages){
int row_from, row_to,
col_from, col_to,
lvl_from, lvl_to;
std::tie(row_from, col_from, lvl_from,
row_to, col_to, lvl_to) = pass;
// North - South passage
if(row_from != row_to){
map_drawing[2 * row_from + 2][lvl_from].replace(2 * col_from + 1, 1, " ");
// West - East passage
} else if (col_from != col_to){
map_drawing[2*row_from + 1][lvl_from].replace(2 * col_from + 2, 1, " ");
// Up - Down passage
} else if (lvl_from != lvl_to){
// If this room have a passage down, you can go up and down from it
if (map_drawing[2 * row_from + 1][lvl_from].at(2 * col_from + 1) == 'D'){
map_drawing[2 * row_from + 1][lvl_from].replace(2 * col_from + 1, 1, "B");
} else {
map_drawing[2 * row_from + 1][lvl_from].replace(2 * col_from + 1, 1, "U");
}
// The passages should come in order, so floor above have no passages up
map_drawing[2 * row_to + 1][lvl_to].replace(2 * col_to + 1, 1, "D");
}
}
// Printing the maze, one row at a time.
for (int floor = 0; floor < HEIGHT; floor++){
for (int row = 0; row < 2*WIDTH+1; row++){
std::cout << map_drawing[row][floor] << std::endl;
}
std::cout << std::endl;
}
}

38
ext/world/terrain/maze.h Normal file
View File

@ -0,0 +1,38 @@
#pragma once
#include<vector>
#include<iostream>
namespace ext {
class Maze {
protected:
double EAST_WALL_THRESHOLD;
double SOUTH_WALL_THRESHOLD;
std::vector< std::tuple<int, int, int, int, int, int> > passages;
typedef std::tuple<int, int, int> pos;
int get(int, int, int);
void set(int, int, int, int);
void calculate();
public:
int LENGTH;
int WIDTH;
int HEIGHT;
size_t seed;
static const uint8_t FLOOR = 1; // 00 00 00 01;
static const uint8_t EAST = 2; // 00 00 00 10;
static const uint8_t NORTH = 4; // 00 00 01 00;
static const uint8_t WEST = 8; // 00 00 10 00;
static const uint8_t SOUTH = 16; // 00 01 00 00;
static const uint8_t CEIL = 32; // 00 10 00 00;
std::vector<int> cells;
int& operator()(int row, int col, int floor){
return cells.at(col + LENGTH*row + LENGTH*WIDTH*floor);
}
void initialize(int, int, int, double, double);
void build();
void print();
};
}

View File

@ -52,28 +52,17 @@ void ext::Terrain::initialize() {
ext::Object::initialize(); ext::Object::initialize();
uf::Serializer& metadata = this->getComponent<uf::Serializer>(); uf::Serializer& metadata = this->getComponent<uf::Serializer>();
std::size_t seed;
if ( metadata["terrain"]["seed"].isUInt64() ) {
seed = metadata["terrain"]["seed"].asUInt64();
} else if ( metadata["terrain"]["seed"].isString() ) {
seed = std::hash<std::string>{}( metadata["terrain"]["seed"].asString() );
}
{ {
std::size_t seed;
if ( metadata["terrain"]["seed"].isUInt64() ) {
seed = metadata["terrain"]["seed"].asUInt64();
} else if ( metadata["terrain"]["seed"].isString() ) {
seed = std::hash<std::string>{}( metadata["terrain"]["seed"].asString() );
}
std::cout << "Seed: " << seed << std::endl; std::cout << "Seed: " << seed << std::endl;
ext::TerrainGenerator::noise.seed( seed ); ext::TerrainGenerator::noise.seed( seed );
} }
/* Test */
/*
{
std::string seed = "170271159441424384 170271159441424384";
std::size_t hash = std::hash<std::string>{}(seed);
uf::PerlinNoise& noise = ext::TerrainGenerator::noise;
noise.seed(hash);
double y = noise.sample(pod::Vector3d{ 0.01, 0.01, 0.01 });
std::cout << seed << ": " << y << std::endl;
}
*/
if ( metadata["terrain"]["raytrace"].asBool() ) { if ( metadata["terrain"]["raytrace"].asBool() ) {
this->addComponent<ext::vulkan::RTGraphic>(); this->addComponent<ext::vulkan::RTGraphic>();
@ -90,11 +79,26 @@ void ext::Terrain::initialize() {
metadata["_config"]["hash"] = uf::string::sha256( input ); metadata["_config"]["hash"] = uf::string::sha256( input );
try { try {
std::string save = "./data/save/regions/" + metadata["_config"]["hash"].asString(); std::string save = "./data/save/" + metadata["_config"]["hash"].asString() + "/";
int status = mkdir(save.c_str()); int status = mkdir(save.c_str());
} catch ( ... ) { } catch ( ... ) {
} }
try {
std::string save = "./data/save/" + metadata["_config"]["hash"].asString() + "/regions/";
int status = mkdir(save.c_str());
} catch ( ... ) {
}
}
// setup maze
{
ext::Maze& maze = this->getComponent<ext::Maze>();
maze.initialize(16, 16, 1, 0.5, 0.5);
maze.seed = seed;
maze.build();
maze.print();
} }
if ( this->hasComponent<ext::vulkan::RTGraphic>() ) { if ( this->hasComponent<ext::vulkan::RTGraphic>() ) {
@ -325,7 +329,7 @@ void ext::Terrain::tick() {
} }
/* Sort by closest to farthest */ { /* Sort by closest to farthest */ {
const ext::World& world = this->getRootParent<ext::World>(); const ext::World& world = this->getRootParent<ext::World>();
const ext::Player& player = world.getController<ext::Player>(); const ext::Object& player = world.getController<ext::Object>();
const pod::Vector3& position = player.getComponent<pod::Transform<>>().position; const pod::Vector3& position = player.getComponent<pod::Transform<>>().position;
std::sort( regions.begin(), regions.end(), [&]( const uf::Entity* l, const uf::Entity* r ){ std::sort( regions.begin(), regions.end(), [&]( const uf::Entity* l, const uf::Entity* r ){
if ( !l ) return false; if ( !r ) return true; if ( !l ) return false; if ( !r ) return true;
@ -359,7 +363,7 @@ void ext::Terrain::tick() {
} }
/* Sort by closest to farthest */ { /* Sort by closest to farthest */ {
const ext::World& world = this->getRootParent<ext::World>(); const ext::World& world = this->getRootParent<ext::World>();
const ext::Player& player = world.getController<ext::Player>(); const ext::Object& player = world.getController<ext::Object>();
const pod::Vector3& position = player.getComponent<pod::Transform<>>().position; const pod::Vector3& position = player.getComponent<pod::Transform<>>().position;
std::sort( regions.begin(), regions.end(), [&]( const uf::Entity* l, const uf::Entity* r ){ std::sort( regions.begin(), regions.end(), [&]( const uf::Entity* l, const uf::Entity* r ){
if ( !l ) return false; if ( !r ) return true; if ( !l ) return false; if ( !r ) return true;
@ -447,7 +451,7 @@ void ext::Terrain::tick() {
pod::Thread& mainThread = uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create( "Main", false, true ); pod::Thread& mainThread = uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create( "Main", false, true );
if ( metadata["terrain"]["state"] == "open" && if ( metadata["terrain"]["state"] == "open" &&
( (generationTimer.running() && generationTimer.elapsed().asDouble() > 3) || !generationTimer.running() ) ( (generationTimer.running() && generationTimer.elapsed().asDouble() > 1) || !generationTimer.running() )
) { metadata["terrain"]["state"] = "resolving:" + metadata["terrain"]["state"].asString(); ) { metadata["terrain"]["state"] = "resolving:" + metadata["terrain"]["state"].asString();
if ( !generationTimer.running() ) generationTimer.start(); if ( !generationTimer.running() ) generationTimer.start();
else generationTimer.reset(); else generationTimer.reset();
@ -489,6 +493,7 @@ void ext::Terrain::tick() {
bool resolved = !metadata["terrain"]["modified"].asBool(); bool resolved = !metadata["terrain"]["modified"].asBool();
if ( !locations.empty() ) { if ( !locations.empty() ) {
std::cout << "GENERATING" << std::endl;
this->generate(); this->generate();
for ( pod::Vector3i& location : locations ) this->degenerate(location); for ( pod::Vector3i& location : locations ) this->degenerate(location);
resolved = false; resolved = false;

View File

@ -8,7 +8,9 @@
#include <uf/utils/math/physics.h> #include <uf/utils/math/physics.h>
#include "../../object/object.h" #include "../../object/object.h"
#include "region.h" #include "region.h"
#include "maze.h"
namespace ext { namespace ext {
class EXT_API Terrain : public ext::Object { class EXT_API Terrain : public ext::Object {

View File

@ -476,7 +476,7 @@ ext::TerrainVoxelWall::TerrainVoxelWall() : ext::TerrainVoxel( 2, true, true, {1
ext::TerrainVoxelCeiling::TerrainVoxelCeiling() : ext::TerrainVoxel( 3, true, true, {2, 1}, 0x0000 ) {} ext::TerrainVoxelCeiling::TerrainVoxelCeiling() : ext::TerrainVoxel( 3, true, true, {2, 1}, 0x0000 ) {}
ext::TerrainVoxelPillar::TerrainVoxelPillar() : ext::TerrainVoxel( 4, true, true, {3, 0}, 0x0000 ) {} ext::TerrainVoxelPillar::TerrainVoxelPillar() : ext::TerrainVoxel( 4, true, true, {3, 0}, 0x0000 ) {}
ext::TerrainVoxelStair::TerrainVoxelStair() : ext::TerrainVoxel( 5, true, true, {2, 0}, 0x0000 ) {} ext::TerrainVoxelStair::TerrainVoxelStair() : ext::TerrainVoxel( 5, true, true, {2, 0}, 0x0000 ) {}
ext::TerrainVoxelLava::TerrainVoxelLava() : ext::TerrainVoxel( 6, true, true, {0, 2}, 0x66FF ) {} ext::TerrainVoxelLava::TerrainVoxelLava() : ext::TerrainVoxel( 6, true, true, {0, 2}, 0xFFFF ) {}
// //
const std::vector<ext::TerrainVoxel>& ext::TerrainVoxel::atlas() { const std::vector<ext::TerrainVoxel>& ext::TerrainVoxel::atlas() {