Clang-format did things

This commit is contained in:
Marc Gilleron 2019-04-24 01:29:47 +01:00
parent 70881ce255
commit 1b9e7257df
18 changed files with 210 additions and 206 deletions

View File

@ -7,18 +7,21 @@
class Rect3i { class Rect3i {
public: public:
Vector3i pos; Vector3i pos;
Vector3i size; Vector3i size;
Rect3i() {} Rect3i() {}
Rect3i(Vector3i p_pos, Vector3i p_size) : pos(p_pos), size(p_size) {} Rect3i(Vector3i p_pos, Vector3i p_size) :
pos(p_pos),
size(p_size) {}
Rect3i(const Rect3i &other) : pos(other.pos), size(other.size) {} Rect3i(const Rect3i &other) :
pos(other.pos),
size(other.size) {}
static inline Rect3i from_center_extents(Vector3i center, Vector3i extents) { static inline Rect3i from_center_extents(Vector3i center, Vector3i extents) {
return Rect3i(center - extents, 2*extents); return Rect3i(center - extents, 2 * extents);
} }
static inline Rect3i get_bounding_box(Rect3i a, Rect3i b) { static inline Rect3i get_bounding_box(Rect3i a, Rect3i b) {
@ -41,12 +44,12 @@ public:
bool inline contains(Vector3i p_pos) const { bool inline contains(Vector3i p_pos) const {
Vector3i end = pos + size; Vector3i end = pos + size;
return p_pos.x >= pos.x return p_pos.x >= pos.x &&
&& p_pos.y >= pos.y p_pos.y >= pos.y &&
&& p_pos.z >= pos.z p_pos.z >= pos.z &&
&& p_pos.x < end.x p_pos.x < end.x &&
&& p_pos.y < end.y p_pos.y < end.y &&
&& p_pos.z < end.z; p_pos.z < end.z;
} }
String to_string() const { String to_string() const {
@ -68,10 +71,9 @@ public:
return false; return false;
return true; return true;
} }
}; };
inline bool operator!=(const Rect3i & a, const Rect3i & b) { inline bool operator!=(const Rect3i &a, const Rect3i &b) {
return a.pos != b.pos || a.size != b.size; return a.pos != b.pos || a.size != b.size;
} }

View File

@ -15,14 +15,20 @@ struct Vector3i {
int coords[3]; int coords[3];
}; };
_FORCE_INLINE_ Vector3i() _FORCE_INLINE_ Vector3i() :
: x(0), y(0), z(0) {} x(0),
y(0),
z(0) {}
_FORCE_INLINE_ Vector3i(int xyz) _FORCE_INLINE_ Vector3i(int xyz) :
: x(xyz), y(xyz), z(xyz) {} x(xyz),
y(xyz),
z(xyz) {}
_FORCE_INLINE_ Vector3i(int px, int py, int pz) _FORCE_INLINE_ Vector3i(int px, int py, int pz) :
: x(px), y(py), z(pz) {} x(px),
y(py),
z(pz) {}
_FORCE_INLINE_ Vector3i(const Vector3i &other) { _FORCE_INLINE_ Vector3i(const Vector3i &other) {
*this = other; *this = other;

View File

@ -4,15 +4,14 @@
#define STRLEN(x) (sizeof(x) / sizeof(x[0])) #define STRLEN(x) (sizeof(x) / sizeof(x[0]))
Voxel::Voxel(): Voxel::Voxel() :
_library(0), _library(0),
_id(-1), _id(-1),
_material_id(0), _material_id(0),
_is_transparent(false), _is_transparent(false),
_color(1.f, 1.f, 1.f), _color(1.f, 1.f, 1.f),
_geometry_type(GEOMETRY_NONE), _geometry_type(GEOMETRY_NONE),
_cube_geometry_padding_y(0) _cube_geometry_padding_y(0) {}
{}
static Cube::Side name_to_side(const String &s) { static Cube::Side name_to_side(const String &s) {
if (s == "left") if (s == "left")
@ -158,7 +157,7 @@ Voxel::GeometryType Voxel::get_geometry_type() const {
} }
void Voxel::set_library(Ref<VoxelLibrary> lib) { void Voxel::set_library(Ref<VoxelLibrary> lib) {
if(lib.is_null()) if (lib.is_null())
_library = 0; _library = 0;
else else
_library = lib->get_instance_id(); _library = lib->get_instance_id();
@ -167,7 +166,7 @@ void Voxel::set_library(Ref<VoxelLibrary> lib) {
} }
VoxelLibrary *Voxel::get_library() const { VoxelLibrary *Voxel::get_library() const {
if(_library == 0) if (_library == 0)
return NULL; return NULL;
Object *v = ObjectDB::get_instance(_library); Object *v = ObjectDB::get_instance(_library);
if (v) if (v)
@ -186,7 +185,7 @@ Ref<Voxel> Voxel::set_cube_geometry(float sy) {
for (unsigned int i = 0; i < 4; ++i) { for (unsigned int i = 0; i < 4; ++i) {
int corner = Cube::g_side_corners[side][i]; int corner = Cube::g_side_corners[side][i];
Vector3 p = Cube::g_corner_position[corner]; Vector3 p = Cube::g_corner_position[corner];
if(p.y > 0.9) if (p.y > 0.9)
p.y = sy; p.y = sy;
w[i] = p; w[i] = p;
} }
@ -213,7 +212,7 @@ void Voxel::set_cube_uv_side(int side, Vector2 tile_pos) {
void Voxel::update_cube_uv_sides() { void Voxel::update_cube_uv_sides() {
VoxelLibrary *library = get_library(); VoxelLibrary *library = get_library();
//ERR_FAIL_COND(library == NULL); //ERR_FAIL_COND(library == NULL);
if(library == NULL) { if (library == NULL) {
// Not an error, the Voxel might have been created before the library, and can't be used without anyways // Not an error, the Voxel might have been created before the library, and can't be used without anyways
print_line("VoxelLibrary not set yet"); print_line("VoxelLibrary not set yet");
return; return;

View File

@ -1,8 +1,8 @@
#ifndef VOXEL_TYPE_H #ifndef VOXEL_TYPE_H
#define VOXEL_TYPE_H #define VOXEL_TYPE_H
#include <core/resource.h>
#include "cube_tables.h" #include "cube_tables.h"
#include <core/resource.h>
class VoxelLibrary; class VoxelLibrary;

View File

@ -15,8 +15,9 @@ VoxelBlock *VoxelBlock::create(Vector3i bpos, Ref<VoxelBuffer> buffer, unsigned
return block; return block;
} }
VoxelBlock::VoxelBlock() VoxelBlock::VoxelBlock() :
: voxels(NULL), _mesh_update_count(0) { voxels(NULL),
_mesh_update_count(0) {
VisualServer &vs = *VisualServer::get_singleton(); VisualServer &vs = *VisualServer::get_singleton();
@ -30,9 +31,9 @@ void VoxelBlock::set_mesh(Ref<Mesh> mesh, Ref<World> world) {
VisualServer &vs = *VisualServer::get_singleton(); VisualServer &vs = *VisualServer::get_singleton();
if(mesh.is_valid()) { if (mesh.is_valid()) {
if(_mesh_instance.is_valid() == false) { if (_mesh_instance.is_valid() == false) {
// Create instance if it doesn't exist // Create instance if it doesn't exist
ERR_FAIL_COND(world.is_null()); ERR_FAIL_COND(world.is_null());
_mesh_instance = vs.instance_create(); _mesh_instance = vs.instance_create();
@ -47,7 +48,7 @@ void VoxelBlock::set_mesh(Ref<Mesh> mesh, Ref<World> world) {
} else { } else {
if(_mesh_instance.is_valid()) { if (_mesh_instance.is_valid()) {
// Delete instance if it exists // Delete instance if it exists
vs.free(_mesh_instance); vs.free(_mesh_instance);
_mesh_instance = RID(); _mesh_instance = RID();
@ -57,30 +58,28 @@ void VoxelBlock::set_mesh(Ref<Mesh> mesh, Ref<World> world) {
_mesh = mesh; _mesh = mesh;
++_mesh_update_count; ++_mesh_update_count;
// if(_mesh_update_count > 1) { // if(_mesh_update_count > 1) {
// print_line(String("Block {0} was updated {1} times").format(varray(pos.to_vec3(), _mesh_update_count))); // print_line(String("Block {0} was updated {1} times").format(varray(pos.to_vec3(), _mesh_update_count)));
// } // }
} }
void VoxelBlock::enter_world(World *world) { void VoxelBlock::enter_world(World *world) {
if(_mesh_instance.is_valid()) { if (_mesh_instance.is_valid()) {
VisualServer &vs = *VisualServer::get_singleton(); VisualServer &vs = *VisualServer::get_singleton();
vs.instance_set_scenario(_mesh_instance, world->get_scenario()); vs.instance_set_scenario(_mesh_instance, world->get_scenario());
} }
} }
void VoxelBlock::exit_world() { void VoxelBlock::exit_world() {
if(_mesh_instance.is_valid()) { if (_mesh_instance.is_valid()) {
VisualServer &vs = *VisualServer::get_singleton(); VisualServer &vs = *VisualServer::get_singleton();
vs.instance_set_scenario(_mesh_instance, RID()); vs.instance_set_scenario(_mesh_instance, RID());
} }
} }
void VoxelBlock::set_visible(bool visible) { void VoxelBlock::set_visible(bool visible) {
if(_mesh_instance.is_valid()) { if (_mesh_instance.is_valid()) {
VisualServer &vs = *VisualServer::get_singleton(); VisualServer &vs = *VisualServer::get_singleton();
vs.instance_set_visible(_mesh_instance, visible); vs.instance_set_visible(_mesh_instance, visible);
} }
} }

View File

@ -3,23 +3,23 @@
static AABB expand_with_vector(AABB box, Vector3 v) { static AABB expand_with_vector(AABB box, Vector3 v) {
if(v.x > 0) { if (v.x > 0) {
box.size.x += v.x; box.size.x += v.x;
} else if(v.x < 0) { } else if (v.x < 0) {
box.position.x += v.x; box.position.x += v.x;
box.size.x -= v.x; box.size.x -= v.x;
} }
if(v.y > 0) { if (v.y > 0) {
box.size.y += v.y; box.size.y += v.y;
} else if(v.y < 0) { } else if (v.y < 0) {
box.position.y += v.y; box.position.y += v.y;
box.size.y -= v.y; box.size.y -= v.y;
} }
if(v.z > 0) { if (v.z > 0) {
box.size.z += v.z; box.size.z += v.z;
} else if(v.z < 0) { } else if (v.z < 0) {
box.position.z += v.z; box.position.z += v.z;
box.size.z -= v.z; box.size.z -= v.z;
} }
@ -34,21 +34,21 @@ static float calculate_i_offset(AABB box, AABB other, float motion, int i, int j
Vector3 other_end = other.position + other.size; Vector3 other_end = other.position + other.size;
Vector3 box_end = box.position + box.size; Vector3 box_end = box.position + box.size;
if(other_end[k] <= box.position[k] || other.position[k] >= box_end[k]) if (other_end[k] <= box.position[k] || other.position[k] >= box_end[k])
return motion; return motion;
if(other_end[j] <= box.position[j] || other.position[j] >= box_end[j]) if (other_end[j] <= box.position[j] || other.position[j] >= box_end[j])
return motion; return motion;
if(motion > 0.0 && other_end[i] <= box.position[i]) { if (motion > 0.0 && other_end[i] <= box.position[i]) {
float off = box.position[i] - other_end[i] - EPSILON; float off = box.position[i] - other_end[i] - EPSILON;
if(off < motion) if (off < motion)
motion = off; motion = off;
} }
if(motion < 0.0 && other.position[i] >= box_end[i]) { if (motion < 0.0 && other.position[i] >= box_end[i]) {
float off = box_end[i] - other.position[i] + EPSILON; float off = box_end[i] - other.position[i] + EPSILON;
if(off > motion) if (off > motion)
motion = off; motion = off;
} }
@ -79,9 +79,9 @@ static Vector3 get_motion(AABB box, Vector3 motion, const Vector<AABB> &other_bo
AABB expanded_box = expand_with_vector(box, motion); AABB expanded_box = expand_with_vector(box, motion);
Vector<AABB> colliding_boxes; Vector<AABB> colliding_boxes;
for(int i = 0; i < other_boxes.size(); ++i) { for (int i = 0; i < other_boxes.size(); ++i) {
AABB other = other_boxes[i]; AABB other = other_boxes[i];
if(expanded_box.intersects(other_boxes[i])) if (expanded_box.intersects(other_boxes[i]))
colliding_boxes.push_back(other); colliding_boxes.push_back(other);
} }
@ -92,15 +92,15 @@ static Vector3 get_motion(AABB box, Vector3 motion, const Vector<AABB> &other_bo
Vector3 new_motion = motion; Vector3 new_motion = motion;
for(int i = 0; i < colliding_boxes.size(); ++i) for (int i = 0; i < colliding_boxes.size(); ++i)
new_motion.y = calculate_i_offset(colliding_boxes[i], box, new_motion.y, 1, 0, 2); new_motion.y = calculate_i_offset(colliding_boxes[i], box, new_motion.y, 1, 0, 2);
box.position.y += new_motion.y; box.position.y += new_motion.y;
for(int i = 0; i < colliding_boxes.size(); ++i) for (int i = 0; i < colliding_boxes.size(); ++i)
new_motion.x = calculate_i_offset(colliding_boxes[i], box, new_motion.x, 0, 1, 2); new_motion.x = calculate_i_offset(colliding_boxes[i], box, new_motion.x, 0, 1, 2);
box.position.x += new_motion.x; box.position.x += new_motion.x;
for(int i = 0; i < colliding_boxes.size(); ++i) for (int i = 0; i < colliding_boxes.size(); ++i)
new_motion.z = calculate_i_offset(colliding_boxes[i], box, new_motion.z, 2, 1, 0); new_motion.z = calculate_i_offset(colliding_boxes[i], box, new_motion.z, 2, 1, 0);
box.position.z += new_motion.z; box.position.z += new_motion.z;
@ -138,8 +138,8 @@ Vector3 VoxelBoxMover::get_motion(Vector3 pos, Vector3 motion, AABB aabb, VoxelT
for (i.x = min_x; i.x < max_x; ++i.x) { for (i.x = min_x; i.x < max_x; ++i.x) {
int voxel_type = voxels.get_voxel(i, 0); int voxel_type = voxels.get_voxel(i, 0);
if(voxel_type != 0) { if (voxel_type != 0) {
AABB voxel_box = AABB(i.to_vec3(), Vector3(1,1,1)); AABB voxel_box = AABB(i.to_vec3(), Vector3(1, 1, 1));
potential_boxes.push_back(voxel_box); potential_boxes.push_back(voxel_box);
} }
} }
@ -161,4 +161,3 @@ void VoxelBoxMover::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_motion", "pos", "motion", "aabb", "terrain"), &VoxelBoxMover::_get_motion_binding); ClassDB::bind_method(D_METHOD("get_motion", "pos", "motion", "aabb", "terrain"), &VoxelBoxMover::_get_motion_binding);
} }

View File

@ -1,7 +1,8 @@
#include "voxel_library.h" #include "voxel_library.h"
VoxelLibrary::VoxelLibrary() : VoxelLibrary::VoxelLibrary() :
Resource(), _atlas_size(1) { Resource(),
_atlas_size(1) {
} }
VoxelLibrary::~VoxelLibrary() { VoxelLibrary::~VoxelLibrary() {
@ -15,8 +16,8 @@ VoxelLibrary::~VoxelLibrary() {
int VoxelLibrary::get_voxel_count() const { int VoxelLibrary::get_voxel_count() const {
int count = 0; int count = 0;
for(int i = 0; i < MAX_VOXEL_TYPES; ++i) { for (int i = 0; i < MAX_VOXEL_TYPES; ++i) {
if(_voxel_types[i].is_valid()) if (_voxel_types[i].is_valid())
++count; ++count;
} }
return count; return count;
@ -33,23 +34,23 @@ void VoxelLibrary::load_default() {
bool VoxelLibrary::_set(const StringName &p_name, const Variant &p_value) { bool VoxelLibrary::_set(const StringName &p_name, const Variant &p_value) {
// if(p_name == "voxels/max") { // if(p_name == "voxels/max") {
// int v = p_value; // int v = p_value;
// _max_count = CLAMP(v, 0, MAX_VOXEL_TYPES); // _max_count = CLAMP(v, 0, MAX_VOXEL_TYPES);
// for(int i = _max_count; i < MAX_VOXEL_TYPES; ++i) { // for(int i = _max_count; i < MAX_VOXEL_TYPES; ++i) {
// _voxel_types[i] = Ref<Voxel>(); // _voxel_types[i] = Ref<Voxel>();
// return true; // return true;
// } // }
// } else // } else
if (p_name.operator String().begins_with("voxels/")) { if (p_name.operator String().begins_with("voxels/")) {
int idx = p_name.operator String().get_slicec('/', 1).to_int(); int idx = p_name.operator String().get_slicec('/', 1).to_int();
if (idx >= 0 && idx < MAX_VOXEL_TYPES) { if (idx >= 0 && idx < MAX_VOXEL_TYPES) {
Ref<Voxel> voxel = p_value; Ref<Voxel> voxel = p_value;
_voxel_types[idx] = voxel; _voxel_types[idx] = voxel;
if(voxel.is_valid()) { if (voxel.is_valid()) {
voxel->set_library(Ref<VoxelLibrary>(this)); voxel->set_library(Ref<VoxelLibrary>(this));
voxel->set_id(idx); voxel->set_id(idx);
} }
@ -64,12 +65,12 @@ bool VoxelLibrary::_set(const StringName &p_name, const Variant &p_value) {
bool VoxelLibrary::_get(const StringName &p_name, Variant &r_ret) const { bool VoxelLibrary::_get(const StringName &p_name, Variant &r_ret) const {
// if(p_name == "voxels/max") { // if(p_name == "voxels/max") {
// r_ret = _max_count; // r_ret = _max_count;
// return true; // return true;
// } else // } else
if (p_name.operator String().begins_with("voxels/")) { if (p_name.operator String().begins_with("voxels/")) {
int idx = p_name.operator String().get_slicec('/', 1).to_int(); int idx = p_name.operator String().get_slicec('/', 1).to_int();
@ -87,10 +88,9 @@ void VoxelLibrary::_get_property_list(List<PropertyInfo> *p_list) const {
//p_list->push_back(PropertyInfo(Variant::INT, "voxels/max")); //p_list->push_back(PropertyInfo(Variant::INT, "voxels/max"));
//for(int i = 0; i < _max_count; ++i) { //for(int i = 0; i < _max_count; ++i) {
for(int i = 0; i < MAX_VOXEL_TYPES; ++i) { for (int i = 0; i < MAX_VOXEL_TYPES; ++i) {
p_list->push_back(PropertyInfo(Variant::OBJECT, "voxels/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "Voxel")); p_list->push_back(PropertyInfo(Variant::OBJECT, "voxels/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "Voxel"));
} }
} }
void VoxelLibrary::set_atlas_size(int s) { void VoxelLibrary::set_atlas_size(int s) {
@ -123,5 +123,3 @@ void VoxelLibrary::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "atlas_size"), "set_atlas_size", "get_atlas_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "atlas_size"), "set_atlas_size", "get_atlas_size");
} }

View File

@ -1,12 +1,11 @@
#include "voxel_map.h" #include "voxel_map.h"
#include "voxel_block.h"
#include "cube_tables.h" #include "cube_tables.h"
#include "voxel_block.h"
#include "core/os/os.h" #include "core/os/os.h"
VoxelMap::VoxelMap() :
VoxelMap::VoxelMap() _last_accessed_block(NULL) {
: _last_accessed_block(NULL) {
// TODO Make it configurable in editor (with all necessary notifications and updatings!) // TODO Make it configurable in editor (with all necessary notifications and updatings!)
set_block_size_pow2(4); set_block_size_pow2(4);

View File

@ -1,6 +1,6 @@
#include <core/os/os.h>
#include "voxel_mesh_updater.h" #include "voxel_mesh_updater.h"
#include "utility.h" #include "utility.h"
#include <core/os/os.h>
VoxelMeshUpdater::VoxelMeshUpdater(Ref<VoxelLibrary> library, MeshingParams params) { VoxelMeshUpdater::VoxelMeshUpdater(Ref<VoxelLibrary> library, MeshingParams params) {
@ -43,7 +43,7 @@ void VoxelMeshUpdater::push(const Input &input) {
{ {
MutexLock lock(_input_mutex); MutexLock lock(_input_mutex);
for(int i = 0; i < input.blocks.size(); ++i) { for (int i = 0; i < input.blocks.size(); ++i) {
Vector3i pos = input.blocks[i].position; Vector3i pos = input.blocks[i].position;
@ -64,7 +64,7 @@ void VoxelMeshUpdater::push(const Input &input) {
int *index = _block_indexes.getptr(pos); int *index = _block_indexes.getptr(pos);
if(index) { if (index) {
// The block is already in the update queue, replace it // The block is already in the update queue, replace it
++replaced_blocks; ++replaced_blocks;
_shared_input.blocks.write[*index] = input.blocks[i]; _shared_input.blocks.write[*index] = input.blocks[i];
@ -77,7 +77,7 @@ void VoxelMeshUpdater::push(const Input &input) {
} }
} }
if(_shared_input.priority_position != input.priority_position || input.blocks.size() > 0) { if (_shared_input.priority_position != input.priority_position || input.blocks.size() > 0) {
_needs_sort = true; _needs_sort = true;
} }
@ -85,7 +85,7 @@ void VoxelMeshUpdater::push(const Input &input) {
should_run = !_shared_input.is_empty(); should_run = !_shared_input.is_empty();
} }
if(replaced_blocks > 0) if (replaced_blocks > 0)
print_line(String("VoxelMeshUpdater: {0} blocks already in queue were replaced").format(varray(replaced_blocks))); print_line(String("VoxelMeshUpdater: {0} blocks already in queue were replaced").format(varray(replaced_blocks)));
if (should_run) { if (should_run) {
@ -103,7 +103,7 @@ void VoxelMeshUpdater::pop(Output &output) {
} }
void VoxelMeshUpdater::_thread_func(void *p_self) { void VoxelMeshUpdater::_thread_func(void *p_self) {
VoxelMeshUpdater *self = reinterpret_cast<VoxelMeshUpdater*>(p_self); VoxelMeshUpdater *self = reinterpret_cast<VoxelMeshUpdater *>(p_self);
self->thread_func(); self->thread_func();
} }
@ -143,9 +143,9 @@ void VoxelMeshUpdater::thread_func() {
stats.min_time = time_taken; stats.min_time = time_taken;
stats.max_time = time_taken; stats.max_time = time_taken;
} else { } else {
if(time_taken < stats.min_time) if (time_taken < stats.min_time)
stats.min_time = time_taken; stats.min_time = time_taken;
if(time_taken > stats.max_time) if (time_taken > stats.max_time)
stats.max_time = time_taken; stats.max_time = time_taken;
} }
@ -224,10 +224,10 @@ void VoxelMeshUpdater::thread_sync(int queue_index, Stats stats) {
_needs_sort = false; _needs_sort = false;
} }
if(!_output.blocks.empty()) { if (!_output.blocks.empty()) {
// print_line(String("VoxelMeshUpdater: posting {0} blocks, {1} remaining ; cost [{2}..{3}] usec") // print_line(String("VoxelMeshUpdater: posting {0} blocks, {1} remaining ; cost [{2}..{3}] usec")
// .format(varray(_output.blocks.size(), _input.blocks.size(), stats.min_time, stats.max_time))); // .format(varray(_output.blocks.size(), _input.blocks.size(), stats.min_time, stats.max_time)));
// Post output // Post output
MutexLock lock(_output_mutex); MutexLock lock(_output_mutex);
@ -244,4 +244,3 @@ void VoxelMeshUpdater::thread_sync(int queue_index, Stats stats) {
sorter.sort(_input.blocks.ptrw(), _input.blocks.size()); sorter.sort(_input.blocks.ptrw(), _input.blocks.size());
} }
} }

View File

@ -1,13 +1,13 @@
#ifndef VOXEL_MESH_UPDATER_H #ifndef VOXEL_MESH_UPDATER_H
#define VOXEL_MESH_UPDATER_H #define VOXEL_MESH_UPDATER_H
#include <core/vector.h>
#include <core/os/semaphore.h> #include <core/os/semaphore.h>
#include <core/os/thread.h> #include <core/os/thread.h>
#include <core/vector.h>
#include "transvoxel/voxel_mesher_transvoxel.h"
#include "voxel_buffer.h" #include "voxel_buffer.h"
#include "voxel_mesher.h" #include "voxel_mesher.h"
#include "transvoxel/voxel_mesher_transvoxel.h"
class VoxelMeshUpdater { class VoxelMeshUpdater {
public: public:
@ -37,7 +37,11 @@ public:
uint64_t max_time; uint64_t max_time;
uint32_t remaining_blocks; uint32_t remaining_blocks;
Stats() : first(true), min_time(0), max_time(0), remaining_blocks(0) {} Stats() :
first(true),
min_time(0),
max_time(0),
remaining_blocks(0) {}
}; };
struct Output { struct Output {
@ -49,8 +53,9 @@ public:
bool baked_ao; bool baked_ao;
float baked_ao_darkness; float baked_ao_darkness;
MeshingParams(): baked_ao(true), baked_ao_darkness(0.75) MeshingParams() :
{ } baked_ao(true),
baked_ao_darkness(0.75) {}
}; };
VoxelMeshUpdater(Ref<VoxelLibrary> library, MeshingParams params); VoxelMeshUpdater(Ref<VoxelLibrary> library, MeshingParams params);

View File

@ -1,7 +1,7 @@
#include "voxel_mesher.h" #include "voxel_mesher.h"
#include "voxel_library.h"
#include "cube_tables.h" #include "cube_tables.h"
#include "utility.h" #include "utility.h"
#include "voxel_library.h"
#include <core/os/os.h> #include <core/os/os.h>
template <typename T> template <typename T>
@ -11,10 +11,9 @@ void raw_copy_to(PoolVector<T> &to, const Vector<T> &from) {
memcpy(w.ptr(), from.ptr(), from.size() * sizeof(T)); memcpy(w.ptr(), from.ptr(), from.size() * sizeof(T));
} }
VoxelMesher::VoxelMesher() :
VoxelMesher::VoxelMesher() _baked_occlusion_darkness(0.8),
: _baked_occlusion_darkness(0.8), _bake_occlusion(true) {}
_bake_occlusion(true) {}
void VoxelMesher::set_library(Ref<VoxelLibrary> library) { void VoxelMesher::set_library(Ref<VoxelLibrary> library) {
_library = library; _library = library;
@ -58,17 +57,17 @@ Ref<ArrayMesh> VoxelMesher::build_mesh(Ref<VoxelBuffer> buffer_ref, unsigned int
VoxelBuffer &buffer = **buffer_ref; VoxelBuffer &buffer = **buffer_ref;
Array surfaces = build(buffer, channel, Vector3i(), buffer.get_size()); Array surfaces = build(buffer, channel, Vector3i(), buffer.get_size());
if(mesh.is_null()) if (mesh.is_null())
mesh.instance(); mesh.instance();
int surface = mesh->get_surface_count(); int surface = mesh->get_surface_count();
for(int i = 0; i < surfaces.size(); ++i) { for (int i = 0; i < surfaces.size(); ++i) {
Array arrays = surfaces[i]; Array arrays = surfaces[i];
mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arrays); mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arrays);
Ref<Material> material = materials[i]; Ref<Material> material = materials[i];
if(material.is_valid()) { if (material.is_valid()) {
mesh->surface_set_material(surface, material); mesh->surface_set_material(surface, material);
} }
} }
@ -132,7 +131,6 @@ Array VoxelMesher::build(const VoxelBuffer &buffer, unsigned int channel, Vector
// \ / // \ /
CRASH_COND(type_buffer == NULL); CRASH_COND(type_buffer == NULL);
//CRASH_COND(memarr_len(type_buffer) != buffer.get_volume() * sizeof(uint8_t)); //CRASH_COND(memarr_len(type_buffer) != buffer.get_volume() * sizeof(uint8_t));
// Build lookup tables so to speed up voxel access. // Build lookup tables so to speed up voxel access.
@ -308,7 +306,7 @@ Array VoxelMesher::build(const VoxelBuffer &buffer, unsigned int channel, Vector
int i = arrays.indices.size(); int i = arrays.indices.size();
arrays.indices.resize(arrays.indices.size() + index_count); arrays.indices.resize(arrays.indices.size() + index_count);
int *w = arrays.indices.ptrw(); int *w = arrays.indices.ptrw();
for(unsigned int j = 0; j < index_count; ++j) { for (unsigned int j = 0; j < index_count; ++j) {
w[i++] = index_offset + ri[j]; w[i++] = index_offset + ri[j];
} }
} }
@ -337,16 +335,16 @@ Array VoxelMesher::build(const VoxelBuffer &buffer, unsigned int channel, Vector
arrays.positions.push_back(rv[i] + pos); arrays.positions.push_back(rv[i] + pos);
} }
if(_bake_occlusion) { if (_bake_occlusion) {
// TODO handle ambient occlusion on inner parts // TODO handle ambient occlusion on inner parts
arrays.colors.push_back(Color(1,1,1)); arrays.colors.push_back(Color(1, 1, 1));
} }
const PoolVector<int> &indices = voxel.get_model_indices(); const PoolVector<int> &indices = voxel.get_model_indices();
PoolVector<int>::Read ri = indices.read(); PoolVector<int>::Read ri = indices.read();
unsigned int index_count = indices.size(); unsigned int index_count = indices.size();
for(unsigned int i = 0; i < index_count; ++i) { for (unsigned int i = 0; i < index_count; ++i) {
arrays.indices.push_back(index_offset + ri[i]); arrays.indices.push_back(index_offset + ri[i]);
} }
@ -362,8 +360,8 @@ Array VoxelMesher::build(const VoxelBuffer &buffer, unsigned int channel, Vector
// Commit mesh // Commit mesh
// print_line(String("Made mesh v: ") + String::num(_arrays[0].positions.size()) // print_line(String("Made mesh v: ") + String::num(_arrays[0].positions.size())
// + String(", i: ") + String::num(_arrays[0].indices.size())); // + String(", i: ") + String::num(_arrays[0].indices.size()));
Array surfaces; Array surfaces;

View File

@ -1,8 +1,8 @@
#ifndef VOXEL_PROVIDER_H #ifndef VOXEL_PROVIDER_H
#define VOXEL_PROVIDER_H #define VOXEL_PROVIDER_H
#include <core/resource.h>
#include "voxel_buffer.h" #include "voxel_buffer.h"
#include <core/resource.h>
class VoxelProvider : public Resource { class VoxelProvider : public Resource {
GDCLASS(VoxelProvider, Resource) GDCLASS(VoxelProvider, Resource)

View File

@ -4,6 +4,7 @@
#include "voxel_provider.h" #include "voxel_provider.h"
#include <core/image.h> #include <core/image.h>
// TODO Rename VoxelProviderHeightmap
// Provides infinite tiling heightmap based on an image // Provides infinite tiling heightmap based on an image
class VoxelProviderImage : public VoxelProvider { class VoxelProviderImage : public VoxelProvider {
GDCLASS(VoxelProviderImage, VoxelProvider) GDCLASS(VoxelProviderImage, VoxelProvider)

View File

@ -75,11 +75,11 @@ void VoxelProviderTest::generate_block_waves(VoxelBuffer &out_buffer, Vector3i o
//out_buffer.fill(0, 1); // TRANSVOXEL TEST //out_buffer.fill(0, 1); // TRANSVOXEL TEST
if(origin.y + size.y < Math::floor(_pattern_offset.y - 1.5*amplitude)) { if (origin.y + size.y < Math::floor(_pattern_offset.y - 1.5 * amplitude)) {
// Everything is ground // Everything is ground
out_buffer.fill(_voxel_type); out_buffer.fill(_voxel_type);
} else if(origin.y > Math::ceil(_pattern_offset.y + 1.5*amplitude)) { } else if (origin.y > Math::ceil(_pattern_offset.y + 1.5 * amplitude)) {
// Everything is air // Everything is air
return; return;
@ -126,5 +126,3 @@ void VoxelProviderTest::_bind_methods() {
BIND_ENUM_CONSTANT(MODE_FLAT); BIND_ENUM_CONSTANT(MODE_FLAT);
BIND_ENUM_CONSTANT(MODE_WAVES); BIND_ENUM_CONSTANT(MODE_WAVES);
} }

View File

@ -1,11 +1,10 @@
#include "core/os/os.h"
#include "core/os/thread.h"
#include "core/os/semaphore.h"
#include "voxel_provider_thread.h" #include "voxel_provider_thread.h"
#include "voxel_provider.h" #include "core/os/os.h"
#include "voxel_map.h" #include "core/os/semaphore.h"
#include "core/os/thread.h"
#include "utility.h" #include "utility.h"
#include "voxel_map.h"
#include "voxel_provider.h"
VoxelProviderThread::VoxelProviderThread(Ref<VoxelProvider> provider, int block_size_pow2) { VoxelProviderThread::VoxelProviderThread(Ref<VoxelProvider> provider, int block_size_pow2) {
@ -50,7 +49,7 @@ void VoxelProviderThread::push(const InputData &input) {
} }
// Notify the thread it should run // Notify the thread it should run
if(should_run) { if (should_run) {
_semaphore->post(); _semaphore->post();
} }
} }
@ -65,13 +64,13 @@ void VoxelProviderThread::pop(OutputData &out_data) {
} }
void VoxelProviderThread::_thread_func(void *p_self) { void VoxelProviderThread::_thread_func(void *p_self) {
VoxelProviderThread *self = reinterpret_cast<VoxelProviderThread*>(p_self); VoxelProviderThread *self = reinterpret_cast<VoxelProviderThread *>(p_self);
self->thread_func(); self->thread_func();
} }
void VoxelProviderThread::thread_func() { void VoxelProviderThread::thread_func() {
while(!_thread_exit) { while (!_thread_exit) {
uint32_t sync_interval = 100.0; // milliseconds uint32_t sync_interval = 100.0; // milliseconds
uint32_t sync_time = OS::get_singleton()->get_ticks_msec() + sync_interval; uint32_t sync_time = OS::get_singleton()->get_ticks_msec() + sync_interval;
@ -81,18 +80,18 @@ void VoxelProviderThread::thread_func() {
thread_sync(emerge_index, stats); thread_sync(emerge_index, stats);
while(!_input.is_empty() && !_thread_exit) { while (!_input.is_empty() && !_thread_exit) {
//print_line(String("Thread runs: {0}").format(varray(_input.blocks_to_emerge.size()))); //print_line(String("Thread runs: {0}").format(varray(_input.blocks_to_emerge.size())));
// TODO Block saving // TODO Block saving
_input.blocks_to_immerge.clear(); _input.blocks_to_immerge.clear();
if(!_input.blocks_to_emerge.empty()) { if (!_input.blocks_to_emerge.empty()) {
Vector3i block_pos = _input.blocks_to_emerge[emerge_index]; Vector3i block_pos = _input.blocks_to_emerge[emerge_index];
++emerge_index; ++emerge_index;
if(emerge_index >= _input.blocks_to_emerge.size()) { if (emerge_index >= _input.blocks_to_emerge.size()) {
_input.blocks_to_emerge.clear(); _input.blocks_to_emerge.clear();
} }
@ -107,14 +106,14 @@ void VoxelProviderThread::thread_func() {
uint64_t time_taken = OS::get_singleton()->get_ticks_usec() - time_before; uint64_t time_taken = OS::get_singleton()->get_ticks_usec() - time_before;
// Do some stats // Do some stats
if(stats.first) { if (stats.first) {
stats.first = false; stats.first = false;
stats.min_time = time_taken; stats.min_time = time_taken;
stats.max_time = time_taken; stats.max_time = time_taken;
} else { } else {
if(time_taken < stats.min_time) if (time_taken < stats.min_time)
stats.min_time = time_taken; stats.min_time = time_taken;
if(time_taken > stats.max_time) if (time_taken > stats.max_time)
stats.max_time = time_taken; stats.max_time = time_taken;
} }
@ -135,7 +134,7 @@ void VoxelProviderThread::thread_func() {
} }
} }
if(_thread_exit) if (_thread_exit)
break; break;
// Wait for future wake-up // Wait for future wake-up
@ -183,8 +182,8 @@ void VoxelProviderThread::thread_sync(int emerge_index, Stats stats) {
stats.remaining_blocks = _input.blocks_to_emerge.size(); stats.remaining_blocks = _input.blocks_to_emerge.size();
// print_line(String("VoxelProviderThread: posting {0} blocks, {1} remaining ; cost [{2}..{3}] usec") // print_line(String("VoxelProviderThread: posting {0} blocks, {1} remaining ; cost [{2}..{3}] usec")
// .format(varray(_output.size(), _input.blocks_to_emerge.size(), stats.min_time, stats.max_time))); // .format(varray(_output.size(), _input.blocks_to_emerge.size(), stats.min_time, stats.max_time)));
{ {
// Post output // Post output
@ -202,5 +201,3 @@ void VoxelProviderThread::thread_sync(int emerge_index, Stats stats) {
sorter.sort(_input.blocks_to_emerge.ptrw(), _input.blocks_to_emerge.size()); sorter.sort(_input.blocks_to_emerge.ptrw(), _input.blocks_to_emerge.size());
} }
} }

View File

@ -37,7 +37,11 @@ public:
uint64_t max_time; uint64_t max_time;
int remaining_blocks; int remaining_blocks;
Stats() : first(true), min_time(0), max_time(0), remaining_blocks(0) {} Stats() :
first(true),
min_time(0),
max_time(0),
remaining_blocks(0) {}
}; };
struct OutputData { struct OutputData {

View File

@ -1,18 +1,18 @@
#include "voxel_terrain.h" #include "voxel_terrain.h"
#include "voxel_map.h" #include "utility.h"
#include "voxel_block.h" #include "voxel_block.h"
#include "voxel_map.h"
#include "voxel_provider_test.h"
#include "voxel_provider_thread.h" #include "voxel_provider_thread.h"
#include "voxel_raycast.h" #include "voxel_raycast.h"
#include "voxel_provider_test.h"
#include "utility.h"
#include <core/engine.h>
#include <core/os/os.h> #include <core/os/os.h>
#include <scene/3d/mesh_instance.h> #include <scene/3d/mesh_instance.h>
#include <core/engine.h>
VoxelTerrain::VoxelTerrain() :
VoxelTerrain::VoxelTerrain() Spatial(),
: Spatial(), _generate_collisions(true) { _generate_collisions(true) {
_map = Ref<VoxelMap>(memnew(VoxelMap)); _map = Ref<VoxelMap>(memnew(VoxelMap));
@ -28,10 +28,10 @@ VoxelTerrain::VoxelTerrain()
VoxelTerrain::~VoxelTerrain() { VoxelTerrain::~VoxelTerrain() {
print_line("Destroying VoxelTerrain"); print_line("Destroying VoxelTerrain");
if(_provider_thread) { if (_provider_thread) {
memdelete(_provider_thread); memdelete(_provider_thread);
} }
if(_block_updater) { if (_block_updater) {
memdelete(_block_updater); memdelete(_block_updater);
} }
} }
@ -70,18 +70,18 @@ void VoxelTerrain::_get_property_list(List<PropertyInfo> *p_list) const {
} }
void VoxelTerrain::set_provider(Ref<VoxelProvider> provider) { void VoxelTerrain::set_provider(Ref<VoxelProvider> provider) {
if(provider != _provider) { if (provider != _provider) {
if(_provider_thread) { if (_provider_thread) {
memdelete(_provider_thread); memdelete(_provider_thread);
_provider_thread = NULL; _provider_thread = NULL;
} }
_provider = provider; _provider = provider;
_provider_thread = memnew(VoxelProviderThread(_provider, _map->get_block_size_pow2())); _provider_thread = memnew(VoxelProviderThread(_provider, _map->get_block_size_pow2()));
// Ref<VoxelProviderTest> test; // Ref<VoxelProviderTest> test;
// test.instance(); // test.instance();
// _provider_thread = memnew(VoxelProviderThread(test, _map->get_block_size_pow2())); // _provider_thread = memnew(VoxelProviderThread(test, _map->get_block_size_pow2()));
// The whole map might change, so make all area dirty // The whole map might change, so make all area dirty
// TODO Actually, we should regenerate the whole map, not just update all its blocks // TODO Actually, we should regenerate the whole map, not just update all its blocks
@ -108,7 +108,7 @@ void VoxelTerrain::set_voxel_library(Ref<VoxelLibrary> library) {
#endif #endif
_library = library; _library = library;
if(_block_updater) { if (_block_updater) {
memdelete(_block_updater); memdelete(_block_updater);
_block_updater = NULL; _block_updater = NULL;
} }
@ -134,7 +134,7 @@ int VoxelTerrain::get_view_distance() const {
void VoxelTerrain::set_view_distance(int distance_in_voxels) { void VoxelTerrain::set_view_distance(int distance_in_voxels) {
ERR_FAIL_COND(distance_in_voxels < 0) ERR_FAIL_COND(distance_in_voxels < 0)
int d = distance_in_voxels / _map->get_block_size(); int d = distance_in_voxels / _map->get_block_size();
if(d != _view_distance_blocks) { if (d != _view_distance_blocks) {
print_line(String("View distance changed from ") + String::num(_view_distance_blocks) + String(" blocks to ") + String::num(d)); print_line(String("View distance changed from ") + String::num(_view_distance_blocks) + String(" blocks to ") + String::num(d));
_view_distance_blocks = d; _view_distance_blocks = d;
// Blocks too far away will be removed in _process, same for blocks to load // Blocks too far away will be removed in _process, same for blocks to load
@ -174,10 +174,10 @@ void VoxelTerrain::make_block_dirty(Vector3i bpos) {
VoxelTerrain::BlockDirtyState *state = _dirty_blocks.getptr(bpos); VoxelTerrain::BlockDirtyState *state = _dirty_blocks.getptr(bpos);
if(state == NULL) { if (state == NULL) {
// The block is not dirty, so it will either be loaded or updated // The block is not dirty, so it will either be loaded or updated
if(_map->has_block(bpos)) { if (_map->has_block(bpos)) {
_blocks_pending_update.push_back(bpos); _blocks_pending_update.push_back(bpos);
_dirty_blocks[bpos] = BLOCK_UPDATE_NOT_SENT; _dirty_blocks[bpos] = BLOCK_UPDATE_NOT_SENT;
@ -187,7 +187,7 @@ void VoxelTerrain::make_block_dirty(Vector3i bpos) {
_dirty_blocks[bpos] = BLOCK_LOAD; _dirty_blocks[bpos] = BLOCK_LOAD;
} }
} else if(*state == BLOCK_UPDATE_SENT) { } else if (*state == BLOCK_UPDATE_SENT) {
// The updater is already processing the block, // The updater is already processing the block,
// but the block was modified again so we schedule another update // but the block was modified again so we schedule another update
*state = BLOCK_UPDATE_NOT_SENT; *state = BLOCK_UPDATE_NOT_SENT;
@ -265,8 +265,8 @@ void VoxelTerrain::make_all_view_dirty_deferred() {
// always use an up-to-date view distance, which is not necessarily loaded yet on initialization. // always use an up-to-date view distance, which is not necessarily loaded yet on initialization.
_last_view_distance_blocks = 0; _last_view_distance_blocks = 0;
// Vector3i radius(_view_distance_blocks, _view_distance_blocks, _view_distance_blocks); // Vector3i radius(_view_distance_blocks, _view_distance_blocks, _view_distance_blocks);
// make_blocks_dirty(-radius, 2*radius); // make_blocks_dirty(-radius, 2*radius);
} }
inline int get_border_index(int x, int max) { inline int get_border_index(int x, int max) {
@ -285,7 +285,7 @@ void VoxelTerrain::make_voxel_dirty(Vector3i pos) {
Vector3i rpos = _map->to_local(pos); Vector3i rpos = _map->to_local(pos);
// TODO Thread-safe way of getting this parameter // TODO Thread-safe way of getting this parameter
bool check_corners = true;//_mesher->get_occlusion_enabled(); bool check_corners = true; //_mesher->get_occlusion_enabled();
const int max = _map->get_block_size() - 1; const int max = _map->get_block_size() - 1;
@ -389,7 +389,7 @@ void VoxelTerrain::make_area_dirty(Rect3i box) {
Vector3i max_pos = box.pos + box.size - Vector3(1, 1, 1); Vector3i max_pos = box.pos + box.size - Vector3(1, 1, 1);
// TODO Thread-safe way of getting this parameter // TODO Thread-safe way of getting this parameter
bool check_corners = true;//_mesher->get_occlusion_enabled(); bool check_corners = true; //_mesher->get_occlusion_enabled();
if (check_corners) { if (check_corners) {
min_pos -= Vector3i(1, 1, 1); min_pos -= Vector3i(1, 1, 1);
@ -431,7 +431,8 @@ void VoxelTerrain::make_area_dirty(Rect3i box) {
struct EnterWorldAction { struct EnterWorldAction {
World *world; World *world;
EnterWorldAction(World *w) : world(w) {} EnterWorldAction(World *w) :
world(w) {}
void operator()(VoxelBlock *block) { void operator()(VoxelBlock *block) {
block->enter_world(world); block->enter_world(world);
} }
@ -445,7 +446,8 @@ struct ExitWorldAction {
struct SetVisibilityAction { struct SetVisibilityAction {
bool visible; bool visible;
SetVisibilityAction(bool v) : visible(v) {} SetVisibilityAction(bool v) :
visible(v) {}
void operator()(VoxelBlock *block) { void operator()(VoxelBlock *block) {
block->set_visible(visible); block->set_visible(visible);
} }
@ -482,7 +484,7 @@ void VoxelTerrain::_notification(int p_what) {
_map->for_all_blocks(SetVisibilityAction(is_visible())); _map->for_all_blocks(SetVisibilityAction(is_visible()));
break; break;
// TODO Listen for transform changes // TODO Listen for transform changes
default: default:
break; break;
@ -490,9 +492,9 @@ void VoxelTerrain::_notification(int p_what) {
} }
void VoxelTerrain::remove_positions_outside_box(Vector<Vector3i> &positions, Rect3i box, HashMap<Vector3i, VoxelTerrain::BlockDirtyState, Vector3iHasher> &state_map) { void VoxelTerrain::remove_positions_outside_box(Vector<Vector3i> &positions, Rect3i box, HashMap<Vector3i, VoxelTerrain::BlockDirtyState, Vector3iHasher> &state_map) {
for(int i = 0; i < positions.size(); ++i) { for (int i = 0; i < positions.size(); ++i) {
const Vector3i bpos = positions[i]; const Vector3i bpos = positions[i];
if(!box.contains(bpos)) { if (!box.contains(bpos)) {
int last = positions.size() - 1; int last = positions.size() - 1;
positions.write[i] = positions[last]; positions.write[i] = positions[last];
positions.resize(last); positions.resize(last);
@ -525,7 +527,7 @@ void VoxelTerrain::_process() {
// Get viewer location // Get viewer location
// TODO Transform to local (Spatial Transform) // TODO Transform to local (Spatial Transform)
Vector3i viewer_block_pos; Vector3i viewer_block_pos;
if(engine.is_editor_hint()) { if (engine.is_editor_hint()) {
// TODO Use editor's camera here // TODO Use editor's camera here
viewer_block_pos = Vector3i(); viewer_block_pos = Vector3i();
} else { } else {
@ -542,7 +544,7 @@ void VoxelTerrain::_process() {
Rect3i new_box = Rect3i::from_center_extents(viewer_block_pos, Vector3i(_view_distance_blocks)); Rect3i new_box = Rect3i::from_center_extents(viewer_block_pos, Vector3i(_view_distance_blocks));
Rect3i prev_box = Rect3i::from_center_extents(_last_viewer_block_pos, Vector3i(_last_view_distance_blocks)); Rect3i prev_box = Rect3i::from_center_extents(_last_viewer_block_pos, Vector3i(_last_view_distance_blocks));
if(prev_box != new_box) { if (prev_box != new_box) {
//print_line(String("Loaded area changed: from ") + prev_box.to_string() + String(" to ") + new_box.to_string()); //print_line(String("Loaded area changed: from ") + prev_box.to_string() + String(" to ") + new_box.to_string());
Rect3i bounds = Rect3i::get_bounding_box(prev_box, new_box); Rect3i bounds = Rect3i::get_bounding_box(prev_box, new_box);
@ -550,18 +552,18 @@ void VoxelTerrain::_process() {
// TODO There should be a way to only iterate relevant blocks // TODO There should be a way to only iterate relevant blocks
Vector3i pos; Vector3i pos;
for(pos.z = bounds.pos.z; pos.z < max.z; ++pos.z) { for (pos.z = bounds.pos.z; pos.z < max.z; ++pos.z) {
for(pos.y = bounds.pos.y; pos.y < max.y; ++pos.y) { for (pos.y = bounds.pos.y; pos.y < max.y; ++pos.y) {
for(pos.x = bounds.pos.x; pos.x < max.x; ++pos.x) { for (pos.x = bounds.pos.x; pos.x < max.x; ++pos.x) {
bool prev_contains = prev_box.contains(pos); bool prev_contains = prev_box.contains(pos);
bool new_contains = new_box.contains(pos); bool new_contains = new_box.contains(pos);
if(prev_contains && !new_contains) { if (prev_contains && !new_contains) {
// Unload block // Unload block
immerge_block(pos); immerge_block(pos);
} else if(!prev_contains && new_contains) { } else if (!prev_contains && new_contains) {
// Load or update block // Load or update block
make_block_dirty(pos); make_block_dirty(pos);
} }
@ -612,14 +614,14 @@ void VoxelTerrain::_process() {
_stats.provider = output.stats; _stats.provider = output.stats;
_stats.dropped_provider_blocks = 0; _stats.dropped_provider_blocks = 0;
for(int i = 0; i < output.emerged_blocks.size(); ++i) { for (int i = 0; i < output.emerged_blocks.size(); ++i) {
const VoxelProviderThread::EmergeOutput &o = output.emerged_blocks[i]; const VoxelProviderThread::EmergeOutput &o = output.emerged_blocks[i];
Vector3i block_pos = _map->voxel_to_block(o.origin_in_voxels); Vector3i block_pos = _map->voxel_to_block(o.origin_in_voxels);
{ {
VoxelTerrain::BlockDirtyState *state = _dirty_blocks.getptr(block_pos); VoxelTerrain::BlockDirtyState *state = _dirty_blocks.getptr(block_pos);
if(state == NULL || *state != BLOCK_LOAD) { if (state == NULL || *state != BLOCK_LOAD) {
// That block was not requested, drop it // That block was not requested, drop it
++_stats.dropped_provider_blocks; ++_stats.dropped_provider_blocks;
continue; continue;
@ -677,7 +679,7 @@ void VoxelTerrain::_process() {
{ {
VoxelMeshUpdater::Input input; VoxelMeshUpdater::Input input;
for(int i = 0; i < _blocks_pending_update.size(); ++i) { for (int i = 0; i < _blocks_pending_update.size(); ++i) {
Vector3i block_pos = _blocks_pending_update[i]; Vector3i block_pos = _blocks_pending_update[i];
VoxelBlock *block = _map->get_block(block_pos); VoxelBlock *block = _map->get_block(block_pos);
@ -692,7 +694,7 @@ void VoxelTerrain::_process() {
CRASH_COND(*block_state != BLOCK_UPDATE_NOT_SENT); CRASH_COND(*block_state != BLOCK_UPDATE_NOT_SENT);
int air_type = 0; int air_type = 0;
if(block->voxels->is_uniform(Voxel::CHANNEL_TYPE) && block->voxels->get_voxel(0, 0, 0, Voxel::CHANNEL_TYPE) == air_type) { if (block->voxels->is_uniform(Voxel::CHANNEL_TYPE) && block->voxels->get_voxel(0, 0, 0, Voxel::CHANNEL_TYPE) == air_type) {
// The block contains empty voxels // The block contains empty voxels
block->set_mesh(Ref<Mesh>(), Ref<World>()); block->set_mesh(Ref<Mesh>(), Ref<World>());
@ -784,7 +786,7 @@ void VoxelTerrain::_process() {
++surface_index; ++surface_index;
} }
for(int i = 0; i < ob.smooth_surfaces.size(); ++i) { for (int i = 0; i < ob.smooth_surfaces.size(); ++i) {
Array surface = ob.smooth_surfaces[i]; Array surface = ob.smooth_surfaces[i];
if (surface.empty()) if (surface.empty())
@ -887,10 +889,10 @@ Vector3 VoxelTerrain::_block_to_voxel_binding(Vector3 pos) {
VoxelTerrain::BlockDirtyState VoxelTerrain::get_block_state(Vector3 p_bpos) const { VoxelTerrain::BlockDirtyState VoxelTerrain::get_block_state(Vector3 p_bpos) const {
Vector3i bpos = p_bpos; Vector3i bpos = p_bpos;
const VoxelTerrain::BlockDirtyState *state = _dirty_blocks.getptr(bpos); const VoxelTerrain::BlockDirtyState *state = _dirty_blocks.getptr(bpos);
if(state) { if (state) {
return *state; return *state;
} else { } else {
if(!_map->has_block(bpos)) if (!_map->has_block(bpos))
return BLOCK_NONE; return BLOCK_NONE;
return BLOCK_IDLE; return BLOCK_IDLE;
} }

View File

@ -1,12 +1,12 @@
#ifndef VOXEL_TERRAIN_H #ifndef VOXEL_TERRAIN_H
#define VOXEL_TERRAIN_H #define VOXEL_TERRAIN_H
#include "rect3i.h"
#include "vector3i.h" #include "vector3i.h"
#include "zprofiling.h" #include "voxel_mesh_updater.h"
#include "voxel_provider.h" #include "voxel_provider.h"
#include "voxel_provider_thread.h" #include "voxel_provider_thread.h"
#include "voxel_mesh_updater.h" #include "zprofiling.h"
#include "rect3i.h"
#include <scene/3d/spatial.h> #include <scene/3d/spatial.h>
@ -15,10 +15,9 @@ class VoxelLibrary;
// Infinite static terrain made of voxels. // Infinite static terrain made of voxels.
// It is loaded around VoxelTerrainStreamers. // It is loaded around VoxelTerrainStreamers.
class VoxelTerrain : public Spatial /*, public IVoxelMapObserver*/ { class VoxelTerrain : public Spatial {
GDCLASS(VoxelTerrain, Spatial) GDCLASS(VoxelTerrain, Spatial)
public: public:
enum BlockDirtyState { enum BlockDirtyState {
BLOCK_NONE, BLOCK_NONE,
BLOCK_LOAD, BLOCK_LOAD,
@ -70,18 +69,17 @@ public:
uint64_t time_send_update_requests; uint64_t time_send_update_requests;
uint64_t time_process_update_responses; uint64_t time_process_update_responses;
Stats(): Stats() :
mesh_alloc_time(0), mesh_alloc_time(0),
updated_blocks(0), updated_blocks(0),
dropped_provider_blocks(0), dropped_provider_blocks(0),
dropped_updater_blocks(0), dropped_updater_blocks(0),
remaining_main_thread_blocks(0), remaining_main_thread_blocks(0),
time_detect_required_blocks(0), time_detect_required_blocks(0),
time_send_load_requests(0), time_send_load_requests(0),
time_process_load_responses(0), time_process_load_responses(0),
time_send_update_requests(0), time_send_update_requests(0),
time_process_update_responses(0) time_process_update_responses(0) {}
{ }
}; };
protected: protected: