summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2018-04-12 14:00:53 +0200
committerPaweł Redman <pawel.redman@gmail.com>2018-04-12 14:00:53 +0200
commita5b20dcd57ddf7bdac8d9bce1aabf934badd837d (patch)
treee05853e98e2481f5ac939919b58227190e1a07d0
parent30c5c419aedd0e5aae92be6e0eee83f0b6690c6e (diff)
Ray tracing against cmodels (WIP).
-rw-r--r--src/common.hpp3
-rw-r--r--src/game/game.cpp25
-rw-r--r--src/game/interface.cpp6
-rw-r--r--src/math.hpp9
-rw-r--r--src/world.cpp76
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_;