summaryrefslogtreecommitdiff
path: root/scene/3d/voxelizer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/3d/voxelizer.cpp')
-rw-r--r--scene/3d/voxelizer.cpp90
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;