diff options
author | Paweł Redman <pawel.redman@gmail.com> | 2018-04-12 14:00:53 +0200 |
---|---|---|
committer | Paweł Redman <pawel.redman@gmail.com> | 2018-04-12 14:00:53 +0200 |
commit | a5b20dcd57ddf7bdac8d9bce1aabf934badd837d (patch) | |
tree | e05853e98e2481f5ac939919b58227190e1a07d0 /src | |
parent | 30c5c419aedd0e5aae92be6e0eee83f0b6690c6e (diff) |
Ray tracing against cmodels (WIP).
Diffstat (limited to 'src')
-rw-r--r-- | src/common.hpp | 3 | ||||
-rw-r--r-- | src/game/game.cpp | 25 | ||||
-rw-r--r-- | src/game/interface.cpp | 6 | ||||
-rw-r--r-- | src/math.hpp | 9 | ||||
-rw-r--r-- | src/world.cpp | 76 |
5 files changed, 113 insertions, 6 deletions
diff --git a/src/common.hpp b/src/common.hpp index c2c8414..ef96cc6 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -122,6 +122,9 @@ namespace world { float frac; } trace_t; + // for testing + trace_t ray_v_rect(v2f_t start, v2f_t end, rectf_t rect); + void register_tile(uint8_t type, cflags_t cflags); class world_t { diff --git a/src/game/game.cpp b/src/game/game.cpp index 8deadd6..4b9a9a3 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -251,6 +251,31 @@ void state_t::command(v2f_t x, int number) if (!selected_units.size()) return; + // debugging + if (number == 666) { + for (size_t i = 0; i < 100; i++) { + v2f_t rad; + world::trace_t best; + + best.hit = false; + best.frac = 2.0f; + + rad = v2f_t::rad(i / 99.0f * 2.0f * M_PI); + + for (unit_t *unit : selected_units) { + world::trace_t trace; + + trace = world::ray_v_rect(x, x + rad * 10, unit->cmodel.bounds); + if (trace.frac < best.frac) + best = trace; + } + + debug_render->render_line(x, best.end, (best.hit ? sf::Color::Yellow : sf::Color::White)); + } + + return; + } + snap[0] = std::round(x[0] - 0.5f) + 0.5f; snap[1] = std::round(x[1] - 0.5f) + 0.5f; diff --git a/src/game/interface.cpp b/src/game/interface.cpp index b187d42..7615acf 100644 --- a/src/game/interface.cpp +++ b/src/game/interface.cpp @@ -334,6 +334,12 @@ void state_t::render_to(render::state_t *render) std::stringstream ss; double fps; + // debug + { + auto wmouse = window->mapPixelToCoords(sf::Mouse::getPosition(*window)); + game->command(wmouse, 666); + } + if (select.selecting) { sf::Color color; diff --git a/src/math.hpp b/src/math.hpp index 7cbd829..97e3b6b 100644 --- a/src/math.hpp +++ b/src/math.hpp @@ -379,6 +379,15 @@ public: return v[0] / 2 + v[1] / 2; } + bool contains(vec_t<T, N> &u) const + { + for (size_t i = 0; i < N; i++) + if (u[i] < v[0][i] || u[i] > v[1][i]) + return false; + + return true; + } + friend bool operator&&(const rect_t<T, N> &a, const rect_t<T, N> &b) { for (size_t i = 0; i < N; i++) diff --git a/src/world.cpp b/src/world.cpp index 640ac6e..b03105e 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -319,6 +319,76 @@ static inline size_t quadrant(v2f_t dx) } } +trace_t ray_v_rect(v2f_t start, v2f_t end, rectf_t rect) +{ + v2f_t dx, tdelta, dims; + size_t quad; + trace_t res; + + if (rect.contains(start)) { + res.hit = true; + res.end = start; + res.frac = 0.0f; + return res; + } + + dx = end - start; + + quad = quadrant(dx); + if (quad == 4) + goto out_no_hit; + + // If necessary, transform (with simple X/Y reflections) the coordinate + // system, so that dx lies in the first quadrant. + + start ^= transforms[quad]; + dx ^= transforms[quad]; + end ^= transforms[quad]; + + dims = rect.dims(); + rect.v[0] ^= transforms[quad]; + rect.v[1] ^= transforms[quad]; + + // Find the closest point on the rectangle and transform the coordinates + // so that it lies at (0, 0). + + tdelta[0] = std::min(rect.v[0][0], rect.v[1][0]); + tdelta[1] = std::min(rect.v[0][1], rect.v[1][1]); + start -= tdelta; + + // Project onto x = 0. + res.frac = -start[0] / dx[0]; + if (res.frac >= 0.0f && res.frac <= 1.0f) { + float y; + + y = start[1] + res.frac * dx[1]; + if (y >= 0 && y <= dims[1]) { + res.hit = true; + res.end = (v2f_t(0, y) + tdelta) ^ transforms[quad]; + return res; + } + } + + // Project onto y = 0. + res.frac = -start[1] / dx[1]; + if (res.frac >= 0.0f && res.frac <= 1.0f) { + float x; + + x = start[0] + res.frac * dx[0]; + if (x >= 0 && x <= dims[0]) { + res.hit = true; + res.end = (v2f_t(x, 0) + tdelta) ^ transforms[quad]; + return res; + } + } + +out_no_hit: + res.hit = false; + res.end = end ^ transforms[quad]; + res.frac = 1.0f; + return res; +} + trace_t world_t::trace(v2f_t start, v2f_t end, cflags_t cflags) { v2f_t x, dx; @@ -382,12 +452,6 @@ trace_t world_t::trace(v2f_t start, v2f_t end, cflags_t cflags) } } -trace_t trace_cmodel(v2f_t start, v2f_t end, const cmodel_t *cmodel) -{ - // TODO - return {0}; -} - entity_t::entity_t(int type_) { type = type_; |