Fixed the voxel mesher, and converted it to c++. Also small bugfixes, and binding improvements. ALso moved a few export variables from GDscript to bindings.

This commit is contained in:
Relintai 2019-07-17 17:01:12 +02:00
parent e4e38c0bde
commit 469773a9fd
9 changed files with 213 additions and 26 deletions

View File

@ -18,6 +18,15 @@ const unsigned int VoxelCubePoints::visibility_check_table[6] = {
VOXEL_NEIGHBOUR_BOTTOM //VOXEL_FACE_BOTTOM 5
};
const int VoxelCubePoints::face_light_direction_table[6][3] = {
{ 0, 0, -1 }, //VOXEL_FACE_FRONT 0
{ -1, 0, 0 }, //VOXEL_FACE_RIGHT 1
{ 0, 0, 1 }, //VOXEL_FACE_BACK 2
{ 1, 0, 0 }, //VOXEL_FACE_LEFT 3
{ 0, -1, 0 }, //VOXEL_FACE_TOP 4
{ 0, 1, 0 } //VOXEL_FACE_BOTTOM 5
};
const float VoxelCubePoints::point_direction_table[8][3] = {
{ -0.5, -0.5, -0.5 }, //P000
{ 0.5, -0.5, -0.5 }, //P100
@ -615,6 +624,12 @@ Color VoxelCubePoints::get_face_point_color_mixed(int face, int index) {
return _point_colors[indx] - Color(ao_value, ao_value, ao_value);
}
Vector3 VoxelCubePoints::get_face_light_direction(int face) {
ERR_FAIL_INDEX_V(face, VOXEL_FACE_COUNT, Vector3());
return Vector3(face_light_direction_table[face][0], face_light_direction_table[face][1], face_light_direction_table[face][2]);
}
Vector3 VoxelCubePoints::get_point(int index) {
ERR_FAIL_INDEX_V(index, POINT_COUNT, Vector3());
@ -787,6 +802,8 @@ void VoxelCubePoints::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_face_point_light_color", "face", "index"), &VoxelCubePoints::get_face_point_light_color);
ClassDB::bind_method(D_METHOD("get_face_point_color_mixed", "face", "index"), &VoxelCubePoints::get_face_point_color_mixed);
ClassDB::bind_method(D_METHOD("get_face_light_direction", "face"), &VoxelCubePoints::get_face_light_direction);
ClassDB::bind_method(D_METHOD("get_point", "index"), &VoxelCubePoints::get_point);
ClassDB::bind_method(D_METHOD("get_top_left_point", "face"), &VoxelCubePoints::get_top_left_point);

View File

@ -113,13 +113,15 @@ public:
int get_point_type(int index);
int get_point_fill(int index);
int get_point_neighbours(int index);
int get_point_ao(int index);
int get_face_point_ao(int face, int index);
Color get_face_point_ao_color(int face, int index);
Color get_face_point_light_color(int face, int index);
Color get_face_point_color_mixed(int face, int index);
Vector3 get_face_light_direction(int face);
Vector3 get_point(int index);
Vector3 get_top_left_point(int face);
Vector3 get_top_right_point(int face);
@ -137,6 +139,7 @@ protected:
static const unsigned int index_table[6][4];
static const unsigned int visibility_check_table[6];
static const int face_light_direction_table[6][3];
static const float point_direction_table[8][3];
static const unsigned int point_direction_neighbour_table[8][3];
static const float uv_direction_table[8][4][2];

View File

@ -1,10 +1,102 @@
#include "voxel_mesher_cubic.h"
float VoxelMesherCubic::get_ao_strength() const {
return _ao_strength;
}
void VoxelMesherCubic::set_ao_strength(float value) {
_ao_strength = value;
}
void VoxelMesherCubic::_add_buffer(Ref<VoxelBuffer> buffer) {
buffer->generate_ao();
Vector3i bfs = buffer->get_size();
int x_size = bfs.x - 1;
int y_size = bfs.y - 1;
int z_size = bfs.z - 1;
float lod_size = get_lod_size();
float voxel_size = get_lod_size();
float voxel_scale = get_voxel_scale();
Ref<VoxelCubePoints> cube_points;
cube_points.instance();
float tile_uv_size = 1 / 4.0;
Color base_light(0.4, 0.4, 0.4);
for (int y = lod_size; y < y_size - lod_size; y += lod_size) {
for (int z = lod_size; z < z_size - lod_size; z += lod_size) {
for (int x = lod_size; x < x_size - lod_size; x += lod_size) {
cube_points->setup(buffer, x, y, z, lod_size);
if (!cube_points->has_points())
continue;
for (int face = 0; face < VoxelCubePoints::VOXEL_FACE_COUNT; ++face) {
if (!cube_points->is_face_visible(face))
continue;
add_indices(get_vertex_count() + 2);
add_indices(get_vertex_count() + 1);
add_indices(get_vertex_count() + 0);
add_indices(get_vertex_count() + 3);
add_indices(get_vertex_count() + 2);
add_indices(get_vertex_count() + 0);
Vector3 vertices[4] = {
cube_points->get_point_for_face(face, 0),
cube_points->get_point_for_face(face, 1),
cube_points->get_point_for_face(face, 2),
cube_points->get_point_for_face(face, 3)
};
Vector3 normals[4] = {
(vertices[3] - vertices[0]).cross(vertices[1] - vertices[0]),
(vertices[0] - vertices[1]).cross(vertices[2] - vertices[1]),
(vertices[1] - vertices[2]).cross(vertices[3] - vertices[2]),
(vertices[2] - vertices[3]).cross(vertices[0] - vertices[3])
};
Vector3 face_light_direction = cube_points->get_face_light_direction(face);
for (int i = 0; i < 4; ++i) {
Color light = cube_points->get_face_point_light_color(face, i);
light += base_light;
float NdotL = CLAMP(normals[i].dot(face_light_direction), 0, 1.0);
light *= NdotL;
light -= cube_points->get_face_point_ao_color(face, i) * _ao_strength;
add_color(light);
light.r = CLAMP(light.r, 0, 1.0);
light.g = CLAMP(light.g, 0, 1.0);
light.b = CLAMP(light.b, 0, 1.0);
add_uv((cube_points->get_point_uv_direction(face, i) + Vector2(0.5, 0.5)) * Vector2(tile_uv_size, tile_uv_size));
add_vertex((vertices[i] * voxel_size + Vector3(x, y, z)) * voxel_scale);
}
}
}
}
}
}
VoxelMesherCubic::VoxelMesherCubic() {
_ao_strength = 0.25;
}
VoxelMesherCubic::~VoxelMesherCubic() {
}
void VoxelMesherCubic::_bind_methods() {
ClassDB::bind_method(D_METHOD("_add_buffer", "buffer"), &VoxelMesherCubic::_add_buffer);
ClassDB::bind_method(D_METHOD("get_ao_strength"), &VoxelMesherCubic::get_ao_strength);
ClassDB::bind_method(D_METHOD("set_ao_strength", "value"), &VoxelMesherCubic::set_ao_strength);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "ao_strength"), "set_ao_strength", "get_ao_strength");
}

