private bool HandleCollision(SweepCallback callback) { // set up for callback cumulative_t += t; float dir = step[axis]; // vector moved so far, and left to move float done = t / max_t; for (int i = 0; i < 3; i++) { float dv = vec[i] * done; bas[i] += dv; max[i] += dv; left[i] = vec[i] - dv; } // set leading edge of stepped axis exactly to voxel boundary // else we'll sometimes rounding error beyond it if (dir > 0) { max[axis] = (float)Math.Round(max[axis]); } else { bas[axis] = (float)Math.Round(bas[axis]); } // call back to let client update the "left to go" vector Vector3 leftVec = new Vector3(left[0], left[1], left[2]); bool res = callback(cumulative_t, axis, dir, ref leftVec); leftVec.CopyTo(left); // bail out out on truthy response if (res) { return(true); } // init for new sweep along vec for (int i = 0; i < 3; i++) { vec[i] = left[i]; } Initialize(); if (max_t == 0) { return(true); // no vector left } return(false); }
// Return total distance moved // (not necessarily magnitude of [end]-[start]) public float Execute(ref BoundingBox boundingBox, Vector3 direction, SweepCallback callback, bool noTranslate) { Vector3 maximum = boundingBox.Maximum(); direction.CopyTo(sdir); direction.CopyTo(vec); maximum.CopyTo(max); maximum.CopyTo(bmax); boundingBox.Position.CopyTo(bas); boundingBox.Position.CopyTo(bbas); cumulative_t = 0; axis = 0; // init for the current sweep vector and take first step Initialize(); if (max_t == 0) { return(0); } axis = StepForward(); float dist = 0; bool done = false; // loop along raycast vector while (t <= max_t) { // sweeps over leading face of AABB if (CheckCollision(axis)) { // calls the callback and decides whether to continue done = HandleCollision(callback); if (done) { dist = cumulative_t; break; } } axis = StepForward(); } if (!done) { cumulative_t += max_t; for (int i = 0; i < 3; i++) { bas[i] += vec[i]; max[i] += vec[i]; } dist = cumulative_t; } if (!noTranslate) { for (int i = 0; i < 3; i++) { result[i] = (sdir[i] > 0) ? (max[i] - bmax[i]) : (bas[i] - bbas[i]); } boundingBox = boundingBox.Translated(new Vector3( result[0], result[1], result[2])); } return(dist); }