Tweaked calculation to better ensure no null normals will be produced

master
Marc Gilleron 2020-01-06 21:48:07 +00:00
parent b1c38a40c0
commit a06de157bf
2 changed files with 43 additions and 32 deletions

View File

@ -119,6 +119,16 @@ inline uint8_t get_border_mask(const Vector3i &pos, const Vector3i &min_pos, con
return mask;
}
inline Vector3 normalized_not_null(Vector3 n) {
real_t lengthsq = n.length_squared();
if (lengthsq == 0) {
return Vector3(0, 1, 0);
} else {
real_t length = Math::sqrt(lengthsq);
return Vector3(n.x / length, n.y / length, n.z / length);
}
}
} // namespace
VoxelMesherTransvoxel::VoxelMesherTransvoxel() {
@ -270,7 +280,7 @@ void VoxelMesherTransvoxel::build_internal(const VoxelBuffer &voxels, unsigned i
// TODO Also abstract positions with padding, it can get quite confusing when one is used but not the other...
FixedArray<int8_t, 8> cell_samples;
FixedArray<Vector3, 8> corner_normals;
FixedArray<Vector3, 8> corner_gradients;
FixedArray<Vector3i, 8> corner_positions;
// Iterate all cells with padding (expected to be neighbors)
@ -339,7 +349,8 @@ void VoxelMesherTransvoxel::build_internal(const VoxelBuffer &voxels, unsigned i
float py = tof(tos(get_voxel(voxels, p.x, p.y + 1, p.z, channel)));
float pz = tof(tos(get_voxel(voxels, p.x, p.y, p.z + 1, channel)));
corner_normals[i] = get_gradient_normal(nx, px, ny, py, nz, pz, cell_samples[i]);
//get_gradient_normal(nx, px, ny, py, nz, pz, cell_samples[i]);
corner_gradients[i] = Vector3(nx - px, ny - py, nz - pz);
}
// For cells occurring along the minimal boundaries of a block,
@ -435,7 +446,7 @@ void VoxelMesherTransvoxel::build_internal(const VoxelBuffer &voxels, unsigned i
// or by falling back on the generator that was used to produce the volume.
Vector3 primary = p0.to_vec3() * t0 + p1.to_vec3() * t1;
Vector3 normal = corner_normals[v0] * t0 + corner_normals[v1] * t1;
Vector3 normal = normalized_not_null(corner_gradients[v0] * t0 + corner_gradients[v1] * t1);
Vector3 secondary;
uint16_t border_mask = cell_border_mask;
@ -459,7 +470,7 @@ void VoxelMesherTransvoxel::build_internal(const VoxelBuffer &voxels, unsigned i
// This cell owns the vertex, so it should be created.
Vector3 primary = p1.to_vec3(); //p0.to_vec3() * t0 + p1.to_vec3() * t1;
Vector3 normal = corner_normals[v1]; // corner_normals[v0] * t0 + corner_normals[v1] * t1;
Vector3 normal = normalized_not_null(corner_gradients[v1]); // corner_normals[v0] * t0 + corner_normals[v1] * t1;
Vector3 secondary;
uint16_t border_mask = cell_border_mask;
@ -495,7 +506,7 @@ void VoxelMesherTransvoxel::build_internal(const VoxelBuffer &voxels, unsigned i
// TODO Interpolation is useless, just pick either
Vector3 primary = p0.to_vec3() * t0 + p1.to_vec3() * t1;
Vector3 normal = corner_normals[v0] * t0 + corner_normals[v1] * t1;
Vector3 normal = normalized_not_null(corner_gradients[v0] * t0 + corner_gradients[v1] * t1);
// TODO This bit of code is repeated several times, factor it?
Vector3 secondary;
@ -675,7 +686,7 @@ void VoxelMesherTransvoxel::build_transition(const VoxelBuffer &p_voxels, unsign
FixedArray<int8_t, 13> cell_samples;
FixedArray<Vector3i, 13> cell_positions;
FixedArray<Vector3, 13> cell_normals;
FixedArray<Vector3, 13> cell_gradients;
// Iterating in face space
for (int fy = min_fpos_y; fy < max_fpos_y; fy += 2) {
@ -735,12 +746,12 @@ void VoxelMesherTransvoxel::build_transition(const VoxelBuffer &p_voxels, unsign
float py = tof(tos(get_voxel(fvoxels, p.x, p.y + 1, p.z, channel)));
float pz = tof(tos(get_voxel(fvoxels, p.x, p.y, p.z + 1, channel)));
cell_normals[i] = get_gradient_normal(nx, px, ny, py, nz, pz, cell_samples[i]);
cell_gradients[i] = Vector3(nx - px, ny - py, nz - pz);
}
cell_normals[0x9] = cell_normals[0];
cell_normals[0xA] = cell_normals[2];
cell_normals[0xB] = cell_normals[6];
cell_normals[0xC] = cell_normals[8];
cell_gradients[0x9] = cell_gradients[0];
cell_gradients[0xA] = cell_gradients[2];
cell_gradients[0xB] = cell_gradients[6];
cell_gradients[0xC] = cell_gradients[8];
uint16_t case_code = sign(cell_samples[0]);
case_code |= (sign(cell_samples[1]) << 1);
@ -831,11 +842,11 @@ void VoxelMesherTransvoxel::build_transition(const VoxelBuffer &p_voxels, unsign
const Vector3 p0 = cell_positions[index_vertex_a].to_vec3();
const Vector3 p1 = cell_positions[index_vertex_b].to_vec3();
const Vector3 n0 = cell_normals[index_vertex_a];
const Vector3 n1 = cell_normals[index_vertex_b];
const Vector3 n0 = cell_gradients[index_vertex_a];
const Vector3 n1 = cell_gradients[index_vertex_b];
Vector3 primary = p0 * t0 + p1 * t1;
Vector3 normal = n0 * t0 + n1 * t1;
Vector3 normal = normalized_not_null(n0 * t0 + n1 * t1);
bool fullres_side = (index_vertex_a < 9 || index_vertex_b < 9);
uint16_t border_mask = cell_border_mask;
@ -887,7 +898,7 @@ void VoxelMesherTransvoxel::build_transition(const VoxelBuffer &p_voxels, unsign
// Going to create a new vertex
Vector3 primary = cell_positions[index_vertex].to_vec3();
Vector3 normal = cell_normals[index_vertex];
Vector3 normal = normalized_not_null(cell_gradients[index_vertex]);
bool fullres_side = (index_vertex < 9);
uint16_t border_mask = cell_border_mask;

View File

@ -127,27 +127,27 @@ inline int wrap(int x, int d) {
return ((x % d) + d) % d;
}
inline Vector3 get_gradient_normal(float left, float right, float bottom, float top, float back, float front, float middle) {
//inline Vector3 get_gradient_normal(float left, float right, float bottom, float top, float back, float front, float middle) {
float gx, gy, gz;
// float gx, gy, gz;
// Float equality, but based on the assumption these come from voxels. Voxels are quantized integer values.
if (left == right && bottom == top && back == front) {
// Sided gradient
// Won't be zero in cells that have triangles in them
gx = left - middle;
gy = bottom - middle;
gz = back - middle;
// // Float equality, but based on the assumption these come from voxels. Voxels are quantized integer values.
// if (left == right && bottom == top && back == front) {
// // Sided gradient
// // Won't be zero in cells that have triangles in them
// gx = left - middle;
// gy = bottom - middle;
// gz = back - middle;
} else {
// Symetric gradient
gx = left - right;
gy = bottom - top;
gz = back - front;
}
// } else {
// // Symetric gradient
// gx = left - right;
// gy = bottom - top;
// gz = back - front;
// }
return Vector3(gx, gy, gz).normalized();
}
// return Vector3(gx, gy, gz).normalized();
//}
#if TOOLS_ENABLED
namespace VoxelDebug {