Fix inconsistent rounding in VoxelLineIterator::VoxelLineIterator (#14555)

floatToInt rounds 0.5 differently depending on sign.
This commit is contained in:
DS 2024-04-20 13:03:34 +02:00 committed by GitHub
parent d767ab0890
commit 5a07f5a652
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 24 additions and 25 deletions

@ -49,31 +49,29 @@ void TestVoxelAlgorithms::runTests(IGameDef *gamedef)
void TestVoxelAlgorithms::testVoxelLineIterator() void TestVoxelAlgorithms::testVoxelLineIterator()
{ {
// Test some lines // Test some lines
// Do not test lines that start or end on the border of std::vector<core::line3d<f32>> lines;
// two voxels as rounding errors can make the test fail! for (f32 x = -9.1f; x < 9.0f; x += 3.124f)
std::vector<core::line3d<f32> > lines; for (f32 y = -9.2f; y < 9.0f; y += 3.123f)
for (f32 x = -9.1; x < 9; x += 3.124) { for (f32 z = -9.3f; z < 9.0f; z += 3.122f) {
for (f32 y = -9.2; y < 9; y += 3.123) {
for (f32 z = -9.3; z < 9; z += 3.122) {
lines.emplace_back(-x, -y, -z, x, y, z); lines.emplace_back(-x, -y, -z, x, y, z);
} }
for (f32 x = -3.0f; x < 3.1f; x += 0.5f)
for (f32 y = -3.0f; y < 3.1f; y += 0.5f)
for (f32 z = -3.0f; z < 3.1f; z += 0.5f) {
lines.emplace_back(-x, -y, -z, x, y, z);
} }
} lines.emplace_back(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
lines.emplace_back(0, 0, 0, 0, 0, 0);
// Test every line // Test every line
std::vector<core::line3d<f32> >::iterator it = lines.begin(); for (auto l : lines) {
for (; it < lines.end(); it++) {
core::line3d<f32> l = *it;
// Initialize test // Initialize test
voxalgo::VoxelLineIterator iterator(l.start, l.getVector()); voxalgo::VoxelLineIterator iterator(l.start, l.getVector());
//Test the first voxel //Test the first voxel
v3s16 start_voxel = floatToInt(l.start, 1); v3s16 start_voxel = floatToInt(l.start, 1.0f);
UASSERT(iterator.m_current_node_pos == start_voxel); UASSERT(iterator.m_current_node_pos == start_voxel);
// Values for testing // Values for testing
v3s16 end_voxel = floatToInt(l.end, 1); v3s16 end_voxel = floatToInt(l.end, 1.0f);
v3s16 voxel_vector = end_voxel - start_voxel; v3s16 voxel_vector = end_voxel - start_voxel;
int nodecount = abs(voxel_vector.X) + abs(voxel_vector.Y) int nodecount = abs(voxel_vector.X) + abs(voxel_vector.Y)
+ abs(voxel_vector.Z); + abs(voxel_vector.Z);
@ -88,8 +86,9 @@ void TestVoxelAlgorithms::testVoxelLineIterator()
UASSERTEQ(f32, (new_voxel - old_voxel).getLengthSQ(), 1); UASSERTEQ(f32, (new_voxel - old_voxel).getLengthSQ(), 1);
// The line must intersect with the voxel // The line must intersect with the voxel
v3f voxel_center = intToFloat(iterator.m_current_node_pos, 1); v3f voxel_center = intToFloat(iterator.m_current_node_pos, 1);
aabb3f box(voxel_center - v3f(0.5, 0.5, 0.5), constexpr f32 eps = 1.0e-5f;
voxel_center + v3f(0.5, 0.5, 0.5)); aabb3f box(voxel_center - v3f(0.5f + eps),
voxel_center + v3f(0.5f + eps));
UASSERT(box.intersectsWithLine(l)); UASSERT(box.intersectsWithLine(l));
// Update old voxel // Update old voxel
old_voxel = new_voxel; old_voxel = new_voxel;

@ -1246,34 +1246,34 @@ VoxelLineIterator::VoxelLineIterator(const v3f &start_position, const v3f &line_
m_last_index = getIndex(floatToInt(start_position + line_vector, 1)); m_last_index = getIndex(floatToInt(start_position + line_vector, 1));
if (m_line_vector.X > 0) { if (m_line_vector.X > 0) {
m_next_intersection_multi.X = (floorf(m_start_position.X - 0.5) + 1.5 m_next_intersection_multi.X = (m_current_node_pos.X + 0.5f
- m_start_position.X) / m_line_vector.X; - m_start_position.X) / m_line_vector.X;
m_intersection_multi_inc.X = 1 / m_line_vector.X; m_intersection_multi_inc.X = 1 / m_line_vector.X;
} else if (m_line_vector.X < 0) { } else if (m_line_vector.X < 0) {
m_next_intersection_multi.X = (floorf(m_start_position.X - 0.5) m_next_intersection_multi.X = (m_current_node_pos.X - 0.5f
- m_start_position.X + 0.5) / m_line_vector.X; - m_start_position.X) / m_line_vector.X;
m_intersection_multi_inc.X = -1 / m_line_vector.X; m_intersection_multi_inc.X = -1 / m_line_vector.X;
m_step_directions.X = -1; m_step_directions.X = -1;
} }
if (m_line_vector.Y > 0) { if (m_line_vector.Y > 0) {
m_next_intersection_multi.Y = (floorf(m_start_position.Y - 0.5) + 1.5 m_next_intersection_multi.Y = (m_current_node_pos.Y + 0.5f
- m_start_position.Y) / m_line_vector.Y; - m_start_position.Y) / m_line_vector.Y;
m_intersection_multi_inc.Y = 1 / m_line_vector.Y; m_intersection_multi_inc.Y = 1 / m_line_vector.Y;
} else if (m_line_vector.Y < 0) { } else if (m_line_vector.Y < 0) {
m_next_intersection_multi.Y = (floorf(m_start_position.Y - 0.5) m_next_intersection_multi.Y = (m_current_node_pos.Y - 0.5f
- m_start_position.Y + 0.5) / m_line_vector.Y; - m_start_position.Y) / m_line_vector.Y;
m_intersection_multi_inc.Y = -1 / m_line_vector.Y; m_intersection_multi_inc.Y = -1 / m_line_vector.Y;
m_step_directions.Y = -1; m_step_directions.Y = -1;
} }
if (m_line_vector.Z > 0) { if (m_line_vector.Z > 0) {
m_next_intersection_multi.Z = (floorf(m_start_position.Z - 0.5) + 1.5 m_next_intersection_multi.Z = (m_current_node_pos.Z + 0.5f
- m_start_position.Z) / m_line_vector.Z; - m_start_position.Z) / m_line_vector.Z;
m_intersection_multi_inc.Z = 1 / m_line_vector.Z; m_intersection_multi_inc.Z = 1 / m_line_vector.Z;
} else if (m_line_vector.Z < 0) { } else if (m_line_vector.Z < 0) {
m_next_intersection_multi.Z = (floorf(m_start_position.Z - 0.5) m_next_intersection_multi.Z = (m_current_node_pos.Z - 0.5f
- m_start_position.Z + 0.5) / m_line_vector.Z; - m_start_position.Z) / m_line_vector.Z;
m_intersection_multi_inc.Z = -1 / m_line_vector.Z; m_intersection_multi_inc.Z = -1 / m_line_vector.Z;
m_step_directions.Z = -1; m_step_directions.Z = -1;
} }