glm::vec3 norm_diff(diff / dist);
bool line_of_sight = true;
- // FIXME: this only works if target is in the reference chunk (which is true for the player)
Ray aim{Target().Position() - diff, norm_diff};
WorldCollision coll;
- if (world.Intersection(aim, glm::mat4(1.0f), coll)) {
+ if (world.Intersection(aim, glm::mat4(1.0f), Target().ChunkCoords(), coll)) {
line_of_sight = coll.depth > dist;
}
}
void Interface::CheckAim() {
- if (!world.Intersection(aim, glm::mat4(1.0f), aim_world)) {
+ if (!world.Intersection(aim, glm::mat4(1.0f), ctrl.Controlled().ChunkCoords(), aim_world)) {
aim_world = WorldCollision();
}
- if (!world.Intersection(aim, glm::mat4(1.0f), aim_entity)) {
+ if (!world.Intersection(aim, glm::mat4(1.0f), ctrl.Controlled(), aim_entity)) {
aim_entity = EntityCollision();
}
if (aim_world && aim_entity) {
bool World::Intersection(
const Ray &ray,
const glm::mat4 &M,
+ const Chunk::Pos &reference,
WorldCollision &coll
) {
candidates.clear();
for (Chunk &cur_chunk : chunks.Loaded()) {
float cur_dist;
- if (cur_chunk.Intersection(ray, M * cur_chunk.Transform(player->ChunkCoords()), cur_dist)) {
+ if (cur_chunk.Intersection(ray, M * cur_chunk.Transform(reference), cur_dist)) {
candidates.push_back({ &cur_chunk, cur_dist });
}
}
for (Candidate &cand : candidates) {
if (cand.dist > coll.depth) continue;
WorldCollision cur_coll;
- if (cand.chunk->Intersection(ray, M * cand.chunk->Transform(player->ChunkCoords()), cur_coll)) {
+ if (cand.chunk->Intersection(ray, M * cand.chunk->Transform(reference), cur_coll)) {
if (cur_coll.depth < coll.depth) {
coll = cur_coll;
}
bool World::Intersection(
const Ray &ray,
const glm::mat4 &M,
+ const Entity &reference,
EntityCollision &coll
) {
coll.entity = nullptr;
coll.depth = std::numeric_limits<float>::infinity();
for (Entity &cur_entity : entities) {
- // TODO: better check for skipping self (because the check might not be for the player)
- if (&cur_entity == player) {
+ if (&cur_entity == &reference) {
continue;
}
float cur_dist;
glm::vec3 cur_normal;
- if (blank::Intersection(ray, cur_entity.Bounds(), M * cur_entity.Transform(player->ChunkCoords()), &cur_dist, &cur_normal)) {
+ if (blank::Intersection(ray, cur_entity.Bounds(), M * cur_entity.Transform(reference.ChunkCoords()), &cur_dist, &cur_normal)) {
// TODO: fine grained check goes here? maybe?
if (cur_dist < coll.depth) {
coll.entity = &cur_entity;
bool World::Intersection(const Entity &e, std::vector<WorldCollision> &col) {
AABB box = e.Bounds();
- glm::mat4 M = e.Transform(player->ChunkCoords());
+ Chunk::Pos reference = e.ChunkCoords();
+ glm::mat4 M = e.Transform(reference);
bool any = false;
for (Chunk &cur_chunk : chunks.Loaded()) {
if (manhattan_radius(cur_chunk.Position() - e.ChunkCoords()) > 1) {
// since there's no entity which can extent over 16 blocks, they can be skipped
continue;
}
- if (cur_chunk.Intersection(box, M, cur_chunk.Transform(player->ChunkCoords()), col)) {
+ if (cur_chunk.Intersection(box, M, cur_chunk.Transform(reference), col)) {
any = true;
}
}
return chunks.ForceLoad(player->ChunkCoords());
}
-Chunk &World::Next(const Chunk &to, const glm::ivec3 &dir) {
- const Chunk::Pos tgt_pos = to.Position() + dir;
- return chunks.ForceLoad(tgt_pos);
-}
-
namespace {
/// check if this ray hits a block
/// depth in the collision is the distance between the ray's
/// origin and the intersection point
+ /// M is the global transform for given reference chunk
bool Intersection(
const Ray &,
const glm::mat4 &M,
+ const Chunk::Pos &reference,
WorldCollision &);
/// check if this ray hits an entity
+ /// intersections with the reference are not tested
+ /// M is the global transform for the chunk of given reference entity
bool Intersection(
const Ray &,
const glm::mat4 &M,
+ const Entity &reference,
EntityCollision &);
/// check if given entity intersects with the world
Entity &AddEntity() { entities.emplace_back(); return entities.back(); }
Chunk &PlayerChunk();
- Chunk &Next(const Chunk &to, const glm::ivec3 &dir);
void Update(int dt);