mirror of
https://github.com/Relintai/voxelman.git
synced 2024-11-12 10:15:12 +01:00
375 lines
10 KiB
C++
375 lines
10 KiB
C++
#include "voxel_chunk.h"
|
|
|
|
NodePath VoxelChunk::get_library_path() {
|
|
return _library_path;
|
|
}
|
|
void VoxelChunk::set_library_path(NodePath value) {
|
|
_library_path = value;
|
|
}
|
|
|
|
NodePath VoxelChunk::get_mesh_instance_path() {
|
|
return _mesh_instance_path;
|
|
}
|
|
void VoxelChunk::set_mesh_instance_path(NodePath value) {
|
|
_mesh_instance_path = value;
|
|
}
|
|
|
|
Ref<VoxelmanLibrary> VoxelChunk::get_library() {
|
|
return _library;
|
|
}
|
|
void VoxelChunk::set_library(Ref<VoxelmanLibrary> value) {
|
|
_library = value;
|
|
}
|
|
|
|
float VoxelChunk::get_voxel_scale() {
|
|
return _voxel_scale;
|
|
}
|
|
void VoxelChunk::set_voxel_scale(float value) {
|
|
_voxel_scale = value;
|
|
}
|
|
|
|
Ref<VoxelMesher> VoxelChunk::get_mesher() const {
|
|
return _mesher;
|
|
}
|
|
void VoxelChunk::set_mesher(Ref<VoxelMesher> mesher) {
|
|
_mesher = mesher;
|
|
}
|
|
|
|
bool VoxelChunk::get_build_mesh() {
|
|
return _build_mesh;
|
|
}
|
|
void VoxelChunk::set_build_mesh(bool value) {
|
|
_build_mesh = value;
|
|
}
|
|
|
|
bool VoxelChunk::get_create_collider() {
|
|
return _create_collider;
|
|
}
|
|
void VoxelChunk::set_create_collider(bool value) {
|
|
_create_collider = value;
|
|
}
|
|
|
|
bool VoxelChunk::get_bake_lights() {
|
|
return _bake_lights;
|
|
}
|
|
void VoxelChunk::set_bake_lights(bool value) {
|
|
_bake_lights = value;
|
|
}
|
|
|
|
NodePath VoxelChunk::get_debug_drawer_path() {
|
|
return _debug_drawer_path;
|
|
}
|
|
void VoxelChunk::set_debug_drawer_path(NodePath value) {
|
|
_debug_drawer_path = value;
|
|
}
|
|
|
|
Ref<VoxelBuffer> VoxelChunk::get_buffer() const {
|
|
return _buffer;
|
|
}
|
|
|
|
void VoxelChunk::clear() {
|
|
_voxel_lights.clear();
|
|
}
|
|
|
|
void VoxelChunk::build() {
|
|
ERR_FAIL_COND(!_library.is_valid());
|
|
ERR_FAIL_COND(!_mesher.is_valid());
|
|
|
|
_mesher->set_library(_library);
|
|
|
|
if (_debug_drawer == NULL) {
|
|
Node *n = get_node_or_null(_debug_drawer_path);
|
|
|
|
if (n != NULL) {
|
|
_debug_drawer = Object::cast_to<ImmediateGeometry>(n);
|
|
}
|
|
}
|
|
|
|
if (get_build_mesh()) {
|
|
if (has_method("_create_mesh")) {
|
|
call("_create_mesh");
|
|
} else {
|
|
_mesher->add_buffer(_buffer);
|
|
}
|
|
|
|
finalize_mesh();
|
|
}
|
|
|
|
if (get_create_collider()) {
|
|
update_collider();
|
|
}
|
|
}
|
|
|
|
void VoxelChunk::finalize_mesh() {
|
|
_mesher->set_library(_library);
|
|
|
|
Node *node = get_node(_mesh_instance_path);
|
|
|
|
ERR_FAIL_COND(node == NULL);
|
|
|
|
_mesh_instance = Object::cast_to<MeshInstance>(node);
|
|
|
|
ERR_FAIL_COND(_mesh_instance == NULL);
|
|
|
|
//if (get_bake_ambient_occlusion()) {
|
|
// set_enabled(true);
|
|
//} else {
|
|
Ref<ArrayMesh> mesh = get_mesher()->build_mesh();
|
|
|
|
_mesh_instance->set_mesh(mesh);
|
|
//}
|
|
}
|
|
|
|
void VoxelChunk::update_collider() {
|
|
//_mesh_instance->create_trimesh_collision();
|
|
//StaticBody *static_body = Object::cast_to<StaticBody>(create_trimesh_collision_node());
|
|
|
|
StaticBody *static_body = create_trimesh_collision_node();
|
|
ERR_FAIL_COND(!static_body);
|
|
static_body->set_name(String(get_name()) + "_col");
|
|
|
|
add_child(static_body);
|
|
if (get_owner()) {
|
|
CollisionShape *cshape = Object::cast_to<CollisionShape>(static_body->get_child(0));
|
|
static_body->set_owner(get_owner());
|
|
cshape->set_owner(get_owner());
|
|
}
|
|
}
|
|
|
|
StaticBody *VoxelChunk::create_trimesh_collision_node() {
|
|
|
|
Ref<ConcavePolygonShape> shape = memnew(ConcavePolygonShape);
|
|
|
|
_mesher->create_trimesh_shape(shape);
|
|
|
|
StaticBody *static_body = memnew(StaticBody);
|
|
CollisionShape *cshape = memnew(CollisionShape);
|
|
cshape->set_shape(shape);
|
|
static_body->add_child(cshape);
|
|
return static_body;
|
|
}
|
|
|
|
void VoxelChunk::set_enabled(bool p_enabled) {
|
|
|
|
_enabled = p_enabled;
|
|
|
|
if (is_inside_tree())
|
|
set_physics_process_internal(p_enabled);
|
|
}
|
|
|
|
bool VoxelChunk::is_enabled() const {
|
|
return _enabled;
|
|
}
|
|
|
|
void VoxelChunk::add_voxel_light_bind(Vector3 position, Color color, float strength) {
|
|
add_voxel_light(position, color, strength);
|
|
}
|
|
|
|
Ref<VoxelLight> VoxelChunk::add_voxel_light(Vector3i position, Color color, float strength, Vector3 offset) {
|
|
Vector3 pos(position.x, position.y, position.z);
|
|
|
|
Ref<VoxelLight> light = Ref<VoxelLight>(memnew(VoxelLight(position, color, strength, to_global(pos + Vector3((float)0.5, (float)0.5, (float)0.5) * _voxel_scale), offset)));
|
|
|
|
_voxel_lights.push_back(light);
|
|
|
|
return light;
|
|
}
|
|
|
|
void VoxelChunk::draw_cross_voxels(Vector3 pos) {
|
|
pos *= _voxel_scale;
|
|
|
|
_debug_drawer->add_vertex(pos + Vector3(0, 0, -0.2));
|
|
_debug_drawer->add_vertex(pos + Vector3(0, 0, 0.2));
|
|
|
|
_debug_drawer->add_vertex(pos + Vector3(0, -0.2, 0));
|
|
_debug_drawer->add_vertex(pos + Vector3(0, 0.2, 0));
|
|
|
|
_debug_drawer->add_vertex(pos + Vector3(-0.2, 0, 0));
|
|
_debug_drawer->add_vertex(pos + Vector3(0.2, 0, 0));
|
|
}
|
|
|
|
void VoxelChunk::draw_cross_voxels(Vector3 pos, float fill) {
|
|
pos *= _voxel_scale;
|
|
|
|
_debug_drawer->add_vertex(pos + Vector3(0, 0, -0.5 * fill));
|
|
_debug_drawer->add_vertex(pos + Vector3(0, 0, 0.5 * fill));
|
|
|
|
_debug_drawer->add_vertex(pos + Vector3(0, -0.5 * fill, 0));
|
|
_debug_drawer->add_vertex(pos + Vector3(0, 0.5 * fill, 0));
|
|
|
|
_debug_drawer->add_vertex(pos + Vector3(-0.5 * fill, 0, 0));
|
|
_debug_drawer->add_vertex(pos + Vector3(0.5 * fill, 0, 0));
|
|
}
|
|
|
|
void VoxelChunk::draw_debug_voxels(int max, Color color) {
|
|
if (_debug_drawer == NULL) {
|
|
Node *n = get_node(_debug_drawer_path);
|
|
|
|
if (n != NULL) {
|
|
_debug_drawer = Object::cast_to<ImmediateGeometry>(n);
|
|
}
|
|
}
|
|
|
|
ERR_FAIL_COND(_debug_drawer == NULL);
|
|
|
|
_debug_drawer->clear();
|
|
_debug_drawer->begin(Mesh::PRIMITIVE_LINES);
|
|
_debug_drawer->set_color(color);
|
|
|
|
int a = 0;
|
|
Vector3i size = _buffer->get_size();
|
|
|
|
for (int y = 0; y < size.y; ++y) {
|
|
for (int z = 0; z < size.z; ++z) {
|
|
for (int x = 0; x < size.x; ++x) {
|
|
|
|
int type = _buffer->get_voxel(x, y, z, VoxelBuffer::CHANNEL_TYPE);
|
|
|
|
if (type == 0) {
|
|
continue;
|
|
}
|
|
|
|
draw_cross_voxels(Vector3(x + 0.5, y + 0.5, z + 0.5), _buffer->get_voxel(x, y, z, VoxelBuffer::CHANNEL_ISOLEVEL) / 255.0);
|
|
|
|
++a;
|
|
|
|
if (a > max) {
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
_debug_drawer->end();
|
|
}
|
|
|
|
void VoxelChunk::draw_debug_voxel_lights(int max, bool localPosition) {
|
|
/*
|
|
if (_debug_drawer == NULL) {
|
|
Node *n = get_node(_debug_drawer_path);
|
|
|
|
if (n != NULL) {
|
|
_debug_drawer = Object::cast_to<ImmediateGeometry>(n);
|
|
}
|
|
}
|
|
|
|
if (_debug_drawer == NULL) {
|
|
return;
|
|
}
|
|
|
|
_debug_drawer->clear();
|
|
_debug_drawer->begin(Mesh::PrimitiveType::PRIMITIVE_LINES);
|
|
_debug_drawer->set_color(Color(1, 1, 1));
|
|
|
|
const int *k = NULL;
|
|
|
|
Vector3 pos = get_transform().get_origin();
|
|
|
|
int a = 0;
|
|
while ((k = _voxel_lights->next(k))) {
|
|
Ref<VoxelLight> v = _voxel_lights->get(*k);
|
|
|
|
if (localPosition) {
|
|
Vector3i lp = v->get_local_position();
|
|
draw_cross_voxels(pos + Vector3(lp.x, lp.y, lp.z), (float)v->get_strength() / (float)10);
|
|
} else {
|
|
Vector3i wp = v->get_world_position();
|
|
draw_cross_voxels(pos + Vector3(wp.x, wp.y, wp.z), (float)v->get_strength() / (float)10);
|
|
}
|
|
++a;
|
|
|
|
if (a > max) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
_debug_drawer->end();*/
|
|
}
|
|
|
|
void VoxelChunk::_bind_methods() {
|
|
BIND_VMETHOD(MethodInfo("_create_mesh"));
|
|
|
|
ClassDB::bind_method(D_METHOD("get_library_path"), &VoxelChunk::get_library_path);
|
|
ClassDB::bind_method(D_METHOD("set_library_path", "value"), &VoxelChunk::set_library_path);
|
|
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "library_path"), "set_library_path", "get_library_path");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_mesh_instance_path"), &VoxelChunk::get_mesh_instance_path);
|
|
ClassDB::bind_method(D_METHOD("set_mesh_instance_path", "value"), &VoxelChunk::set_mesh_instance_path);
|
|
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "mesh_instance_path"), "set_mesh_instance_path", "get_mesh_instance_path");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_library"), &VoxelChunk::get_library);
|
|
ClassDB::bind_method(D_METHOD("set_library", "value"), &VoxelChunk::set_library);
|
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "library", PROPERTY_HINT_RESOURCE_TYPE, "VoxelmanLibrary"), "set_library", "get_library");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_voxel_scale"), &VoxelChunk::get_voxel_scale);
|
|
ClassDB::bind_method(D_METHOD("set_voxel_scale", "value"), &VoxelChunk::set_voxel_scale);
|
|
ADD_PROPERTY(PropertyInfo(Variant::REAL, "voxel_scale"), "set_voxel_scale", "get_voxel_scale");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_buffer"), &VoxelChunk::get_buffer);
|
|
|
|
ADD_GROUP("Meshing", "meshing");
|
|
|
|
ClassDB::bind_method(D_METHOD("meshing_get_build_mesh"), &VoxelChunk::get_build_mesh);
|
|
ClassDB::bind_method(D_METHOD("meshing_set_build_mesh", "value"), &VoxelChunk::set_build_mesh);
|
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meshing_build_mesh"), "meshing_set_build_mesh", "meshing_get_build_mesh");
|
|
|
|
ClassDB::bind_method(D_METHOD("meshing_get_create_collider"), &VoxelChunk::get_create_collider);
|
|
ClassDB::bind_method(D_METHOD("meshing_set_create_collider", "value"), &VoxelChunk::set_create_collider);
|
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meshing_create_collider"), "meshing_set_create_collider", "meshing_get_create_collider");
|
|
|
|
ClassDB::bind_method(D_METHOD("meshing_get_bake_lights"), &VoxelChunk::get_bake_lights);
|
|
ClassDB::bind_method(D_METHOD("meshing_set_bake_lights", "value"), &VoxelChunk::set_bake_lights);
|
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meshing_bake_lights"), "meshing_set_bake_lights", "meshing_get_bake_lights");
|
|
|
|
ADD_GROUP("Settings", "setting");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_debug_drawer_path"), &VoxelChunk::get_debug_drawer_path);
|
|
ClassDB::bind_method(D_METHOD("set_debug_drawer_path", "value"), &VoxelChunk::set_debug_drawer_path);
|
|
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "debug_drawer_path"), "set_debug_drawer_path", "get_debug_drawer_path");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_mesher"), &VoxelChunk::get_mesher);
|
|
ClassDB::bind_method(D_METHOD("set_mesher", "Mesher"), &VoxelChunk::set_mesher);
|
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesher", PROPERTY_HINT_RESOURCE_TYPE, "VoxelMesher"), "set_mesher", "get_mesher");
|
|
|
|
ClassDB::bind_method(D_METHOD("build"), &VoxelChunk::build);
|
|
ClassDB::bind_method(D_METHOD("finalize_mesh"), &VoxelChunk::finalize_mesh);
|
|
|
|
ClassDB::bind_method(D_METHOD("clear"), &VoxelChunk::clear);
|
|
|
|
ClassDB::bind_method(D_METHOD("draw_debug_voxels", "max"), &VoxelChunk::draw_debug_voxels, DEFVAL(Color(1, 1, 1)));
|
|
ClassDB::bind_method(D_METHOD("draw_debug_voxel_lights", "max", "localPosition"), &VoxelChunk::draw_debug_voxel_lights);
|
|
}
|
|
|
|
VoxelChunk::VoxelChunk() {
|
|
_build_mesh = true;
|
|
_create_collider = true;
|
|
_bake_lights = true;
|
|
|
|
_voxel_scale = 1;
|
|
|
|
_buffer.instance();
|
|
|
|
_debug_drawer = NULL;
|
|
}
|
|
|
|
VoxelChunk::~VoxelChunk() {
|
|
_voxel_lights.clear();
|
|
|
|
if (_mesher.is_valid()) {
|
|
_mesher.unref();
|
|
}
|
|
|
|
_buffer.unref();
|
|
|
|
_debug_drawer = NULL;
|
|
|
|
if (_library.is_valid()) {
|
|
_library.unref();
|
|
}
|
|
|
|
if (_mesh.is_valid()) {
|
|
_mesh.unref();
|
|
}
|
|
}
|