mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
Compare commits
3 Commits
9fc94c56b5
...
1af41db615
| Author | SHA1 | Date | |
|---|---|---|---|
| 1af41db615 | |||
| 1e17474122 | |||
| b24ce458dc |
@@ -26,9 +26,6 @@ class DevPanel {
|
|||||||
int gait = 0;
|
int gait = 0;
|
||||||
float pos[3] = {0.0f, 0.0f, 0.0f};
|
float pos[3] = {0.0f, 0.0f, 0.0f};
|
||||||
};
|
};
|
||||||
struct TextEditing {
|
|
||||||
bool perlin_seed = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DevPanel(App& app);
|
DevPanel(App& app);
|
||||||
@@ -40,7 +37,6 @@ private:
|
|||||||
ConfigView m_config;
|
ConfigView m_config;
|
||||||
ClientPlayer* m_player;
|
ClientPlayer* m_player;
|
||||||
PlayerProfile m_player_profile;
|
PlayerProfile m_player_profile;
|
||||||
TextEditing m_text_editing;
|
|
||||||
bool m_need_save_config = false;
|
bool m_need_save_config = false;
|
||||||
bool m_gen_thread_running = true;
|
bool m_gen_thread_running = true;
|
||||||
int m_theme = 0;
|
int m_theme = 0;
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ public:
|
|||||||
void update();
|
void update();
|
||||||
void hot_reload();
|
void hot_reload();
|
||||||
|
|
||||||
void rebuild_world();
|
|
||||||
int rendering_distance() const;
|
int rendering_distance() const;
|
||||||
void rendering_distance(int rendering_distance);
|
void rendering_distance(int rendering_distance);
|
||||||
void start_gen_thread();
|
void start_gen_thread();
|
||||||
@@ -131,7 +130,6 @@ private:
|
|||||||
std::atomic<bool> m_could_gen{true};
|
std::atomic<bool> m_could_gen{true};
|
||||||
std::atomic<bool> m_gen_running{false};
|
std::atomic<bool> m_gen_running{false};
|
||||||
std::atomic<bool> m_need_gen_chunk{false};
|
std::atomic<bool> m_need_gen_chunk{false};
|
||||||
std::atomic<bool> m_is_rebuilding{false};
|
|
||||||
std::atomic<bool> m_init{false};
|
std::atomic<bool> m_init{false};
|
||||||
std::atomic<bool> m_stopped{false};
|
std::atomic<bool> m_stopped{false};
|
||||||
std::atomic<int> m_rendering_distance{24};
|
std::atomic<int> m_rendering_distance{24};
|
||||||
|
|||||||
@@ -1,18 +1,108 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <algorithm>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
namespace Math {
|
namespace Math {
|
||||||
|
|
||||||
void extract_frustum_planes(const glm::mat4& mvp_matrix,
|
inline void extract_frustum_planes(const glm::mat4& mvp_matrix,
|
||||||
std::vector<glm::vec4>& planes);
|
std::vector<glm::vec4>& planes) {
|
||||||
|
if (planes.size() != 6) {
|
||||||
|
planes.resize(6);
|
||||||
|
}
|
||||||
|
|
||||||
float smootherstep(float edge0, float edge1, float x);
|
const float* m = glm::value_ptr(mvp_matrix);
|
||||||
bool is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_extents,
|
|
||||||
const std::vector<glm::vec4>& planes);
|
// left plane
|
||||||
float deterministic_random(int x, int z, uint64_t seed);
|
planes[0] =
|
||||||
glm::vec3 slerp(const glm::vec3& from, const glm::vec3& to, float t);
|
glm::vec4(m[3] + m[0], m[7] + m[4], m[11] + m[8], m[15] + m[12]);
|
||||||
|
// right plane
|
||||||
|
planes[1] =
|
||||||
|
glm::vec4(m[3] - m[0], m[7] - m[4], m[11] - m[8], m[15] - m[12]);
|
||||||
|
// bottom plane
|
||||||
|
planes[2] =
|
||||||
|
glm::vec4(m[3] + m[1], m[7] + m[5], m[11] + m[9], m[15] + m[13]);
|
||||||
|
// top plane
|
||||||
|
planes[3] =
|
||||||
|
glm::vec4(m[3] - m[1], m[7] - m[5], m[11] - m[9], m[15] - m[13]);
|
||||||
|
// near plane
|
||||||
|
planes[4] =
|
||||||
|
glm::vec4(m[3] + m[2], m[7] + m[6], m[11] + m[10], m[15] + m[14]);
|
||||||
|
// far plane
|
||||||
|
planes[5] =
|
||||||
|
glm::vec4(m[3] - m[2], m[7] - m[6], m[11] - m[10], m[15] - m[14]);
|
||||||
|
|
||||||
|
for (auto& p : planes) {
|
||||||
|
p = glm::normalize(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float smootherstep(float edge0, float edge1, float x) {
|
||||||
|
|
||||||
|
x = std::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
|
||||||
|
|
||||||
|
return x * x * x * (x * (6.0f * x - 15.0f) + 10.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_aabb_in_frustum(const glm::vec3& center,
|
||||||
|
const glm::vec3& half_extents,
|
||||||
|
const std::vector<glm::vec4>& planes) {
|
||||||
|
for (const auto& plane : planes) {
|
||||||
|
// distance
|
||||||
|
float d = glm::dot(glm::vec3(plane), center) + plane.w;
|
||||||
|
float r = half_extents.x * std::abs(plane.x) +
|
||||||
|
half_extents.y * std::abs(plane.y) +
|
||||||
|
half_extents.z * std::abs(plane.z);
|
||||||
|
if (d + r < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
inline float deterministic_random(int x, int z, uint64_t seed) {
|
||||||
|
uint64_t h = seed;
|
||||||
|
h = h * 6364136223846793005ULL + (uint64_t)x;
|
||||||
|
h = h * 6364136223846793005ULL + (uint64_t)z;
|
||||||
|
return (float)(h >> 40) / (float)(1 << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline glm::vec3 slerp(const glm::vec3& from, const glm::vec3& to, float t) {
|
||||||
|
|
||||||
|
float cos_theta = glm::clamp(glm::dot(from, to), -1.0f, 1.0f);
|
||||||
|
|
||||||
|
if (cos_theta > 0.9995f) {
|
||||||
|
return glm::normalize(glm::mix(from, to, t));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cos_theta < -0.9995f) {
|
||||||
|
|
||||||
|
glm::vec3 axis = (std::fabs(from.x) < 0.9f)
|
||||||
|
? glm::vec3(1.0f, 0.0f, 0.0f)
|
||||||
|
: glm::vec3(0.0f, 1.0f, 0.0f);
|
||||||
|
glm::vec3 ortho = glm::normalize(glm::cross(from, axis));
|
||||||
|
|
||||||
|
float angle = glm::pi<float>() * t;
|
||||||
|
|
||||||
|
glm::vec3 rotated =
|
||||||
|
from * std::cos(angle) + glm::cross(ortho, from) * std::sin(angle);
|
||||||
|
|
||||||
|
return glm::normalize(rotated);
|
||||||
|
}
|
||||||
|
|
||||||
|
float theta = std::acos(cos_theta);
|
||||||
|
float sin_theta = std::sin(theta);
|
||||||
|
|
||||||
|
float a = std::sin((1.0f - t) * theta) / sin_theta;
|
||||||
|
float b = std::sin(t * theta) / sin_theta;
|
||||||
|
|
||||||
|
return glm::normalize(a * from + b * to);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float distance2(const glm::vec3& a, const glm::vec3& b) {
|
||||||
|
glm::vec3 diff = a - b;
|
||||||
|
return glm::dot(diff, diff);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Math
|
} // namespace Math
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ target_sources(${PROJECT_NAME}
|
|||||||
shader.cpp
|
shader.cpp
|
||||||
texture_manager.cpp
|
texture_manager.cpp
|
||||||
tools/cubed_random.cpp
|
tools/cubed_random.cpp
|
||||||
tools/math_tools.cpp
|
|
||||||
tools/shader_tools.cpp
|
tools/shader_tools.cpp
|
||||||
tools/font.cpp
|
tools/font.cpp
|
||||||
tools/perlin_noise.cpp
|
tools/perlin_noise.cpp
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ static constexpr const char* THEMES[] = {"Dark", "Light"};
|
|||||||
static constexpr const char* GAITS[] = {"Walk", "Run"};
|
static constexpr const char* GAITS[] = {"Walk", "Run"};
|
||||||
static constexpr const char* GAME_MODES[] = {"Creative", "Spectator"};
|
static constexpr const char* GAME_MODES[] = {"Creative", "Spectator"};
|
||||||
static constexpr const char* CHUNK_LOAD_STYLE[] = {"Random", "Center"};
|
static constexpr const char* CHUNK_LOAD_STYLE[] = {"Random", "Center"};
|
||||||
static char perlin_noise_input_buffer[64];
|
|
||||||
|
|
||||||
constexpr float TEMP_MIN = 0.0f;
|
constexpr float TEMP_MIN = 0.0f;
|
||||||
constexpr float TEMP_MAX = 1.0f;
|
constexpr float TEMP_MAX = 1.0f;
|
||||||
@@ -47,16 +46,6 @@ constexpr float DELTA_ANGLE_MAX = 30.0f;
|
|||||||
constexpr int PATH_STEP_MIN = 1;
|
constexpr int PATH_STEP_MIN = 1;
|
||||||
constexpr int PATH_STEP_MAX = 1000;
|
constexpr int PATH_STEP_MAX = 1000;
|
||||||
|
|
||||||
static int filter_unsigned(ImGuiInputTextCallbackData* data) {
|
|
||||||
if (data->EventFlag == ImGuiInputTextFlags_CallbackCharFilter) {
|
|
||||||
char c = data->EventChar;
|
|
||||||
if (c < '0' || c > '9') {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DevPanel::DevPanel(App& app) : m_app(app) {}
|
DevPanel::DevPanel(App& app) : m_app(app) {}
|
||||||
|
|
||||||
void DevPanel::init() {
|
void DevPanel::init() {
|
||||||
@@ -483,25 +472,8 @@ void DevPanel::show_world_tab_item() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DevPanel::show_server_world_table_bar() {
|
void DevPanel::show_server_world_table_bar() {
|
||||||
if (m_text_editing.perlin_seed) {
|
|
||||||
if (ImGui::InputText("ChunkGenerator Seed", perlin_noise_input_buffer,
|
|
||||||
sizeof(perlin_noise_input_buffer),
|
|
||||||
ImGuiInputTextFlags_CallbackCharFilter |
|
|
||||||
ImGuiInputTextFlags_EnterReturnsTrue,
|
|
||||||
filter_unsigned)) {
|
|
||||||
ChunkGenerator::seed(static_cast<unsigned int>(
|
|
||||||
std::strtoul(perlin_noise_input_buffer, nullptr, 10)));
|
|
||||||
m_text_editing.perlin_seed = false;
|
|
||||||
m_player->set_player_pos({0.0f, 255.0f, 0.0f});
|
|
||||||
m_app.server_world().rebuild_world();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!m_text_editing.perlin_seed) {
|
|
||||||
ImGui::Text("ChunkGenerator Seed: %u", ChunkGenerator::seed());
|
ImGui::Text("ChunkGenerator Seed: %u", ChunkGenerator::seed());
|
||||||
if (ImGui::IsItemClicked()) {
|
|
||||||
m_text_editing.perlin_seed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Text("Pool Threads %d Max Support Threads %d Reserved Threads %d",
|
ImGui::Text("Pool Threads %d Max Support Threads %d Reserved Threads %d",
|
||||||
m_app.server_world().gen_pool_threads(),
|
m_app.server_world().gen_pool_threads(),
|
||||||
@@ -525,12 +497,8 @@ void DevPanel::show_server_world_table_bar() {
|
|||||||
IM_ARRAYSIZE(CHUNK_LOAD_STYLE))) {
|
IM_ARRAYSIZE(CHUNK_LOAD_STYLE))) {
|
||||||
m_app.server_world().set_chunk_load_style(m_chunk_style);
|
m_app.server_world().set_chunk_load_style(m_chunk_style);
|
||||||
}
|
}
|
||||||
if (ImGui::Button("Rebuild World")) {
|
|
||||||
m_app.server_world().rebuild_world();
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("Request Chunk Build")) {
|
if (ImGui::Button("Request Chunk Build")) {
|
||||||
Logger::warn("This Request Chunk Build button is not finish");
|
|
||||||
m_app.server_world().need_gen(m_player->get_uuid());
|
m_app.server_world().need_gen(m_player->get_uuid());
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
@@ -572,6 +540,10 @@ void DevPanel::show_client_world_table_bar() {
|
|||||||
m_app.client_world().rendering_distance(rendering_distance);
|
m_app.client_world().rendering_distance(rendering_distance);
|
||||||
// Config::get().set("world.rendering_distance", rendering_distance);
|
// Config::get().set("world.rendering_distance", rendering_distance);
|
||||||
}
|
}
|
||||||
|
if (ImGui::Button("Rebuild World")) {
|
||||||
|
m_app.client_world().rebuild_world();
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Spawn Point")) {
|
if (ImGui::Button("Spawn Point")) {
|
||||||
m_player->set_player_pos({0.0f, 255.0f, 0.0f});
|
m_player->set_player_pos({0.0f, 255.0f, 0.0f});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "Cubed/config.hpp"
|
#include "Cubed/config.hpp"
|
||||||
#include "Cubed/gameplay/game_time.hpp"
|
#include "Cubed/gameplay/game_time.hpp"
|
||||||
#include "Cubed/gameplay/packet.hpp"
|
#include "Cubed/gameplay/packet.hpp"
|
||||||
|
#include "Cubed/tools/math_tools.hpp"
|
||||||
|
|
||||||
#include <numbers>
|
#include <numbers>
|
||||||
|
|
||||||
@@ -608,6 +609,11 @@ void ClientWorld::update(float delta_time) {
|
|||||||
for (auto& [uuid, player] : m_other_players) {
|
for (auto& [uuid, player] : m_other_players) {
|
||||||
player.render_pos =
|
player.render_pos =
|
||||||
glm::mix(player.render_pos, player.target_pos, 0.15f);
|
glm::mix(player.render_pos, player.target_pos, 0.15f);
|
||||||
|
if (Math::distance2(player.render_pos, m_player.get_player_pos()) >
|
||||||
|
m_rendering_distance * CHUNK_SIZE * m_rendering_distance *
|
||||||
|
CHUNK_SIZE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
m_render_player_data.emplace_back(player.name, player.render_pos);
|
m_render_player_data.emplace_back(player.name, player.render_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -504,40 +504,6 @@ void ServerWorld::hot_reload() {
|
|||||||
m_rendering_distance = dist <= MAX_DISTANCE ? dist : MAX_DISTANCE;
|
m_rendering_distance = dist <= MAX_DISTANCE ? dist : MAX_DISTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerWorld::rebuild_world() {
|
|
||||||
if (m_is_rebuilding.exchange(true)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
stop_gen_thread();
|
|
||||||
stop_thread_pool();
|
|
||||||
stop_server_thread();
|
|
||||||
m_cave_carcer.reload(ChunkGenerator::seed());
|
|
||||||
m_river_worm.reload(ChunkGenerator::seed());
|
|
||||||
|
|
||||||
m_chunks.clear();
|
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard lock(m_new_chunk_mutex);
|
|
||||||
m_new_chunks.clear();
|
|
||||||
}
|
|
||||||
m_could_gen = true;
|
|
||||||
ChunkGenerator::reload();
|
|
||||||
start_thread_pool();
|
|
||||||
start_gen_thread();
|
|
||||||
start_server_thread();
|
|
||||||
Arena arena;
|
|
||||||
auto* rsp = Arena::Create<S2C_ClearAllChunks>(&arena);
|
|
||||||
rsp->set_clear(true);
|
|
||||||
{
|
|
||||||
std::lock_guard lock(m_player_mutex);
|
|
||||||
for (auto& [uuid, player] : m_players) {
|
|
||||||
player.get_session()->send(make_packet(*rsp));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_is_rebuilding = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerWorld::update() {
|
void ServerWorld::update() {
|
||||||
// poll_finished_chunks();
|
// poll_finished_chunks();
|
||||||
{
|
{
|
||||||
@@ -585,7 +551,7 @@ void ServerWorld::sync_player_pos(const std::string& uuid, float x, float y,
|
|||||||
it->second.update_sync_gametick(m_game_ticks);
|
it->second.update_sync_gametick(m_game_ticks);
|
||||||
name = it->second.get_name();
|
name = it->second.get_name();
|
||||||
}
|
}
|
||||||
|
ChunkPos pos = get_chunk_pos(x, z);
|
||||||
// update other player pos;
|
// update other player pos;
|
||||||
std::vector<std::shared_ptr<Session>> other;
|
std::vector<std::shared_ptr<Session>> other;
|
||||||
{
|
{
|
||||||
@@ -594,11 +560,16 @@ void ServerWorld::sync_player_pos(const std::string& uuid, float x, float y,
|
|||||||
if (o_uuid == uuid) {
|
if (o_uuid == uuid) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (player.has_player(pos)) {
|
||||||
other.emplace_back(player.get_session());
|
other.emplace_back(player.get_session());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& session : other) {
|
for (auto& session : other) {
|
||||||
|
if (!session) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Arena arena;
|
Arena arena;
|
||||||
auto* rsp = Arena::Create<PlayerInfoRsp>(&arena);
|
auto* rsp = Arena::Create<PlayerInfoRsp>(&arena);
|
||||||
rsp->set_uuid(uuid);
|
rsp->set_uuid(uuid);
|
||||||
@@ -694,8 +665,10 @@ void ServerWorld::handle_player_exit(const std::string& uuid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto& s : sessions) {
|
for (auto& s : sessions) {
|
||||||
|
if (s) {
|
||||||
s->send(make_packet(*rsp));
|
s->send(make_packet(*rsp));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 ServerWorld::get_player_pos(const std::string& uuid) const {
|
glm::vec3 ServerWorld::get_player_pos(const std::string& uuid) const {
|
||||||
@@ -741,15 +714,23 @@ void ServerWorld::handle_block_change(const BlockChangeReq& req) {
|
|||||||
pos->set_y(y);
|
pos->set_y(y);
|
||||||
pos->set_z(z);
|
pos->set_z(z);
|
||||||
rsp->set_block(req.block());
|
rsp->set_block(req.block());
|
||||||
|
std::vector<std::shared_ptr<Session>> sessions;
|
||||||
|
auto chunk_pos = get_chunk_pos(x, z);
|
||||||
{
|
{
|
||||||
std::shared_lock lock(m_player_mutex);
|
std::shared_lock lock(m_player_mutex);
|
||||||
for (auto& [uuid, player] : m_players) {
|
for (auto& [uuid, player] : m_players) {
|
||||||
|
if (player.has_player(chunk_pos)) {
|
||||||
auto session = player.get_session();
|
auto session = player.get_session();
|
||||||
if (session) {
|
sessions.emplace_back(std::move(session));
|
||||||
session->send(make_packet(*rsp));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto& x : sessions) {
|
||||||
|
if (x) {
|
||||||
|
x->send(make_packet(*rsp));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ServerWorld::rendering_distance() const {
|
int ServerWorld::rendering_distance() const {
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
#include "Cubed/tools/math_tools.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
|
||||||
|
|
||||||
namespace Cubed {
|
|
||||||
|
|
||||||
namespace Math {
|
|
||||||
|
|
||||||
void extract_frustum_planes(const glm::mat4& mvp_matrix,
|
|
||||||
std::vector<glm::vec4>& planes) {
|
|
||||||
if (planes.size() != 6) {
|
|
||||||
planes.resize(6);
|
|
||||||
}
|
|
||||||
|
|
||||||
const float* m = glm::value_ptr(mvp_matrix);
|
|
||||||
|
|
||||||
// left plane
|
|
||||||
planes[0] =
|
|
||||||
glm::vec4(m[3] + m[0], m[7] + m[4], m[11] + m[8], m[15] + m[12]);
|
|
||||||
// right plane
|
|
||||||
planes[1] =
|
|
||||||
glm::vec4(m[3] - m[0], m[7] - m[4], m[11] - m[8], m[15] - m[12]);
|
|
||||||
// bottom plane
|
|
||||||
planes[2] =
|
|
||||||
glm::vec4(m[3] + m[1], m[7] + m[5], m[11] + m[9], m[15] + m[13]);
|
|
||||||
// top plane
|
|
||||||
planes[3] =
|
|
||||||
glm::vec4(m[3] - m[1], m[7] - m[5], m[11] - m[9], m[15] - m[13]);
|
|
||||||
// near plane
|
|
||||||
planes[4] =
|
|
||||||
glm::vec4(m[3] + m[2], m[7] + m[6], m[11] + m[10], m[15] + m[14]);
|
|
||||||
// far plane
|
|
||||||
planes[5] =
|
|
||||||
glm::vec4(m[3] - m[2], m[7] - m[6], m[11] - m[10], m[15] - m[14]);
|
|
||||||
|
|
||||||
for (auto& p : planes) {
|
|
||||||
p = glm::normalize(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float smootherstep(float edge0, float edge1, float x) {
|
|
||||||
|
|
||||||
x = std::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
|
|
||||||
|
|
||||||
return x * x * x * (x * (6.0f * x - 15.0f) + 10.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_extents,
|
|
||||||
const std::vector<glm::vec4>& planes) {
|
|
||||||
for (const auto& plane : planes) {
|
|
||||||
// distance
|
|
||||||
float d = glm::dot(glm::vec3(plane), center) + plane.w;
|
|
||||||
float r = half_extents.x * std::abs(plane.x) +
|
|
||||||
half_extents.y * std::abs(plane.y) +
|
|
||||||
half_extents.z * std::abs(plane.z);
|
|
||||||
if (d + r < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
float deterministic_random(int x, int z, uint64_t seed) {
|
|
||||||
uint64_t h = seed;
|
|
||||||
h = h * 6364136223846793005ULL + (uint64_t)x;
|
|
||||||
h = h * 6364136223846793005ULL + (uint64_t)z;
|
|
||||||
return (float)(h >> 40) / (float)(1 << 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 slerp(const glm::vec3& from, const glm::vec3& to, float t) {
|
|
||||||
|
|
||||||
float cos_theta = glm::clamp(glm::dot(from, to), -1.0f, 1.0f);
|
|
||||||
|
|
||||||
if (cos_theta > 0.9995f) {
|
|
||||||
return glm::normalize(glm::mix(from, to, t));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cos_theta < -0.9995f) {
|
|
||||||
|
|
||||||
glm::vec3 axis = (std::fabs(from.x) < 0.9f)
|
|
||||||
? glm::vec3(1.0f, 0.0f, 0.0f)
|
|
||||||
: glm::vec3(0.0f, 1.0f, 0.0f);
|
|
||||||
glm::vec3 ortho = glm::normalize(glm::cross(from, axis));
|
|
||||||
|
|
||||||
float angle = glm::pi<float>() * t;
|
|
||||||
|
|
||||||
glm::vec3 rotated =
|
|
||||||
from * std::cos(angle) + glm::cross(ortho, from) * std::sin(angle);
|
|
||||||
|
|
||||||
return glm::normalize(rotated);
|
|
||||||
}
|
|
||||||
|
|
||||||
float theta = std::acos(cos_theta);
|
|
||||||
float sin_theta = std::sin(theta);
|
|
||||||
|
|
||||||
float a = std::sin((1.0f - t) * theta) / sin_theta;
|
|
||||||
float b = std::sin(t * theta) / sin_theta;
|
|
||||||
|
|
||||||
return glm::normalize(a * from + b * to);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Math
|
|
||||||
|
|
||||||
} // namespace Cubed
|
|
||||||
Reference in New Issue
Block a user