, bounds()
, radius(0.0f)
, state()
+, model_transform(1.0f)
+, view_transform(1.0f)
+, speed(0.0f)
, heading(0.0f, 0.0f, -1.0f)
, max_vel(5.0f)
, max_force(25.0f)
Ray Entity::Aim(const ExactLocation::Coarse &chunk_offset) const noexcept {
glm::mat4 transform = ViewTransform(chunk_offset);
- return Ray{ glm::vec3(transform[3]), -glm::vec3(transform[2]) };
+ Ray ray{ glm::vec3(transform[3]), -glm::vec3(transform[2]) };
+ ray.Update();
+ return ray;
}
void Entity::Update(World &world, float dt) {
const ExactLocation::Coarse &reference,
WorldCollision &coll
) {
+ // only consider chunks of the index closest to reference
+ // this makes the ray not be infinite anymore (which means it's
+ // actually a line segment), but oh well
+ ChunkIndex *index = chunks.ClosestIndex(reference);
+ if (!index) {
+ return false;
+ }
+
candidates.clear();
- for (Chunk &cur_chunk : chunks) {
- float cur_dist;
- if (cur_chunk.Intersection(ray, reference, cur_dist)) {
- candidates.push_back({ &cur_chunk, cur_dist });
+ // maybe worht to try:
+ // change this so the test starts at the chunk of the ray's
+ // origin and "walks" forward until it hits (actually casting
+ // the ray, so to say). if this performs well (at least, better
+ // than now), this could also qualify for the chunk test itself
+ // see Bresenham's line algo or something similar
+
+ ExactLocation ray_loc(reference, ray.orig);
+ ray_loc.Correct();
+
+ ExactLocation::Coarse begin(index->CoordsBegin());
+ ExactLocation::Coarse end(index->CoordsEnd());
+
+ // ignore chunks that are bind the ray's origin
+ for (int i = 0; i < 3; ++i) {
+ if (ray.dir[i] >= 0.0f) {
+ begin[i] = ray_loc.chunk[i];
+ }
+ if (ray.dir[i] <= 0.0f) {
+ end[i] = ray_loc.chunk[i] + 1;
+ }
+ }
+
+ for (ExactLocation::Coarse pos(begin); pos.z < end.z; ++pos.z) {
+ for (pos.y = begin.y; pos.y < end.y; ++pos.y) {
+ for (pos.x = begin.x; pos.x < end.x; ++pos.x) {
+ Chunk *cur_chunk = index->Get(pos);
+ float cur_dist;
+ if (cur_chunk && cur_chunk->Intersection(ray, reference, cur_dist)) {
+ candidates.push_back({ cur_chunk, cur_dist });
+ }
+ }
}
}
const glm::ivec3 &reference,
std::vector<WorldCollision> &col
) {
+ // this only works if box's diameter is < than 16
+ ExactLocation::Coarse begin(reference - 1);
+ ExactLocation::Coarse end(reference + 2);
+
bool any = false;
- for (Chunk &cur_chunk : chunks) {
- if (manhattan_radius(cur_chunk.Position() - reference) > 1) {
- // chunk is not one of the 3x3x3 surrounding the entity
- // since there's no entity which can extent over 16 blocks, they can be skipped
- // TODO: change to indexed (like with entity)
- continue;
- }
- if (cur_chunk.Intersection(box, M, cur_chunk.Transform(reference), col)) {
- any = true;
+ for (ExactLocation::Coarse pos(begin); pos.z < end.z; ++pos.z) {
+ for (pos.y = begin.y; pos.y < end.y; ++pos.y) {
+ for (pos.x = begin.x; pos.x < end.x; ++pos.x) {
+ Chunk *chunk = chunks.Get(pos);
+ if (chunk && chunk->Intersection(box, M, chunk->Transform(reference), col)) {
+ any = true;
+ }
+ }
}
}
return any;
PrimitiveMesh debug_mesh;
PlainColor &prog = viewport.WorldColorProgram();
for (const Entity &entity : entities) {
- debug_buf.OutlineBox(entity.Bounds(), glm::vec4(1.0f, 0.0f, 0.0f, 1.0f));
+ debug_buf.OutlineBox(entity.Bounds(), glm::tvec4<unsigned char>(255, 0, 0, 255));
debug_mesh.Update(debug_buf);
prog.SetM(entity.Transform(players.front().GetEntity().ChunkCoords()));
debug_mesh.DrawLines();