View File

@ -1,18 +1,31 @@
#ifndef VOXEL_MESHER_CUBIC_H
#define VOXEL_MESHER_CUBIC_H
#include "core/color.h"
#include "core/math/vector3.h"
#include "core/math/vector2.h"
#include "../voxel_mesher.h"
#include "voxel_cube_points.h"
class VoxelMesherCubic : public VoxelMesher {
GDCLASS(VoxelMesherCubic, VoxelMesher);
public:
float get_ao_strength() const;
void set_ao_strength(float value);
void _add_buffer(Ref<VoxelBuffer> buffer);
VoxelMesherCubic();
~VoxelMesherCubic();
protected:
static void _bind_methods();
private:
float _ao_strength;
};
#endif

View File

@ -3,19 +3,18 @@
VoxelMesher::VoxelMesher(Ref<VoxelmanLibrary> library) {
_library = library;
_debug_voxel_face = false;
size = (float)1;
vertexOffset = Vector3((float)0.5, (float)0.5, (float)0.5);
_voxel_scale = 1;
_lod_size = 1;
_surface_tool = memnew(SurfaceTool());
_surface_tool.instance();
}
VoxelMesher::VoxelMesher() {
_debug_voxel_face = false;
size = (float)1;
vertexOffset = Vector3((float)0.5, (float)0.5, (float)0.5);
_surface_tool = memnew(SurfaceTool());
_voxel_scale = 1;
_lod_size = 1;
_surface_tool.instance();
}
VoxelMesher::~VoxelMesher() {
@ -26,7 +25,7 @@ VoxelMesher::~VoxelMesher() {
_indices.clear();
_bones.clear();
memdelete(_surface_tool);
_surface_tool.unref();
if (_library.is_valid()) {
_library.unref();
@ -59,7 +58,9 @@ Ref<ArrayMesh> VoxelMesher::build_mesh() {
_surface_tool->add_index(_indices.get(i));
}
_surface_tool->generate_normals();
if (_normals.size() == 0) {
_surface_tool->generate_normals();
}
Ref<ArrayMesh> m = _surface_tool->commit();
@ -81,6 +82,20 @@ void VoxelMesher::add_buffer(Ref<VoxelBuffer> voxels) {
call("_add_buffer", voxels);
}
float VoxelMesher::get_voxel_scale() const {
return _voxel_scale;
}
void VoxelMesher::set_voxel_scale(const float voxel_scale) {
_voxel_scale = voxel_scale;
}
int VoxelMesher::get_lod_size() const {
return _lod_size;
}
void VoxelMesher::set_lod_size(const int lod_size) {
_lod_size = lod_size;
}
void VoxelMesher::create_trimesh_shape(Ref<ConcavePolygonShape> shape) const {
if (_vertices.size() == 0)
return;
@ -89,8 +104,6 @@ void VoxelMesher::create_trimesh_shape(Ref<ConcavePolygonShape> shape) const {
if (_indices.size() == 0) {
//face_points.resize(_vertices.size());
int len = (_vertices.size() / 4);
for (int i = 0; i < len; ++i) {
@ -310,6 +323,14 @@ void VoxelMesher::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_buffer", "buffer"), &VoxelMesher::add_buffer);
ClassDB::bind_method(D_METHOD("get_voxel_scale"), &VoxelMesher::get_voxel_scale);
ClassDB::bind_method(D_METHOD("set_voxel_scale", "value"), &VoxelMesher::set_voxel_scale);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "voxel_scale"), "set_voxel_scale", "get_voxel_scale");
ClassDB::bind_method(D_METHOD("get_lod_size"), &VoxelMesher::get_lod_size);
ClassDB::bind_method(D_METHOD("set_lod_size", "value"), &VoxelMesher::set_lod_size);
ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_size"), "set_lod_size", "get_lod_size");
ClassDB::bind_method(D_METHOD("get_library"), &VoxelMesher::get_library);
ClassDB::bind_method(D_METHOD("set_library", "value"), &VoxelMesher::set_library);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "library"), "set_library", "get_library");

View File

@ -36,6 +36,12 @@ public:
void add_buffer(Ref<VoxelBuffer> voxels);
float get_voxel_scale() const;
void set_voxel_scale(const float voxel_scale);
int get_lod_size() const;
void set_lod_size(const int lod_size);
void create_trimesh_shape(Ref<ConcavePolygonShape> shape) const;
void bake_lights(MeshInstance *node, Vector<Ref<VoxelLight> > &lights);
@ -87,11 +93,10 @@ protected:
Ref<VoxelmanLibrary> _library;
float size;
Vector3 vertexOffset;
bool _debug_voxel_face;
float _voxel_scale;
int _lod_size;
SurfaceTool *_surface_tool;
Ref<SurfaceTool> _surface_tool;
};
#endif

View File

@ -323,9 +323,9 @@ void VoxelBuffer::add_light(int local_x, int local_y, int local_z, int size, Col
int size_z = _size.z;
float sizef = static_cast<float>(size);
float rf = (color.r / sizef);
float gf = (color.g / sizef);
float bf = (color.b / sizef);
//float rf = (color.r / sizef);
//float gf = (color.g / sizef);
//float bf = (color.b / sizef);
for (int y = local_y - size; y <= local_y + size; ++y) {
if (y < 0 || y > size_y)
@ -339,11 +339,19 @@ void VoxelBuffer::add_light(int local_x, int local_y, int local_z, int size, Col
if (x < 0 || x > size_x)
continue;
float len = (Math::sqrt((real_t)x * x + y * y + z * z)) / sizef;
int lx = x - local_x;
int ly = y - local_y;
int lz = z - local_z;
int r = rf * len * 255.0;
int g = gf * len * 255.0;
int b = bf * len * 255.0;
float str = size - (((float)lx * lx + ly * ly + lz * lz));
str /= size;
if (str < 0)
continue;
int r = color.r * str * 255.0;
int g = color.g * str * 255.0;
int b = color.b * str * 255.0;
r += get_voxel(x, y, z, CHANNEL_LIGHT_COLOR_R);
g += get_voxel(x, y, z, CHANNEL_LIGHT_COLOR_G);

View File

@ -74,11 +74,26 @@ void VoxelChunk::set_library(Ref<VoxelmanLibrary> value) {
_library = value;
}
int VoxelChunk::get_lod_size() const {
return _lod_size;
}
void VoxelChunk::set_lod_size(const int lod_size) {
_lod_size = lod_size;
if (_mesher.is_valid()) {
_mesher->set_lod_size(_lod_size);
}
}
float VoxelChunk::get_voxel_scale() const {
return _voxel_scale;
}
void VoxelChunk::set_voxel_scale(float value) {
_voxel_scale = value;
if (_mesher.is_valid()) {
_mesher->set_voxel_scale(_voxel_scale);
}
}
Ref<VoxelMesher> VoxelChunk::get_mesher() const {
@ -131,6 +146,9 @@ void VoxelChunk::build() {
call("_create_mesher");
ERR_FAIL_COND(!_mesher.is_valid());
_mesher->set_lod_size(get_lod_size());
_mesher->set_voxel_scale(get_voxel_scale());
}
_mesher->set_library(_library);
@ -159,7 +177,7 @@ void VoxelChunk::build() {
}
void VoxelChunk::_create_mesher() {
_mesher = Ref<VoxelMesher>(memnew(VoxelMesher()));
_mesher = Ref<VoxelMesher>(memnew(VoxelMesherCubic()));
}
void VoxelChunk::finalize_mesh() {
@ -421,6 +439,10 @@ void VoxelChunk::_bind_methods() {
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_lod_size"), &VoxelChunk::get_lod_size);
ClassDB::bind_method(D_METHOD("set_lod_size", "value"), &VoxelChunk::set_lod_size);
ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_size"), "set_lod_size", "get_lod_size");
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");

View File

@ -14,6 +14,7 @@
#include "../data/voxel_light.h"
#include "../meshers/voxel_mesher.h"
#include "../meshers/cubic_mesher/voxel_mesher_cubic.h"
#include "../library/voxel_surface.h"
#include "../library/voxelman_library.h"
@ -51,6 +52,9 @@ public:
Ref<VoxelmanLibrary> get_library();
void set_library(Ref<VoxelmanLibrary> value);
int get_lod_size() const;
void set_lod_size(int lod_size);
float get_voxel_scale() const;
void set_voxel_scale(float value);
@ -97,7 +101,7 @@ public:
StaticBody *create_trimesh_collision_node();
VoxelChunk();
virtual ~VoxelChunk();
~VoxelChunk();
void draw_debug_voxels(int max, Color color = Color(1, 1, 1));
void draw_debug_voxel_lights();
@ -114,6 +118,8 @@ protected:
Ref<VoxelBuffer> _buffer;
Vector<Ref<VoxelLight> > _voxel_lights;
int _lod_size;
float _voxel_scale;
NodePath _library_path;