From 084c4d64da9592b19643e683c62aa04e7ba44479 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sun, 23 Jul 2017 04:37:25 +0100 Subject: [PATCH] Fix the assert triggering sometimes in the raytrace grid traversal. --- src/gamelib/grid_raytrace.cpp | 63 +++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/src/gamelib/grid_raytrace.cpp b/src/gamelib/grid_raytrace.cpp index 28aa2a0..1641c31 100644 --- a/src/gamelib/grid_raytrace.cpp +++ b/src/gamelib/grid_raytrace.cpp @@ -27,6 +27,7 @@ #include #include #include +#include namespace curry { #if !defined(BUILD_TESTING) @@ -104,46 +105,50 @@ namespace curry { const vec2f& u = parFrom; const vec2f v = parTo - parFrom; - //vec2f step(fsgn(v.x()), fsgn(v.y())); - - const auto delta = tile_size / v; - auto max = delta * (vec2f(1.0f) - frac(u / tile_size)); - - //vec2us start = pixel_to_world_tile(parWorld, u); - //const auto next_tile_boundary = (step + abs(step)) / 2.0f; - //const auto max = vec2f( - // segment_intersection( - // u, - // v, - // vec2f(static_cast(start.x() + next_tile_boundary.x()), 0.0f), - // vec2f(0.0f, static_cast(parWorld.world_size().y()) * tile_size.y()) - // ), - // segment_intersection( - // u, - // v, - // vec2f(0.0f, static_cast(start.y()) + next_tile_boundary.y()), - // vec2f(static_cast(parWorld.world_size().x()) * tile_size.x(), 0.0f) - // ) - //); - - //const auto delta = vec2f( - // std::isinf(max.x()) ? 0.0f : tile_size.x() / dot(vec2f(1.0f, 0.0f), v * inv_length(v)), - // 0.0f //std::isinf(max.y()) ? 0.0f : tile_size.y() / - //); + const auto delta = tile_size / abs(v); + const auto fr = frac(u / tile_size); + assert(fr.x() >= 0.0f and fr.x() < 1.0f); + assert(fr.y() >= 0.0f and fr.y() < 1.0f); //see: //http://stackoverflow.com/questions/12367071/how-do-i-initialize-the-t-variables-in-a-fast-voxel-traversal-algorithm-for-ray#12370474 - vec2i step(sgn(v.x()), sgn(v.y())); + const vec2i step(sgn(v.x()), sgn(v.y())); + vec2f max; + if (step.x() > 0) + max.x() = delta.x() * (1.0f - fr.x()); + else if (step.x() < 0) + max.x() = delta.x() * fr.x(); + else + max.x() = FLT_MAX; + if (step.y() > 0) + max.y() = delta.y() * (1.0f - fr.y()); + else if (step.y() < 0) + max.y() = delta.y() * fr.y(); + else + max.y() = FLT_MAX; + vec2us curr_tile = pixel_to_world_tile(parWorld, u); const vec2us last_tile = pixel_to_world_tile(parWorld, parTo); while (parFunc(curr_tile) and last_tile != curr_tile) { if (max.x() < max.y()) { - assert(std::max(static_cast(curr_tile.x() + step.x()), last_tile.x()) - std::min(static_cast(curr_tile.x() + step.x()), last_tile.x()) < std::max(curr_tile.x(), last_tile.x()) - std::min(curr_tile.x(), last_tile.x())); + assert(step.x()); + assert( + std::max(static_cast(curr_tile.x() + step.x()), last_tile.x()) - + std::min(static_cast(curr_tile.x() + step.x()), last_tile.x()) < + std::max(curr_tile.x(), last_tile.x()) - + std::min(curr_tile.x(), last_tile.x()) + ); max.x() += delta.x(); curr_tile.x() = static_cast(curr_tile.x() + step.x()); } else { - assert(std::max(static_cast(curr_tile.y() + step.y()), last_tile.y()) - std::min(static_cast(curr_tile.y() + step.y()), last_tile.y()) < std::max(curr_tile.y(), last_tile.y()) - std::min(curr_tile.y(), last_tile.y())); + assert(step.y()); + assert( + std::max(static_cast(curr_tile.y() + step.y()), last_tile.y()) - + std::min(static_cast(curr_tile.y() + step.y()), last_tile.y()) < + std::max(curr_tile.y(), last_tile.y()) - + std::min(curr_tile.y(), last_tile.y()) + ); max.y() += delta.y(); curr_tile.y() = static_cast(curr_tile.y() + step.y()); }