Entity &Application::MakeTestEntity(World &world) {
Entity &e = world.AddEntity();
+ e.Name("test");
e.Position({ 0.0f, 0.0f, 0.0f });
+ e.Bounds({ { -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f } });
+ e.WorldCollidable(true);
e.SetShape(world.BlockTypes()[1].shape, { 1.0f, 1.0f, 0.0f });
e.AngularVelocity(glm::quat(glm::vec3{ 0.00001f, 0.000006f, 0.000013f }));
return e;
void Interface::CheckAim() {
float dist;
- if (world.Intersection(aim, glm::mat4(1.0f), &aim_chunk, &aim_block, &dist, &aim_normal)) {
+ if (world.Intersection(aim, glm::mat4(1.0f), aim_chunk, aim_block, dist, aim_normal)) {
outline.Clear();
aim_chunk->Type(aim_chunk->BlockAt(aim_block)).FillOutlineModel(outline);
outline_transform = glm::scale(glm::vec3(1.0002f));
float &dist,
glm::vec3 &normal) const noexcept;
+ bool Intersection(
+ const AABB &box,
+ const glm::mat4 &Mbox,
+ const glm::mat4 &Mchunk) const noexcept;
+
void Position(const Pos &pos) noexcept { position = pos; }
const Pos &Position() const noexcept { return position; }
glm::mat4 Transform(const Pos &offset) const noexcept {
#include "Entity.hpp"
-#include "../model/geometry.hpp"
#include "../model/Shape.hpp"
#include <cmath>
Entity::Entity() noexcept
: shape(nullptr)
, model()
+, name("anonymous")
+, bounds()
, velocity(0, 0, 0)
, position(0, 0, 0)
, chunk(0, 0, 0)
, angular_velocity(1.0f, 0.0f, 0.0f, 0.0f)
-, rotation(1.0f) {
+, rotation(1.0f)
+, world_collision(false) {
}
#include "Block.hpp"
#include "Chunk.hpp"
+#include "../model/geometry.hpp"
#include "../model/Model.hpp"
+#include <string>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
namespace blank {
-class Ray;
class Shape;
class Entity {
void SetShape(const Shape *, const glm::vec3 &color);
void SetShapeless() noexcept;
+ const std::string &Name() const noexcept { return name; }
+ void Name(const std::string &n) { name = n; }
+
+ const AABB &Bounds() const noexcept { return bounds; }
+ void Bounds(const AABB &b) noexcept { bounds = b; }
+
+ bool WorldCollidable() const noexcept { return world_collision; }
+ void WorldCollidable(bool b) noexcept { world_collision = b; }
+
const glm::vec3 &Velocity() const noexcept { return velocity; }
void Velocity(const glm::vec3 &) noexcept;
const Shape *shape;
Model model;
+ std::string name;
+
+ AABB bounds;
+
glm::vec3 velocity;
Block::Pos position;
Chunk::Pos chunk;
glm::quat angular_velocity;
glm::mat4 rotation;
+ bool world_collision;
+
};
}
#include "../graphics/BlockLighting.hpp"
#include "../graphics/DirectionalLighting.hpp"
+#include <iostream>
#include <limits>
#include <glm/gtx/transform.hpp>
generate.Solids({ 1, 4, 7, 10 });
player = &AddEntity();
+ player->Name("player");
+ player->Bounds({ { -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f } });
+ player->WorldCollidable(true);
player->Position(config.spawn);
chunks.GenerateSurrounding(player->ChunkCoords());
}
bool World::Intersection(
- const Ray &ray,
- const glm::mat4 &M,
- Chunk **chunk,
- int *blkid,
- float *dist,
- glm::vec3 *normal) {
+ const Ray &ray,
+ const glm::mat4 &M,
+ Chunk *&chunk,
+ int &blkid,
+ float &dist,
+ glm::vec3 &normal
+) {
candidates.clear();
for (Chunk &cur_chunk : chunks.Loaded()) {
if (candidates.empty()) return false;
- Chunk *closest_chunk = nullptr;
- float closest_dist = std::numeric_limits<float>::infinity();
- int closest_blkid = -1;
- glm::vec3 closest_normal;
+ chunk = nullptr;
+ dist = std::numeric_limits<float>::infinity();
+ blkid = -1;
for (Candidate &cand : candidates) {
- if (cand.dist > closest_dist) continue;
+ if (cand.dist > dist) continue;
int cur_blkid;
float cur_dist;
glm::vec3 cur_normal;
if (cand.chunk->Intersection(ray, M * cand.chunk->Transform(player->ChunkCoords()), cur_blkid, cur_dist, cur_normal)) {
- if (cur_dist < closest_dist) {
- closest_chunk = cand.chunk;
- closest_blkid = cur_blkid;
- closest_dist = cur_dist;
- closest_normal = cur_normal;
+ if (cur_dist < dist) {
+ chunk = cand.chunk;
+ blkid = cur_blkid;
+ dist = cur_dist;
+ normal = cur_normal;
}
}
}
- if (chunk) {
- *chunk = closest_chunk;
- }
- if (blkid) {
- *blkid = closest_blkid;
- }
- if (dist) {
- *dist = closest_dist;
- }
- if (normal) {
- *normal = closest_normal;
+ return chunk;
+}
+
+bool World::Intersection(const Entity &e) {
+ AABB box = e.Bounds();
+ glm::mat4 M = e.Transform(player->ChunkCoords());
+ for (Chunk &cur_chunk : chunks.Loaded()) {
+ if (cur_chunk.Intersection(box, M, cur_chunk.Transform(player->ChunkCoords()))) {
+ return true;
+ }
}
- return closest_chunk;
+ return false;
}
for (Entity &entity : entities) {
entity.Update(dt);
}
+ for (Entity &entity : entities) {
+ if (entity.WorldCollidable() && Intersection(entity)) {
+ // entity collides with the world
+ std::cout << entity.Name() << " entity intersects world" << std::endl;
+ }
+ }
chunks.Rebase(player->ChunkCoords());
chunks.Update(dt);
}
public:
struct Config {
// initial player position
- glm::vec3 spawn = { 4.0f, 4.0f, 4.0f };
+ glm::vec3 spawn = { 0.0f, 0.0f, 0.0f };
// direction facing towards(!) the light
glm::vec3 light_direction = { -1.0f, -3.0f, -2.0f };
// fade out reaches 1/e (0.3679) at 1/fog_density,
bool Intersection(
const Ray &,
const glm::mat4 &M,
- Chunk **chunk = nullptr,
- int *blkid = nullptr,
- float *dist = nullptr,
- glm::vec3 *normal = nullptr);
+ Chunk *&chunk,
+ int &blkid,
+ float &dist,
+ glm::vec3 &normal);
+
+ bool Intersection(const Entity &e);
BlockTypeRegistry &BlockTypes() { return blockType; }
}
}
+bool Chunk::Intersection(
+ const AABB &box,
+ const glm::mat4 &Mbox,
+ const glm::mat4 &Mchunk
+) const noexcept {
+ if (!blank::Intersection(box, Mbox, Bounds(), Mchunk)) {
+ return false;
+ }
+ for (int idx = 0, z = 0; z < depth; ++z) {
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x, ++idx) {
+ const BlockType &type = Type(idx);
+ if (!type.visible) {
+ continue;
+ }
+ if (type.shape->Intersects(Mchunk * ToTransform(Pos(x, y, z), idx), box, Mbox)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
namespace {