Ray basic collision
This commit is contained in:
parent
2f3335fe88
commit
7a51061fce
4
TODO.md
4
TODO.md
|
@ -23,6 +23,8 @@
|
|||
- [ ] Inheritance
|
||||
- [ ] ECS
|
||||
- [ ] Relative to area
|
||||
- [ ] Player as entity
|
||||
- [ ] Entities block world changes
|
||||
- [x] Area
|
||||
- [x] Offset
|
||||
- [ ] Rotation
|
||||
|
@ -76,7 +78,7 @@
|
|||
- [ ] LOD
|
||||
- [x] Dual MC
|
||||
- [ ] Octree
|
||||
- [ ] Collision
|
||||
- [~] Collision
|
||||
- [ ] Dynamic index size
|
||||
- [x] Chunk size performance
|
||||
- [ ] Render with glBufferSubData
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include "../render/window.hpp"
|
||||
|
||||
Camera::Camera(GLFWwindow *window, const InputMap& inputs, const Camera::options& opt): window(window), inputs(inputs),
|
||||
Position(voxel_pos(0), 1), o(opt){
|
||||
Camera::Camera(const Controllable* origin, const Camera::options& opt): origin(origin), o(opt) {
|
||||
updateProjection();
|
||||
}
|
||||
Camera::~Camera() { }
|
||||
|
@ -13,75 +12,13 @@ void Camera::updateProjection() {
|
|||
ProjectionMatrix = glm::perspective(o.fov, RATIO, o.near, o.far);
|
||||
}
|
||||
|
||||
void Camera::update(bool captureMouse, bool captureKeys, float deltaTime) {
|
||||
// Get mouse position
|
||||
if(captureMouse) {
|
||||
int viewportX, viewportY;
|
||||
glfwGetWindowSize(window, &viewportX, &viewportY);
|
||||
if(capturingMouse) {
|
||||
double xPos, yPos;
|
||||
glfwGetCursorPos(window, &xPos, &yPos);
|
||||
|
||||
// Compute new orientation
|
||||
HorizontalAngle += o.sensibility * 0.0001f * float(viewportX / 2 - xPos);
|
||||
VerticalAngle += o.sensibility * 0.0001f * float(viewportY / 2 - yPos);
|
||||
} else {
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
capturingMouse = true;
|
||||
}
|
||||
// Reset mouse position for next frame
|
||||
glfwSetCursorPos(window, viewportX / 2, viewportY / 2);
|
||||
} else if (capturingMouse) {
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
capturingMouse = false;
|
||||
}
|
||||
|
||||
// Direction : Spherical coordinates to Cartesian coordinates conversion
|
||||
glm::vec3 direction = getDirection();
|
||||
|
||||
// Right vector
|
||||
glm::vec3 right = glm::vec3(
|
||||
sin(HorizontalAngle - 3.14f / 2.0f),
|
||||
0,
|
||||
cos(HorizontalAngle - 3.14f / 2.0f));
|
||||
|
||||
// Up vector
|
||||
glm::vec3 up = glm::cross(right, direction);
|
||||
|
||||
if(captureKeys) {
|
||||
// Move forward
|
||||
if (inputs.isDown(Input::Forward)) {
|
||||
Position.offset += direction * deltaTime * o.speed;
|
||||
}
|
||||
// Move backward
|
||||
if (inputs.isDown(Input::Backward)) {
|
||||
Position.offset -= direction * deltaTime * o.speed;
|
||||
}
|
||||
// Strafe right
|
||||
if (inputs.isDown(Input::Right)) {
|
||||
Position.offset += right * deltaTime * o.speed;
|
||||
}
|
||||
// Strafe left
|
||||
if (inputs.isDown(Input::Left)) {
|
||||
Position.offset -= right * deltaTime * o.speed;
|
||||
}
|
||||
// Move up
|
||||
if (inputs.isDown(Input::Up)) {
|
||||
Position.offset += up * deltaTime * o.speed;
|
||||
}
|
||||
// Move down
|
||||
if (inputs.isDown(Input::Down)) {
|
||||
Position.offset -= up * deltaTime * o.speed;
|
||||
}
|
||||
Position.center();
|
||||
}
|
||||
|
||||
// MAYBE: only if moved
|
||||
// MAYBE: save frustum
|
||||
void Camera::update() {
|
||||
const auto &offset = origin->position.offset;
|
||||
const auto axis = origin->getAxis();
|
||||
// Camera matrix
|
||||
ViewMatrix = glm::lookAt(
|
||||
Position.offset, // Camera is here
|
||||
Position.offset + direction, // and looks here : at the same position, plus "direction"
|
||||
up // Head is up (set to 0,-1,0 to look upside-down)
|
||||
offset, // Camera is here
|
||||
offset + axis.direction, // and looks here : at the same position, plus "direction"
|
||||
axis.up // Head is up (set to 0,-1,0 to look upside-down)
|
||||
);
|
||||
}
|
|
@ -1,13 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "InputMap.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include "../data/glm.hpp"
|
||||
#include "Controllable.hpp"
|
||||
#include "../data/geometry/Frustum.hpp"
|
||||
#include "../data/geometry/Ray.hpp"
|
||||
#include "../world/position.h"
|
||||
|
||||
/// Moving perspective camera
|
||||
class Camera {
|
||||
|
@ -16,42 +11,33 @@ public:
|
|||
float fov = glm::radians(70.f);
|
||||
float near = 0.1;
|
||||
float far = 64;
|
||||
|
||||
float speed = 5.0f;
|
||||
int sensibility = 50;
|
||||
};
|
||||
|
||||
Camera(GLFWwindow*, const InputMap&, const options&);
|
||||
Camera(const Controllable*, const options&);
|
||||
~Camera();
|
||||
|
||||
void update(bool captureMouse, bool captureKeys, float deltaTime);
|
||||
void update();
|
||||
void setOptions(const options &options) {
|
||||
o = options;
|
||||
updateProjection();
|
||||
}
|
||||
void setOrigin(const Controllable* ct) {
|
||||
origin = ct;
|
||||
}
|
||||
|
||||
glm::vec3 getDirection() const { return glm::vec3(cos(VerticalAngle) * sin(HorizontalAngle), sin(VerticalAngle), cos(VerticalAngle) * cos(HorizontalAngle)); }
|
||||
inline geometry::Frustum getFrustum() const { return geometry::Frustum(ViewMatrix, ProjectionMatrix); }
|
||||
inline geometry::Ray getRay() const { return geometry::Ray(Position, getDirection(), o.far); }
|
||||
inline geometry::Ray getRay() const { return geometry::Ray(origin->position, origin->getDirection(), o.far); }
|
||||
|
||||
constexpr glm::mat4 getViewMatrix() const { return ViewMatrix; }
|
||||
constexpr glm::mat4 getProjectionMatrix() const { return ProjectionMatrix; }
|
||||
camera_pos getPosition() const { return Position; }
|
||||
constexpr float getDepth() const { return o.far; }
|
||||
|
||||
private:
|
||||
GLFWwindow *window;
|
||||
const InputMap &inputs;
|
||||
const Controllable* origin;
|
||||
|
||||
glm::mat4 ViewMatrix;
|
||||
glm::mat4 ProjectionMatrix;
|
||||
void updateProjection();
|
||||
|
||||
camera_pos Position;
|
||||
|
||||
float HorizontalAngle = 3.14f;
|
||||
float VerticalAngle = 0.0f;
|
||||
|
||||
bool capturingMouse = false;
|
||||
options o;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
#include "Controllable.hpp"
|
||||
|
||||
Controllable::Controllable(GLFWwindow *window, const InputMap& inputs, const Controllable::options& opt): position(voxel_pos(0), 1), window(window), inputs(inputs), o(opt){ }
|
||||
Controllable::~Controllable() { }
|
||||
|
||||
Controllable::axis Controllable::getAxis() const {
|
||||
Controllable::axis a;
|
||||
// Direction : Spherical coordinates to Cartesian coordinates conversion
|
||||
a.direction = getDirection();
|
||||
|
||||
// Right vector
|
||||
a.right = glm::vec3(sin(HorizontalAngle - 3.14f / 2.0f), 0, cos(HorizontalAngle - 3.14f / 2.0f));
|
||||
|
||||
// Up vector
|
||||
a.up = glm::cross(a.right, a.direction);
|
||||
return a;
|
||||
}
|
||||
|
||||
void Controllable::capture(bool captureMouse, bool captureKeys, float deltaTime) {
|
||||
// Get mouse position
|
||||
if(captureMouse) {
|
||||
int viewportX, viewportY;
|
||||
glfwGetWindowSize(window, &viewportX, &viewportY);
|
||||
if(capturingMouse) {
|
||||
double xPos, yPos;
|
||||
glfwGetCursorPos(window, &xPos, &yPos);
|
||||
|
||||
// Compute new orientation
|
||||
HorizontalAngle += o.sensibility * 0.0001f * float(viewportX / 2 - xPos);
|
||||
VerticalAngle += o.sensibility * 0.0001f * float(viewportY / 2 - yPos);
|
||||
} else {
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
capturingMouse = true;
|
||||
}
|
||||
// Reset mouse position for next frame
|
||||
glfwSetCursorPos(window, viewportX / 2, viewportY / 2);
|
||||
} else if (capturingMouse) {
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
capturingMouse = false;
|
||||
}
|
||||
|
||||
const auto axis = getAxis();
|
||||
|
||||
velocity = glm::vec3(0);
|
||||
if(captureKeys) {
|
||||
// Move forward
|
||||
if (inputs.isDown(Input::Forward)) {
|
||||
velocity += axis.direction;
|
||||
}
|
||||
// Move backward
|
||||
if (inputs.isDown(Input::Backward)) {
|
||||
velocity -= axis.direction;
|
||||
}
|
||||
// Strafe right
|
||||
if (inputs.isDown(Input::Right)) {
|
||||
velocity += axis.right;
|
||||
}
|
||||
// Strafe left
|
||||
if (inputs.isDown(Input::Left)) {
|
||||
velocity -= axis.right;
|
||||
}
|
||||
// Move up
|
||||
if (inputs.isDown(Input::Up)) {
|
||||
velocity += axis.up;
|
||||
}
|
||||
// Move down
|
||||
if (inputs.isDown(Input::Down)) {
|
||||
velocity -= axis.up;
|
||||
}
|
||||
if(velocity != glm::vec3(0)) {
|
||||
velocity = glm::normalize(velocity) * deltaTime * o.speed;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#include "InputMap.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include "../data/glm.hpp"
|
||||
#include "../world/position.h"
|
||||
|
||||
/// Player controller moving entity
|
||||
struct Controllable {
|
||||
public:
|
||||
struct options {
|
||||
float speed = 5.0f;
|
||||
int sensibility = 50;
|
||||
bool collide = true;
|
||||
};
|
||||
|
||||
Controllable(GLFWwindow*, const InputMap&, const options&);
|
||||
~Controllable();
|
||||
|
||||
void capture(bool captureMouse, bool captureKeys, float deltaTime);
|
||||
void setOptions(const options &options) {
|
||||
o = options;
|
||||
}
|
||||
|
||||
glm::vec3 getDirection() const { return glm::vec3(cos(VerticalAngle) * sin(HorizontalAngle), sin(VerticalAngle), cos(VerticalAngle) * cos(HorizontalAngle)); }
|
||||
struct axis {
|
||||
glm::vec3 direction;
|
||||
glm::vec3 up;
|
||||
glm::vec3 right;
|
||||
};
|
||||
axis getAxis() const;
|
||||
|
||||
camera_pos position;
|
||||
glm::vec3 velocity;
|
||||
|
||||
private:
|
||||
GLFWwindow *window;
|
||||
const InputMap &inputs;
|
||||
|
||||
float HorizontalAngle = 3.14f;
|
||||
float VerticalAngle = 0.0f;
|
||||
|
||||
bool capturingMouse = false;
|
||||
options o;
|
||||
};
|
|
@ -19,3 +19,6 @@ void ifvec3::center() {
|
|||
raw += diff;
|
||||
offset -= diff * static_cast<long>(IDX_LENGTH2);
|
||||
}
|
||||
double ifvec3::dist(const ifvec3& p) const {
|
||||
return glm::length(glm::dvec3(raw - p.raw)) + glm::length(offset - p.offset);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace glm {
|
|||
void center();
|
||||
glm::llvec3 raw_as_long() const;
|
||||
glm::dvec3 as_double() const;
|
||||
double dist(const ifvec3 &p) const;
|
||||
|
||||
inline const ifvec3 &operator+=(const offset_t &v) {
|
||||
offset += v;
|
||||
|
@ -39,6 +40,7 @@ namespace glm {
|
|||
return *this;
|
||||
}
|
||||
inline ifvec3 operator+(const offset_t& v) const { return ifvec3(raw, offset + v); }
|
||||
inline ifvec3 operator-(const offset_t &v) const { return ifvec3(raw, offset - v); }
|
||||
inline ifvec3 operator/(int i) const { return ifvec3(raw / i, offset / (i * 1.f), false); }
|
||||
inline ifvec3 operator*(int i) const { return ifvec3(raw * i, offset * (i * 1.f)); }
|
||||
};
|
||||
|
|
17
src/main.cpp
17
src/main.cpp
|
@ -52,7 +52,8 @@ int main(int /*unused*/, char */*unused*/[]){
|
|||
glfwSwapInterval(static_cast<int>(options.target_fps < MIN_FPS));
|
||||
|
||||
InputMap inputs(window);
|
||||
Camera camera(window, inputs, options.camera);
|
||||
Controllable player(window, inputs, options.control);
|
||||
Camera camera(&player, options.camera);
|
||||
|
||||
auto *renderer = new Renderer(options.renderer);
|
||||
renderer->LightInvDir = glm::vec3(-0.5f, 2, -2);
|
||||
|
@ -108,10 +109,17 @@ int main(int /*unused*/, char */*unused*/[]){
|
|||
inputs.toggle(state.capture_mouse, Input::Mouse);
|
||||
inputs.toggle(options.show_debug_menu, Input::Debug);
|
||||
|
||||
camera.update(state.capture_mouse, !UI::isFocus(), deltaTime);
|
||||
player.capture(state.capture_mouse, !UI::isFocus(), deltaTime);
|
||||
if(player.velocity != glm::vec3(0) && (
|
||||
!options.control.collide ||
|
||||
!world.collide(player.position, player.velocity, options.voxel_density, 1))
|
||||
) {
|
||||
player.position += player.velocity;
|
||||
state.position = player.position;
|
||||
}
|
||||
camera.update();
|
||||
renderer->lookFrom(camera);
|
||||
|
||||
state.position = camera.getPosition();
|
||||
state.look_at = world.raycast(camera.getRay() * options.voxel_density);
|
||||
if (state.capture_mouse) {
|
||||
if (state.look_at.has_value()) {
|
||||
|
@ -161,6 +169,9 @@ int main(int /*unused*/, char */*unused*/[]){
|
|||
if(actions && UI::Actions::Camera) {
|
||||
camera.setOptions(options.camera);
|
||||
}
|
||||
if(actions && UI::Actions::Control) {
|
||||
player.setOptions(options.control);
|
||||
}
|
||||
if(actions && UI::Actions::ChangeContouring) {
|
||||
state.contouring = NULL;
|
||||
world.setContouring(contouring::load(options.contouring_idx, options.contouring_data));
|
||||
|
|
|
@ -61,12 +61,12 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
|
|||
ImGui::Separator();
|
||||
ImGui::Checkbox("Overlay", &options.overlay_show);
|
||||
if (ImGui::SliderInt("FPS", &options.target_fps, MIN_FPS-1, MAX_FPS+1, options.target_fps > MIN_FPS ? (options.target_fps < MAX_FPS ? "%d" : "UNLIMITED") : "VSYNC")){
|
||||
actions = actions | Actions::FPS;
|
||||
actions |= Actions::FPS;
|
||||
}
|
||||
|
||||
ImGui::Text("Sampling %d (requires restart)", options.samples);
|
||||
if (ImGui::Checkbox("Fullscreen", &options.fullscreen)){
|
||||
actions = actions | Actions::FullScreen;
|
||||
actions |= Actions::FullScreen;
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -87,17 +87,17 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
|
|||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Skybox", &options.renderer.skybox);
|
||||
if (changeRenderer) {
|
||||
actions = actions | Actions::RendererSharders;
|
||||
actions |= Actions::RendererSharders;
|
||||
}
|
||||
}
|
||||
if (ImGui::ColorEdit3("Fog color", &options.renderer.clear_color[0])) {
|
||||
actions = actions | Actions::ClearColor;
|
||||
actions |= Actions::ClearColor;
|
||||
}
|
||||
if (ImGui::Checkbox("Wireframe", &options.renderer.wireframe))
|
||||
glPolygonMode(GL_FRONT_AND_BACK, options.renderer.wireframe ? GL_LINE : GL_FILL);
|
||||
ImGui::Text("Textures '%s'", options.renderer.textures.c_str()); // MAYBE: select
|
||||
if (ImGui::SliderFloat("LOD", &options.renderer.mipMapLOD, -1, 1)) {
|
||||
actions = actions | Actions::RendererTextures;
|
||||
actions |= Actions::RendererTextures;
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
|
|||
ImGui::Text("Path: %s", options.world.folderPath.c_str());
|
||||
if (ImGui::SliderInt("Load distance", &options.world.loadDistance, 1, options.world.keepDistance) |
|
||||
ImGui::SliderInt("Keep distance", &options.world.keepDistance, options.world.loadDistance + 1, 21)) {
|
||||
actions = actions | Actions::World;
|
||||
actions |= Actions::World;
|
||||
}
|
||||
if(ImGui::SliderInt("Voxel density", &options.voxel_density, 1, CHUNK_LENGTH * REGION_LENGTH)) {
|
||||
options.voxel_density = pow(2, ceil(log(options.voxel_density) / log(2)));
|
||||
|
@ -121,7 +121,7 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
|
|||
for (size_t i = 0; i < contouring::names.size(); i++) {
|
||||
const bool is_selected = (options.contouring_idx == (int)i);
|
||||
if (ImGui::Selectable(contouring::names[i].c_str(), is_selected)) {
|
||||
actions = actions | Actions::ChangeContouring;
|
||||
actions |= Actions::ChangeContouring;
|
||||
contouring::save(options.contouring_idx, state.contouring, options.contouring_data);
|
||||
options.contouring_idx = i;
|
||||
}
|
||||
|
@ -142,15 +142,21 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
|
|||
const auto p = state.position.as_voxel(options.voxel_density);
|
||||
ImGui::Text("Position: (%lld, %lld, %lld)", p.x, p.y, p.z);
|
||||
ImGui::Separator();
|
||||
{
|
||||
if (ImGui::SliderFloat("Move speed", &options.control.speed, 0.1, 50) |
|
||||
ImGui::SliderInt("Sensibility", &options.control.sensibility, 1, 100, "%d%%")) {
|
||||
actions |= Actions::Control;
|
||||
}
|
||||
ImGui::Checkbox("Collide", &options.control.collide);
|
||||
}
|
||||
ImGui::Separator();
|
||||
{
|
||||
bool changePerspective = false;
|
||||
changePerspective |= ImGui::SliderAngle("FoV", &options.camera.fov, 30, 110);
|
||||
changePerspective |= ImGui::SliderFloat("Near", &options.camera.near, 0.01, 10);
|
||||
changePerspective |= ImGui::SliderFloat("Far", &options.camera.far, farRange.first / options.voxel_density, farRange.second / options.voxel_density);
|
||||
changePerspective |= ImGui::SliderFloat("Move speed", &options.camera.speed, 0.1, 50);
|
||||
changePerspective |= ImGui::SliderInt("Sensibility", &options.camera.sensibility, 1, 100, "%d%%");
|
||||
if(changePerspective) {
|
||||
actions = actions | Actions::Camera;
|
||||
actions |= Actions::Camera;
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
|
@ -158,7 +164,7 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
|
|||
const auto far = std::clamp(options.camera.far, farRange.first / options.voxel_density, farRange.second / options.voxel_density);
|
||||
if(far != options.camera.far) {
|
||||
options.camera.far = far;
|
||||
actions = actions | Actions::Camera;
|
||||
actions |= Actions::Camera;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,11 @@ namespace UI {
|
|||
RendererTextures = 1 << 4,
|
||||
World = 1 << 5,
|
||||
Camera = 1 << 6,
|
||||
ChangeContouring = 1 << 7,
|
||||
Control = 1 << 7,
|
||||
ChangeContouring = 1 << 8,
|
||||
};
|
||||
inline Actions operator|(Actions a, Actions b) {
|
||||
return static_cast<Actions>(static_cast<int>(a) | static_cast<int>(b));
|
||||
inline void operator|=(Actions& a, Actions b) {
|
||||
a = static_cast<Actions>(static_cast<int>(a) | static_cast<int>(b));
|
||||
}
|
||||
inline bool operator&&(Actions a, Actions b) {
|
||||
return static_cast<int>(a) & static_cast<int>(b);
|
||||
|
|
15
src/state.h
15
src/state.h
|
@ -62,8 +62,9 @@ struct options {
|
|||
camera.far = config["camera"]["far"].value_or(camera.far);
|
||||
camera.near = config["camera"]["near"].value_or(camera.near);
|
||||
camera.fov = config["camera"]["fov"].value_or(camera.fov);
|
||||
camera.sensibility = config["camera"]["sensibility"].value_or(camera.sensibility);
|
||||
camera.speed = config["camera"]["speed"].value_or(camera.speed);
|
||||
control.sensibility = config["control"]["sensibility"].value_or(control.sensibility);
|
||||
control.speed = config["control"]["speed"].value_or(control.speed);
|
||||
control.collide = config["control"]["collide"].value_or(control.collide);
|
||||
|
||||
overlay_show = config["overlay"]["visible"].value_or(true);
|
||||
overlay_corner = config["overlay"]["corner"].value_or(3);
|
||||
|
@ -117,9 +118,12 @@ struct options {
|
|||
config.insert_or_assign("camera", toml::table({
|
||||
{"far", camera.far},
|
||||
{"near", camera.near},
|
||||
{"fov", camera.fov},
|
||||
{"sensibility", camera.sensibility},
|
||||
{"speed", camera.speed}
|
||||
{"fov", camera.fov}
|
||||
}));
|
||||
config.insert_or_assign("control", toml::table({
|
||||
{"sensibility", control.sensibility},
|
||||
{"speed", control.speed},
|
||||
{"collide", control.collide}
|
||||
}));
|
||||
config.insert_or_assign("overlay", toml::table({
|
||||
{"visible", overlay_show},
|
||||
|
@ -164,6 +168,7 @@ struct options {
|
|||
std::map<std::string, std::string> contouring_data;
|
||||
|
||||
bool show_debug_controls;
|
||||
Controllable::options control;
|
||||
Camera::options camera;
|
||||
|
||||
bool editor_show;
|
||||
|
|
|
@ -113,6 +113,7 @@ Universe::~Universe() {
|
|||
LOG_I("Saving " << size << " chunks");
|
||||
const auto SAVE_CHECK_TIME = 500;
|
||||
do {
|
||||
loadQueue.notify_all();
|
||||
std::cout << "\rSaving... " << size << " " << std::flush;
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(SAVE_CHECK_TIME));
|
||||
size = saveQueue.size();
|
||||
|
@ -384,6 +385,25 @@ ItemList Universe::setCube(const area_<voxel_pos>& pos, const Voxel& val, int ra
|
|||
}
|
||||
return list;
|
||||
}
|
||||
bool Universe::collide(const glm::ifvec3 &pos, const glm::vec3 &vel, int density, float radius) const {
|
||||
const auto dir = glm::normalize(vel);
|
||||
const auto velocity = vel * glm::vec3(density);
|
||||
const auto from = pos * density + dir;
|
||||
return raycast(Ray(from, dir, glm::length(velocity) + radius)).has_value();
|
||||
}
|
||||
bool Universe::move(glm::ifvec3 &pos, const glm::vec3 &vel, int density, float radius) const {
|
||||
const auto dir = glm::normalize(vel);
|
||||
const auto velocity = vel * glm::vec3(density);
|
||||
const auto from = pos * density + dir;
|
||||
if (const auto target = raycast(Ray(from, dir, glm::length(velocity) + radius))) {
|
||||
const auto target_dist = from.dist(glm::ifvec3(target.value().offset + target.value().pos.second, density)) - radius;
|
||||
pos += vel * glm::vec3(target_dist / glm::length(vel));
|
||||
return true;
|
||||
}
|
||||
|
||||
pos += vel;
|
||||
return false;
|
||||
}
|
||||
|
||||
entity_instance_id Universe::addEntity(entity_id type, const Entity::Instance &instance) {
|
||||
return std::make_pair(type, entities.at(type).instances.push(instance));
|
||||
|
|
|
@ -56,6 +56,11 @@ namespace world {
|
|||
/// Set cube of voxel with pos as center
|
||||
/// MAYBE: allow set multi area
|
||||
ItemList setCube(const area_<voxel_pos> &pos, const Voxel &val, int radius);
|
||||
/// Check for collision on movement
|
||||
bool collide(const glm::ifvec3 &pos, const glm::vec3 &vel, int density, float radius = 0) const;
|
||||
/// Move with collision check
|
||||
/// @note must remove velocity after colision
|
||||
bool move(glm::ifvec3 &pos, const glm::vec3 &vel, int density, float radius = 0) const;
|
||||
|
||||
/// Entities commun properties
|
||||
struct Entity {
|
||||
|
|
Loading…
Reference in New Issue