diff options
Diffstat (limited to 'scene/3d/voxelizer.cpp')
-rw-r--r-- | scene/3d/voxelizer.cpp | 90 |
1 files changed, 33 insertions, 57 deletions
diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index f9c3810843..9fc3feb49a 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -36,7 +36,6 @@ #include <stdlib.h> static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3 *p_vtx, const Vector2 *p_uv, const Vector3 *p_normal, Vector2 &r_uv, Vector3 &r_normal) { - if (p_pos.distance_squared_to(p_vtx[0]) < CMP_EPSILON2) { r_uv = p_uv[0]; r_normal = p_normal[0]; @@ -77,7 +76,6 @@ static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3 } void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector3 *p_normal, const Vector2 *p_uv, const MaterialCache &p_material, const AABB &p_aabb) { - if (p_level == cell_subdiv) { //plot the face by guessing its albedo and emission value @@ -89,7 +87,6 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co Vector3 normal = plane.normal; for (int i = 0; i < 3; i++) { - Vector3 axis; axis[i] = 1.0; float dot = ABS(normal.dot(axis)); @@ -117,11 +114,9 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co //map to a grid average in the best axis for this face for (int i = 0; i < color_scan_cell_width; i++) { - Vector3 ofs_i = float(i) * t1; for (int j = 0; j < color_scan_cell_width; j++) { - Vector3 ofs_j = float(j) * t2; Vector3 from = p_aabb.position + ofs_i + ofs_j; @@ -147,7 +142,6 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co if (ABS(plane.distance_to(ray_from)) < ABS(plane.distance_to(ray_to))) { intersection = plane.project(ray_from); } else { - intersection = plane.project(ray_to); } } @@ -157,8 +151,9 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co Vector2 uv; Vector3 lnormal; get_uv_and_normal(intersection, p_vtx, p_uv, p_normal, uv, lnormal); - if (lnormal == Vector3()) //just in case normal as nor provided + if (lnormal == Vector3()) { //just in case normal as nor provided lnormal = normal; + } int uv_x = CLAMP(int(Math::fposmod(uv.x, 1.0f) * bake_texture_size), 0, bake_texture_size - 1); int uv_y = CLAMP(int(Math::fposmod(uv.y, 1.0f) * bake_texture_size), 0, bake_texture_size - 1); @@ -188,8 +183,9 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co Vector3 lnormal; Vector2 uv; get_uv_and_normal(inters, p_vtx, p_uv, p_normal, uv, normal); - if (lnormal == Vector3()) //just in case normal as nor provided + if (lnormal == Vector3()) { //just in case normal as nor provided lnormal = normal; + } int uv_x = CLAMP(Math::fposmod(uv.x, 1.0f) * bake_texture_size, 0, bake_texture_size - 1); int uv_y = CLAMP(Math::fposmod(uv.y, 1.0f) * bake_texture_size, 0, bake_texture_size - 1); @@ -210,7 +206,6 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co normal_accum = lnormal * alpha; } else { - float accdiv = 1.0 / (color_scan_cell_width * color_scan_cell_width); alpha *= accdiv; @@ -243,7 +238,6 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co int half = (1 << cell_subdiv) >> (p_level + 1); for (int i = 0; i < 8; i++) { - AABB aabb = p_aabb; aabb.size *= 0.5; @@ -264,8 +258,9 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co nz += half; } //make sure to not plot beyond limits - if (nx < 0 || nx >= axis_cell_size[0] || ny < 0 || ny >= axis_cell_size[1] || nz < 0 || nz >= axis_cell_size[2]) + if (nx < 0 || nx >= axis_cell_size[0] || ny < 0 || ny >= axis_cell_size[1] || nz < 0 || nz >= axis_cell_size[2]) { continue; + } { AABB test_aabb = aabb; @@ -297,11 +292,9 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co } Vector<Color> Voxelizer::_get_bake_texture(Ref<Image> p_image, const Color &p_color_mul, const Color &p_color_add) { - Vector<Color> ret; if (p_image.is_null() || p_image->empty()) { - ret.resize(bake_texture_size * bake_texture_size); for (int i = 0; i < bake_texture_size * bake_texture_size; i++) { ret.write[i] = p_color_add; @@ -335,7 +328,6 @@ Vector<Color> Voxelizer::_get_bake_texture(Ref<Image> p_image, const Color &p_co } Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material) { - //this way of obtaining materials is inaccurate and also does not support some compressed formats very well Ref<StandardMaterial3D> mat = p_material; @@ -348,12 +340,10 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material MaterialCache mc; if (mat.is_valid()) { - Ref<Texture2D> albedo_tex = mat->get_texture(StandardMaterial3D::TEXTURE_ALBEDO); Ref<Image> img_albedo; if (albedo_tex.is_valid()) { - img_albedo = albedo_tex->get_data(); mc.albedo = _get_bake_texture(img_albedo, mat->get_albedo(), Color(0, 0, 0)); // albedo texture, color is multiplicative } else { @@ -368,7 +358,6 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material Ref<Image> img_emission; if (emission_tex.is_valid()) { - img_emission = emission_tex->get_data(); } @@ -390,11 +379,10 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material } void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material>> &p_materials, const Ref<Material> &p_override_material) { - for (int i = 0; i < p_mesh->get_surface_count(); i++) { - - if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) + if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { continue; //only triangles + } Ref<Material> src_material; @@ -426,12 +414,10 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vec } if (index.size()) { - int facecount = index.size() / 3; const int *ir = index.ptr(); for (int j = 0; j < facecount; j++) { - Vector3 vtxs[3]; Vector2 uvs[3]; Vector3 normal[3]; @@ -453,18 +439,17 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vec } //test against original bounds - if (!Geometry::triangle_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) + if (!Geometry::triangle_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) { continue; + } //plot _plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds); } } else { - int facecount = vertices.size() / 3; for (int j = 0; j < facecount; j++) { - Vector3 vtxs[3]; Vector2 uvs[3]; Vector3 normal[3]; @@ -486,8 +471,9 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vec } //test against original bounds - if (!Geometry::triangle_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) + if (!Geometry::triangle_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) { continue; + } //plot face _plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds); } @@ -498,7 +484,6 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vec } void Voxelizer::_sort() { - // cells need to be sorted by level and coordinates // it is important that level has more priority (for compute), and that Z has the least, // given it may aid older implementations plot using GPU @@ -507,7 +492,6 @@ void Voxelizer::_sort() { uint32_t cell_count = bake_cells.size(); sorted_cells.resize(cell_count); { - CellSort *sort_cellsp = sorted_cells.ptrw(); const Cell *bake_cellsp = bake_cells.ptr(); @@ -540,7 +524,6 @@ void Voxelizer::_sort() { } { - const CellSort *sort_cellsp = sorted_cells.ptr(); const Cell *bake_cellsp = bake_cells.ptr(); const uint32_t *reverse_mapp = reverse_map.ptr(); @@ -563,9 +546,7 @@ void Voxelizer::_sort() { } void Voxelizer::_fixup_plot(int p_idx, int p_level) { - if (p_level == cell_subdiv) { - leaf_voxel_count++; float alpha = bake_cells[p_idx].alpha; @@ -604,7 +585,6 @@ void Voxelizer::_fixup_plot(int p_idx, int p_level) { }*/ } else { - //go down bake_cells.write[p_idx].emission[0] = 0; @@ -621,11 +601,11 @@ void Voxelizer::_fixup_plot(int p_idx, int p_level) { int children_found = 0; for (int i = 0; i < 8; i++) { - uint32_t child = bake_cells[p_idx].children[i]; - if (child == CHILD_EMPTY) + if (child == CHILD_EMPTY) { continue; + } _fixup_plot(child, p_level + 1); alpha_average += bake_cells[child].alpha; @@ -638,7 +618,6 @@ void Voxelizer::_fixup_plot(int p_idx, int p_level) { } void Voxelizer::begin_bake(int p_subdiv, const AABB &p_bounds) { - sorted = false; original_bounds = p_bounds; cell_subdiv = p_subdiv; @@ -653,9 +632,9 @@ void Voxelizer::begin_bake(int p_subdiv, const AABB &p_bounds) { leaf_voxel_count = 0; for (int i = 0; i < 3; i++) { - - if (i == longest_axis) + if (i == longest_axis) { continue; + } axis_cell_size[i] = axis_cell_size[longest_axis]; float axis_size = po2_bounds.size[longest_axis]; @@ -693,9 +672,11 @@ void Voxelizer::end_bake() { int Voxelizer::get_gi_probe_octree_depth() const { return cell_subdiv; } + Vector3i Voxelizer::get_giprobe_octree_size() const { return Vector3i(axis_cell_size[0], axis_cell_size[1], axis_cell_size[2]); } + int Voxelizer::get_giprobe_cell_count() const { return bake_cells.size(); } @@ -711,7 +692,6 @@ Vector<uint8_t> Voxelizer::get_giprobe_octree_cells() const { uint32_t cell_count = bake_cells.size(); for (uint32_t i = 0; i < cell_count; i++) { - for (uint32_t j = 0; j < 8; j++) { children_cells[i * 8 + j] = cells[i].children[j]; } @@ -720,6 +700,7 @@ Vector<uint8_t> Voxelizer::get_giprobe_octree_cells() const { return data; } + Vector<uint8_t> Voxelizer::get_giprobe_data_cells() const { Vector<uint8_t> data; data.resize((4 * 4) * bake_cells.size()); //8 uint32t values @@ -731,7 +712,6 @@ Vector<uint8_t> Voxelizer::get_giprobe_data_cells() const { uint32_t cell_count = bake_cells.size(); for (uint32_t i = 0; i < cell_count; i++) { - { //position uint32_t x = cells[i].x; @@ -803,7 +783,6 @@ Vector<int> Voxelizer::get_giprobe_level_cell_count() const { /* dt of 1d function using squared distance */ static void edt(float *f, int stride, int n) { - float *d = (float *)alloca(sizeof(float) * n + sizeof(int) * n + sizeof(float) * (n + 1)); int *v = (int *)&(d[n]); float *z = (float *)&v[n]; @@ -827,8 +806,9 @@ static void edt(float *f, int stride, int n) { k = 0; for (int q = 0; q <= n - 1; q++) { - while (z[k + 1] < q) + while (z[k + 1] < q) { k++; + } d[q] = square(q - v[k]) + f[v[k] * stride]; } @@ -840,7 +820,6 @@ static void edt(float *f, int stride, int n) { #undef square Vector<uint8_t> Voxelizer::get_sdf_3d_image() const { - Vector3i octree_size = get_giprobe_octree_size(); uint32_t float_count = octree_size.x * octree_size.y * octree_size.z; @@ -858,7 +837,6 @@ Vector<uint8_t> Voxelizer::get_sdf_3d_image() const { uint32_t cell_count = bake_cells.size(); for (uint32_t i = 0; i < cell_count; i++) { - if (cells[i].level < (cell_subdiv - 1)) { continue; //do not care about this level } @@ -912,9 +890,7 @@ Vector<uint8_t> Voxelizer::get_sdf_3d_image() const { #undef INF void Voxelizer::_debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx) { - if (p_level == cell_subdiv - 1) { - Vector3 center = p_aabb.position + p_aabb.size * 0.5; Transform xform; xform.origin = center; @@ -928,23 +904,25 @@ void Voxelizer::_debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<Mult idx++; } else { - for (int i = 0; i < 8; i++) { - uint32_t child = bake_cells[p_idx].children[i]; - if (child == CHILD_EMPTY || child >= (uint32_t)max_original_cells) + if (child == CHILD_EMPTY || child >= (uint32_t)max_original_cells) { continue; + } AABB aabb = p_aabb; aabb.size *= 0.5; - if (i & 1) + if (i & 1) { aabb.position.x += aabb.size.x; - if (i & 2) + } + if (i & 2) { aabb.position.y += aabb.size.y; - if (i & 4) + } + if (i & 4) { aabb.position.z += aabb.size.z; + } _debug_mesh(bake_cells[p_idx].children[i], p_level + 1, aabb, p_multimesh, idx); } @@ -952,7 +930,6 @@ void Voxelizer::_debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<Mult } Ref<MultiMesh> Voxelizer::create_debug_multimesh() { - Ref<MultiMesh> mm; mm.instance(); @@ -975,22 +952,20 @@ Ref<MultiMesh> Voxelizer::create_debug_multimesh() { colors.push_back(Color(1, 1, 1, 1)); for (int i = 0; i < 6; i++) { - Vector3 face_points[4]; for (int j = 0; j < 4; j++) { - float v[3]; v[0] = 1.0; v[1] = 1 - 2 * ((j >> 1) & 1); v[2] = v[1] * (1 - 2 * (j & 1)); for (int k = 0; k < 3; k++) { - - if (i < 3) + if (i < 3) { face_points[j][(i + k) % 3] = v[k]; - else + } else { face_points[3 - j][(i + k) % 3] = -v[k]; + } } } @@ -1031,6 +1006,7 @@ Ref<MultiMesh> Voxelizer::create_debug_multimesh() { Transform Voxelizer::get_to_cell_space_xform() const { return to_cell_space; } + Voxelizer::Voxelizer() { sorted = false; color_scan_cell_width = 4; |