-void World::Resolve(const Entity &e, std::vector<WorldCollision> &col) {
- std::cout << e.Name() << " entity intersects world at " << col.size() << " blocks" << std::endl;
-}
-
-
-void World::Render(BlockLighting &chunk_prog, DirectionalLighting &entity_prog) {
- chunk_prog.Activate();
- chunk_prog.SetFogDensity(fog_density);
- chunk_prog.SetView(glm::inverse(player->Transform(player->ChunkCoords())));
-
- for (Chunk &chunk : chunks.Loaded()) {
- glm::mat4 m(chunk.Transform(player->ChunkCoords()));
- chunk_prog.SetM(m);
- glm::mat4 mvp(chunk_prog.GetVP() * m);
- if (!CullTest(Chunk::Bounds(), mvp)) {
- chunk.Draw();
+void World::Resolve(Entity &e, std::vector<WorldCollision> &col) {
+ // determine displacement for each cardinal axis and move entity accordingly
+ glm::vec3 min_disp(0.0f);
+ glm::vec3 max_disp(0.0f);
+ for (const WorldCollision &c : col) {
+ if (!c.Blocks()) continue;
+ glm::vec3 local_disp(c.normal * c.depth);
+ // swap if neccessary (normal may point away from the entity)
+ if (dot(c.normal, e.Position() - c.BlockCoords()) < 0) {
+ local_disp *= -1;
+ }
+ min_disp = min(min_disp, local_disp);
+ max_disp = max(max_disp, local_disp);
+ }
+ // for each axis
+ // if only one direction is set, use that as the final
+ // if both directions are set, use average
+ glm::vec3 final_disp(0.0f);
+ for (int axis = 0; axis < 3; ++axis) {
+ if (std::abs(min_disp[axis]) > std::numeric_limits<float>::epsilon()) {
+ if (std::abs(max_disp[axis]) > std::numeric_limits<float>::epsilon()) {
+ final_disp[axis] = (min_disp[axis] + max_disp[axis]) * 0.5f;
+ } else {
+ final_disp[axis] = min_disp[axis];
+ }
+ } else if (std::abs(max_disp[axis]) > std::numeric_limits<float>::epsilon()) {
+ final_disp[axis] = max_disp[axis];