Now VoxelChunkDefault supports coloring MeshDataResources that span multiple chunks.

This commit is contained in:
Relintai 2020-08-16 18:20:16 +02:00
parent d8cf2af059
commit 5358c99646
7 changed files with 202 additions and 1 deletions

View File

@ -481,6 +481,49 @@ void VoxelMesher::add_mesh_data_resource_transform(Ref<MeshDataResource> mesh, c
_indices.set(orig_indices_count + i, orig_vert_size + indices[i]);
}
}
void VoxelMesher::add_mesh_data_resource_transform_colored(Ref<MeshDataResource> mesh, const Transform transform, const PoolColorArray &colors, const Rect2 uv_rect) {
if (mesh->get_array().size() == 0)
return;
const Array &arr = mesh->get_array();
PoolVector3Array vertices = arr[Mesh::ARRAY_VERTEX];
PoolVector3Array normals = arr[Mesh::ARRAY_NORMAL];
PoolVector2Array uvs = arr[Mesh::ARRAY_TEX_UV];
PoolIntArray indices = arr[Mesh::ARRAY_INDEX];
if (vertices.size() == 0)
return;
int orig_vert_size = _vertices.size();
for (int i = 0; i < vertices.size(); ++i) {
if (normals.size() > 0)
add_normal(transform.basis.xform(normals[i]));
if (normals.size() > 0) {
Vector2 uv = uvs[i];
uv.x = uv_rect.size.width * uv.x + uv_rect.position.x;
uv.y = uv_rect.size.height * uv.y + uv_rect.position.y;
add_uv(uv);
}
if (colors.size() > 0)
add_color(colors[i]);
add_vertex(transform.xform(vertices[i]));
}
int orig_indices_count = _indices.size();
_indices.resize(_indices.size() + indices.size());
for (int i = 0; i < indices.size(); ++i) {
_indices.set(orig_indices_count + i, orig_vert_size + indices[i]);
}
}
#endif
void VoxelMesher::add_mesher(const Ref<VoxelMesher> &mesher) {
@ -911,6 +954,7 @@ void VoxelMesher::_bind_methods() {
#ifdef MESH_DATA_RESOURCE_PRESENT
ClassDB::bind_method(D_METHOD("add_mesh_data_resource", "mesh", "position", "rotation", "scale", "uv_rect"), &VoxelMesher::add_mesh_data_resource, DEFVAL(Rect2(0, 0, 1, 1)), DEFVAL(Vector3(1.0, 1.0, 1.0)), DEFVAL(Vector3()), DEFVAL(Vector3()));
ClassDB::bind_method(D_METHOD("add_mesh_data_resource_transform", "mesh", "transform", "uv_rect"), &VoxelMesher::add_mesh_data_resource_transform, DEFVAL(Rect2(0, 0, 1, 1)));
ClassDB::bind_method(D_METHOD("add_mesh_data_resource_transform_colored", "mesh", "transform", "colors", "uv_rect"), &VoxelMesher::add_mesh_data_resource_transform_colored, DEFVAL(Rect2(0, 0, 1, 1)));
#endif
BIND_VMETHOD(MethodInfo("_add_mesher", PropertyInfo(Variant::OBJECT, "mesher", PROPERTY_HINT_RESOURCE_TYPE, "VoxelMesher")));

View File

@ -121,6 +121,7 @@ public:
#ifdef MESH_DATA_RESOURCE_PRESENT
void add_mesh_data_resource(Ref<MeshDataResource> mesh, const Vector3 position = Vector3(0, 0, 0), const Vector3 rotation = Vector3(0, 0, 0), const Vector3 scale = Vector3(1.0, 1.0, 1.0), const Rect2 uv_rect = Rect2(0, 0, 1, 1));
void add_mesh_data_resource_transform(Ref<MeshDataResource> mesh, const Transform transform, const Rect2 uv_rect = Rect2(0, 0, 1, 1));
void add_mesh_data_resource_transform_colored(Ref<MeshDataResource> mesh, const Transform transform, const PoolColorArray &colors, const Rect2 uv_rect = Rect2(0, 0, 1, 1));
#endif
void add_mesher(const Ref<VoxelMesher> &mesher);

View File

@ -34,6 +34,8 @@ SOFTWARE.
#include "../../../thread_pool/thread_pool.h"
#include "voxel_job.h"
#include "voxel_world_default.h"
const String VoxelChunkDefault::BINDING_STRING_ACTIVE_BUILD_PHASE_TYPE = "Normal,Process,Physics Process";
const String VoxelChunkDefault::BINDING_STRING_BUILD_FLAGS = "Use Isolevel,Use Lighting,Use AO,Use RAO,Generate AO,Generate RAO,Bake Lights,Create Collider,Create Lods";
@ -1706,7 +1708,9 @@ void VoxelChunkDefault::_build_phase(int phase) {
}
for (int i = 0; i < get_mesh_data_resource_count(); ++i) {
get_prop_mesher()->add_mesh_data_resource_transform(get_mesh_data_resource(i), get_mesh_data_resource_transform(i), get_mesh_data_resource_uv_rect(i));
if (get_mesh_data_resource_is_inside(i)) {
get_prop_mesher()->add_mesh_data_resource_transform(get_mesh_data_resource(i), get_mesh_data_resource_transform(i), get_mesh_data_resource_uv_rect(i));
}
}
if (get_prop_mesher()->get_vertex_count() == 0) {
@ -1731,6 +1735,44 @@ void VoxelChunkDefault::_build_phase(int phase) {
}
}
if (_job->should_do()) {
if ((_build_flags & VoxelChunkDefault::BUILD_FLAG_USE_LIGHTING) != 0) {
VoxelWorldDefault *world = Object::cast_to<VoxelWorldDefault>(get_voxel_world());
if (world) {
for (int i = 0; i < get_mesh_data_resource_count(); ++i) {
if (!get_mesh_data_resource_is_inside(i)) {
Ref<MeshDataResource> mdr = get_mesh_data_resource(i);
ERR_CONTINUE(!mdr.is_valid());
Transform trf = get_mesh_data_resource_transform(i);
Array arr = mdr->get_array();
if (arr.size() <= Mesh::ARRAY_VERTEX) {
continue;
}
PoolVector3Array varr = arr[Mesh::ARRAY_VERTEX];
if (varr.size() == 0) {
continue;
}
PoolColorArray carr = world->get_vertex_colors(trf, varr);
get_prop_mesher()->add_mesh_data_resource_transform_colored(mdr, trf, carr, get_mesh_data_resource_uv_rect(i));
}
}
}
}
if (_job->should_return()) {
return;
}
}
if (get_prop_mesher()->get_vertex_count() != 0) {
if (_job->should_do()) {
temp_mesh_arr = get_prop_mesher()->build_mesh();

View File

@ -60,6 +60,70 @@ void VoxelWorldDefault::set_chunk_lod_falloff(const int value) {
_chunk_lod_falloff = value;
}
PoolColorArray VoxelWorldDefault::get_vertex_colors(const Transform &transform, const PoolVector3Array &vertices, const float base_light_value, const float ao_strength) {
PoolColorArray arr;
arr.resize(vertices.size());
for (int i = 0; i < vertices.size(); ++i) {
Vector3 v = transform.xform(vertices[i]);
Vector3 pos = v / get_voxel_scale();
//Note: floor is needed to handle negative numbers proiberly
int x = static_cast<int>(Math::floor(pos.x / get_chunk_size_x()));
int y = static_cast<int>(Math::floor(pos.y / get_chunk_size_y()));
int z = static_cast<int>(Math::floor(pos.z / get_chunk_size_z()));
int bx = static_cast<int>(Math::floor(pos.x)) % get_chunk_size_x();
int by = static_cast<int>(Math::floor(pos.y)) % get_chunk_size_y();
int bz = static_cast<int>(Math::floor(pos.z)) % get_chunk_size_z();
if (bx < 0) {
bx += get_chunk_size_x();
}
if (by < 0) {
by += get_chunk_size_y();
}
if (bz < 0) {
bz += get_chunk_size_z();
}
Ref<VoxelChunk> chunk = get_chunk(x, y, z);
if (chunk.is_valid()) {
Color light = Color(
chunk->get_voxel(bx, by, bz, VoxelChunkDefault::DEFAULT_CHANNEL_LIGHT_COLOR_R) / 255.0,
chunk->get_voxel(bx, by, bz, VoxelChunkDefault::DEFAULT_CHANNEL_LIGHT_COLOR_G) / 255.0,
chunk->get_voxel(bx, by, bz, VoxelChunkDefault::DEFAULT_CHANNEL_LIGHT_COLOR_B) / 255.0);
float ao = (chunk->get_voxel(bx, by, bz, VoxelChunkDefault::DEFAULT_CHANNEL_AO) / 255.0) * ao_strength;
float rao = chunk->get_voxel(bx, by, bz, VoxelChunkDefault::DEFAULT_CHANNEL_RANDOM_AO) / 255.0;
ao += rao;
light.r += base_light_value;
light.g += base_light_value;
light.b += base_light_value;
light.r -= ao;
light.g -= ao;
light.b -= ao;
light.r = CLAMP(light.r, 0, 1.0);
light.g = CLAMP(light.g, 0, 1.0);
light.b = CLAMP(light.b, 0, 1.0);
arr.set(i, light);
} else {
arr.set(i, Color(base_light_value, base_light_value, base_light_value));
}
}
return arr;
}
void VoxelWorldDefault::_update_lods() {
if (!get_player() || !INSTANCE_VALIDATE(get_player())) {
return;
@ -188,4 +252,6 @@ void VoxelWorldDefault::_bind_methods() {
BIND_VMETHOD(MethodInfo("_update_lods"));
ClassDB::bind_method(D_METHOD("update_lods"), &VoxelWorldDefault::update_lods);
ClassDB::bind_method(D_METHOD("_update_lods"), &VoxelWorldDefault::_update_lods);
ClassDB::bind_method(D_METHOD("get_vertex_colors", "transform", "vertices", "base_light_value", "ao_strength"), &VoxelWorldDefault::get_vertex_colors, DEFVAL(0.45), DEFVAL(0.2));
}

View File

@ -40,6 +40,8 @@ public:
void update_lods();
PoolColorArray get_vertex_colors(const Transform &transform, const PoolVector3Array &vertices, const float base_light_value = 0.45, const float ao_strength = 0.2);
VoxelWorldDefault();
~VoxelWorldDefault();

View File

@ -105,6 +105,17 @@ void VoxelChunk::set_position_z(const int value) {
_FORCE_INLINE_ Vector3 VoxelChunk::get_position() const {
return Vector3(_position_x, _position_y, _position_z);
}
_FORCE_INLINE_ Vector3 VoxelChunk::get_world_position() const {
return Vector3(_position_x * _size_x * _voxel_scale, _position_y * _size_y * _voxel_scale, _position_z * _size_z * _voxel_scale);
}
_FORCE_INLINE_ Vector3 VoxelChunk::get_world_size() const {
return Vector3(_size_x * _voxel_scale, _size_y * _voxel_scale, _size_z * _voxel_scale);
}
_FORCE_INLINE_ AABB VoxelChunk::get_world_aabb() const {
return AABB(get_world_position(), get_world_size());
}
_FORCE_INLINE_ int VoxelChunk::get_size_x() const {
return _size_x;
@ -726,6 +737,10 @@ int VoxelChunk::add_mesh_data_resourcev(const Vector3 &local_data_pos, const Ref
e.texture = texture;
e.color = color;
AABB aabb = AABB(Vector3(), get_world_size());
AABB mesh_aabb = e.transform.xform(mesh->get_aabb());
e.is_inside = aabb.encloses(mesh_aabb);
if (get_library().is_valid() && texture.is_valid()) {
e.uv_rect = get_library()->get_prop_uv_rect(texture);
} else {
@ -758,6 +773,10 @@ int VoxelChunk::add_mesh_data_resource(const Transform &local_transform, const R
e.texture = texture;
e.color = color;
AABB aabb = AABB(Vector3(), get_world_size());
AABB mesh_aabb = e.transform.xform(mesh->get_aabb());
e.is_inside = aabb.encloses(mesh_aabb);
if (get_library().is_valid() && texture.is_valid())
e.uv_rect = get_library()->get_prop_uv_rect(texture);
else
@ -825,6 +844,17 @@ void VoxelChunk::set_mesh_data_resource_transform(const int index, const Transfo
_mesh_data_resources.write[index].transform = transform;
}
bool VoxelChunk::get_mesh_data_resource_is_inside(const int index) {
ERR_FAIL_INDEX_V(index, _mesh_data_resources.size(), true);
return _mesh_data_resources[index].is_inside;
}
void VoxelChunk::set_mesh_data_resource_is_inside(const int index, const bool &inside) {
ERR_FAIL_INDEX(index, _mesh_data_resources.size());
_mesh_data_resources.write[index].is_inside = inside;
}
int VoxelChunk::get_mesh_data_resource_count() const {
return _mesh_data_resources.size();
}
@ -1191,6 +1221,10 @@ void VoxelChunk::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_position"), &VoxelChunk::get_position);
ClassDB::bind_method(D_METHOD("set_position", "x", "y", "z"), &VoxelChunk::set_position);
ClassDB::bind_method(D_METHOD("get_world_position"), &VoxelChunk::get_world_position);
ClassDB::bind_method(D_METHOD("get_world_size"), &VoxelChunk::get_world_size);
ClassDB::bind_method(D_METHOD("get_world_aabb"), &VoxelChunk::get_world_aabb);
ClassDB::bind_method(D_METHOD("get_margin_start"), &VoxelChunk::get_margin_start);
ClassDB::bind_method(D_METHOD("set_margin_start"), &VoxelChunk::set_margin_start);
ADD_PROPERTY(PropertyInfo(Variant::INT, "margin_start"), "set_margin_start", "get_margin_start");
@ -1285,6 +1319,9 @@ void VoxelChunk::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_mesh_data_resource_transform", "index"), &VoxelChunk::get_mesh_data_resource_transform);
ClassDB::bind_method(D_METHOD("set_mesh_data_resource_transform", "index", "transform"), &VoxelChunk::set_mesh_data_resource_transform);
ClassDB::bind_method(D_METHOD("get_mesh_data_resource_is_inside", "index"), &VoxelChunk::get_mesh_data_resource_is_inside);
ClassDB::bind_method(D_METHOD("set_mesh_data_resource_is_inside", "index", "inside"), &VoxelChunk::set_mesh_data_resource_is_inside);
ClassDB::bind_method(D_METHOD("get_mesh_data_resource_count"), &VoxelChunk::get_mesh_data_resource_count);
ClassDB::bind_method(D_METHOD("remove_mesh_data_resource", "index"), &VoxelChunk::remove_mesh_data_resource);
ClassDB::bind_method(D_METHOD("clear_mesh_data_resources"), &VoxelChunk::clear_mesh_data_resources);

View File

@ -116,6 +116,11 @@ public:
Vector3 get_position() const;
Vector3 get_size() const;
Vector3 get_world_position() const;
Vector3 get_world_size() const;
AABB get_world_aabb() const;
void set_position(const int x, const int y, const int z);
int get_margin_start() const;
@ -222,6 +227,9 @@ public:
Transform get_mesh_data_resource_transform(const int index);
void set_mesh_data_resource_transform(const int index, const Transform &transform);
bool get_mesh_data_resource_is_inside(const int index);
void set_mesh_data_resource_is_inside(const int index, const bool &inside);
int get_mesh_data_resource_count() const;
void remove_mesh_data_resource(const int index);
void clear_mesh_data_resources();
@ -281,6 +289,7 @@ protected:
Color color;
Rect2 uv_rect;
Transform transform;
bool is_inside;
};
#endif