mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
Compare commits
7 Commits
849386a3bc
...
7b530968af
| Author | SHA1 | Date | |
|---|---|---|---|
| 7b530968af | |||
| 930226cc47 | |||
| f9bf2f4b89 | |||
| df3ac5b5db | |||
| 2568eb7d18 | |||
| 2e3b4f4f0f | |||
| 5951a5e81c |
16
assets/model/creature/collision.json
Normal file
16
assets/model/creature/collision.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"boxes": [
|
||||
{
|
||||
"center": [
|
||||
0,
|
||||
0.78,
|
||||
0
|
||||
],
|
||||
"half": [
|
||||
0.53,
|
||||
0.78,
|
||||
0.406
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3,13 +3,45 @@
|
||||
in vec2 tc;
|
||||
in vec3 normal;
|
||||
in vec3 vert_pos;
|
||||
|
||||
in vec4 FragPosLightSpace;
|
||||
out vec4 color;
|
||||
|
||||
layout (binding = 0) uniform sampler2D samp;
|
||||
layout (binding = 0) uniform sampler2D shadowMap;
|
||||
layout (binding = 1) uniform sampler2D samp;
|
||||
|
||||
uniform float ambientStrength;
|
||||
uniform vec3 sunlightColor;
|
||||
uniform vec3 ambientColor;
|
||||
uniform vec3 sunlightDir;
|
||||
uniform bool shader_on;
|
||||
uniform int shadowMode;
|
||||
uniform float lightSizeUV;
|
||||
uniform float minRadius;
|
||||
uniform float maxRadius;
|
||||
|
||||
#include "shadow.glsl"
|
||||
|
||||
void main() {
|
||||
color = texture(samp, tc);
|
||||
vec4 objectColor = texture(samp, tc);
|
||||
|
||||
if (!shader_on) {
|
||||
color = objectColor;
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 lightDir = normalize(-sunlightDir);
|
||||
|
||||
vec3 norm = normalize(normal);
|
||||
|
||||
vec3 ambient = ambientStrength * ambientColor;
|
||||
|
||||
float diff = max(dot(norm, lightDir), 0.0);
|
||||
|
||||
vec3 diffuse = diff * sunlightColor;
|
||||
|
||||
float shadow = ShadowCalculation(FragPosLightSpace, norm, lightDir);
|
||||
//float shadow = 0.0;
|
||||
//color = vec4(vec3(shadow),1);
|
||||
//color = vec4(vec3(diff),1);
|
||||
color = vec4((ambient + (1.0 - shadow) * (diffuse)) * objectColor.rgb, objectColor.a);
|
||||
}
|
||||
|
||||
@@ -6,17 +6,21 @@ layout (location = 2) in vec3 aNormal;
|
||||
|
||||
uniform mat4 mv_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
|
||||
uniform mat4 norm_matrix;
|
||||
uniform mat4 lightSpaceMatrix;
|
||||
uniform mat4 modelMatrix;
|
||||
out vec4 FragPosLightSpace;
|
||||
out vec3 normal;
|
||||
out vec2 tc;
|
||||
out vec3 vert_pos;
|
||||
|
||||
|
||||
void main() {
|
||||
//vec4 worldPos = modelMatrix * vec4(pos, 1.0);
|
||||
vec4 worldPos = modelMatrix * vec4(pos, 1.0);
|
||||
FragPosLightSpace = lightSpaceMatrix * worldPos;
|
||||
vec4 viewPos = mv_matrix * vec4(pos, 1.0);
|
||||
tc = texCoord;
|
||||
vert_pos = pos;
|
||||
//normal = normalize(mat3(norm_matrix) * aNormal);
|
||||
normal = normalize(mat3(norm_matrix) * aNormal);
|
||||
gl_Position = proj_matrix * viewPos;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
#version 460
|
||||
|
||||
in vec2 tc;
|
||||
in vec3 normal;
|
||||
in vec3 vert_pos;
|
||||
in vec4 FragPosLightSpace;
|
||||
out vec4 color;
|
||||
|
||||
layout (binding = 0) uniform sampler2D shadowMap;
|
||||
layout (binding = 1) uniform sampler2D samp;
|
||||
|
||||
uniform float ambientStrength;
|
||||
uniform vec3 sunlightColor;
|
||||
uniform vec3 ambientColor;
|
||||
uniform vec3 sunlightDir;
|
||||
uniform bool shader_on;
|
||||
uniform int shadowMode;
|
||||
uniform float lightSizeUV;
|
||||
uniform float minRadius;
|
||||
uniform float maxRadius;
|
||||
|
||||
#include "shadow.glsl"
|
||||
|
||||
void main() {
|
||||
vec4 objectColor = texture(samp, tc);
|
||||
|
||||
if (!shader_on) {
|
||||
color = objectColor;
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 lightDir = normalize(-sunlightDir);
|
||||
|
||||
vec3 norm = normalize(normal);
|
||||
|
||||
vec3 ambient = ambientStrength * ambientColor;
|
||||
|
||||
float diff = max(dot(norm, lightDir), 0.0);
|
||||
|
||||
vec3 diffuse = diff * sunlightColor;
|
||||
|
||||
float shadow = ShadowCalculation(FragPosLightSpace, norm, lightDir);
|
||||
//float shadow = 0.0;
|
||||
//color = vec4(vec3(shadow),1);
|
||||
//color = vec4(vec3(diff),1);
|
||||
color = vec4((ambient + (1.0 - shadow) * (diffuse)) * objectColor.rgb, objectColor.a);
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec3 pos;
|
||||
layout (location = 1) in vec2 texCoord;
|
||||
layout (location = 2) in vec3 aNormal;
|
||||
layout (location = 3) in vec3 aTangent;
|
||||
|
||||
uniform mat4 mv_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
uniform mat4 norm_matrix;
|
||||
uniform mat4 lightSpaceMatrix;
|
||||
uniform mat4 modelMatrix;
|
||||
out vec4 FragPosLightSpace;
|
||||
out vec3 normal;
|
||||
out vec2 tc;
|
||||
out vec3 vert_pos;
|
||||
|
||||
|
||||
void main() {
|
||||
vec4 worldPos = modelMatrix * vec4(pos, 1.0);
|
||||
FragPosLightSpace = lightSpaceMatrix * worldPos;
|
||||
vec4 viewPos = mv_matrix * vec4(pos, 1.0);
|
||||
tc = texCoord;
|
||||
vert_pos = pos;
|
||||
normal = normalize(mat3(norm_matrix) * aNormal);
|
||||
gl_Position = proj_matrix * viewPos;
|
||||
}
|
||||
@@ -4,16 +4,20 @@
|
||||
namespace Cubed {
|
||||
|
||||
struct AABB {
|
||||
glm::vec3 min{0.0f, 0.0f, 0.0f};
|
||||
glm::vec3 max{0.0f, 0.0f, 0.0f};
|
||||
glm::vec3 center{0.0f};
|
||||
glm::vec3 half{0.0f};
|
||||
|
||||
AABB(glm::vec3 min_point, glm::vec3 max_point)
|
||||
: min(min_point), max(max_point) {}
|
||||
AABB(glm::vec3 center_point, glm::vec3 half_size)
|
||||
: center(center_point), half(half_size) {}
|
||||
|
||||
glm::vec3 min() const { return center - half; }
|
||||
|
||||
glm::vec3 max() const { return center + half; }
|
||||
|
||||
bool intersects(const AABB& other) const {
|
||||
return (min.x <= other.max.x && max.x >= other.min.x) &&
|
||||
(min.y <= other.max.y && max.y >= other.min.y) &&
|
||||
(min.z <= other.max.z && max.z >= other.min.z);
|
||||
return (glm::abs(center.x - other.center.x) <= half.x + other.half.x) &&
|
||||
(glm::abs(center.y - other.center.y) <= half.y + other.half.y) &&
|
||||
(glm::abs(center.z - other.center.z) <= half.z + other.half.z);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
27
include/Cubed/gameplay/chunk.hpp
Normal file
27
include/Cubed/gameplay/chunk.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <tuple>
|
||||
namespace Cubed {
|
||||
class Chunk {
|
||||
public:
|
||||
Chunk() = default;
|
||||
Chunk(const Chunk&) = delete;
|
||||
Chunk(Chunk&&) = delete;
|
||||
Chunk& operator=(const Chunk&) = delete;
|
||||
Chunk& operator=(Chunk&&) = delete;
|
||||
virtual ~Chunk() = default;
|
||||
static int index(int x, int y, int z);
|
||||
static int index(const glm::vec3& pos);
|
||||
static std::tuple<int, int, int> world_to_block(int world_x, int world_y,
|
||||
int world_z, int chunk_x,
|
||||
int chunk_z);
|
||||
static std::tuple<int, int, int> world_to_block(const glm::ivec3& block_pos,
|
||||
ChunkPos chunk_pos);
|
||||
static std::tuple<int, int, int> block_to_world(int x, int y, int z,
|
||||
int chunk_x, int chunk_z);
|
||||
static std::tuple<int, int, int> block_to_world(const glm::ivec3& block_pos,
|
||||
ChunkPos chunk_pos);
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "Cubed/constants.hpp"
|
||||
#include "Cubed/gameplay/biome.hpp"
|
||||
#include "Cubed/gameplay/block.hpp"
|
||||
#include "Cubed/gameplay/chunk.hpp"
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/vertex_data.hpp"
|
||||
#include "world/chunk_data.pb.h"
|
||||
@@ -26,7 +27,7 @@ struct ChunkRenderSnapshot {
|
||||
glm::vec3 center;
|
||||
glm::vec3 half_extents;
|
||||
};
|
||||
class ClientChunk {
|
||||
class ClientChunk : public Chunk {
|
||||
public:
|
||||
ClientChunk(ClientWorld& world);
|
||||
~ClientChunk();
|
||||
@@ -35,17 +36,6 @@ public:
|
||||
ClientChunk(ClientChunk&&) noexcept;
|
||||
ClientChunk& operator=(ClientChunk&&) noexcept;
|
||||
|
||||
static int index(int x, int y, int z);
|
||||
static int index(const glm::vec3& pos);
|
||||
static std::tuple<int, int, int> world_to_block(int world_x, int world_y,
|
||||
int world_z, int chunk_x,
|
||||
int chunk_z);
|
||||
static std::tuple<int, int, int> world_to_block(const glm::ivec3& block_pos,
|
||||
ChunkPos chunk_pos);
|
||||
static std::tuple<int, int, int> block_to_world(int x, int y, int z,
|
||||
int chunk_x, int chunk_z);
|
||||
static std::tuple<int, int, int> block_to_world(const glm::ivec3& block_pos,
|
||||
ChunkPos chunk_pos);
|
||||
BiomeType get_biome() const;
|
||||
ChunkPos get_chunk_pos() const;
|
||||
const std::vector<BlockType>& get_chunk_blocks() const;
|
||||
|
||||
@@ -8,32 +8,19 @@
|
||||
#include "Cubed/gameplay/client_player.hpp"
|
||||
#include "Cubed/gameplay/game_time.hpp"
|
||||
#include "Cubed/gameplay/network_client.hpp"
|
||||
#include "Cubed/gameplay/world.hpp"
|
||||
#include "Cubed/input/event.hpp"
|
||||
#include "Cubed/tools/cubed_random.hpp"
|
||||
#include "Cubed/tools/priority_thread_pool.hpp"
|
||||
|
||||
#include <absl/container/flat_hash_set.h>
|
||||
#include <deque>
|
||||
#include <entt/entt.hpp>
|
||||
#include <tbb/concurrent_hash_map.h>
|
||||
#include <tbb/concurrent_queue.h>
|
||||
#include <tbb/concurrent_unordered_map.h>
|
||||
namespace Cubed {
|
||||
|
||||
struct PlayerInfo {
|
||||
std::string name;
|
||||
std::string uuid;
|
||||
glm::vec3 render_pos;
|
||||
glm::vec3 target_pos;
|
||||
float render_yaw;
|
||||
float yaw;
|
||||
float render_pitch;
|
||||
float pitch;
|
||||
Gait gait;
|
||||
float angle = 0.0f;
|
||||
float walk_time = 0.0f;
|
||||
float moving_time = 0.0f;
|
||||
};
|
||||
|
||||
struct PlayerRenderData {
|
||||
std::string name;
|
||||
std::string uuid;
|
||||
@@ -44,21 +31,26 @@ struct PlayerRenderData {
|
||||
float angle;
|
||||
};
|
||||
class WorldScene;
|
||||
class ClientWorld {
|
||||
class ClientWorld : public World {
|
||||
public:
|
||||
ClientWorld(const ClientWorld&) = delete;
|
||||
ClientWorld(ClientWorld&&) = delete;
|
||||
ClientWorld& operator=(const ClientWorld&) = delete;
|
||||
ClientWorld& operator=(ClientWorld&&) = delete;
|
||||
ClientWorld(AudioEngine& auido, Config& config, WorldScene& scene);
|
||||
~ClientWorld();
|
||||
void init(std::string_view player_name,
|
||||
std::shared_ptr<NetworkClient> client);
|
||||
void update(float delta_time);
|
||||
void update(float dt);
|
||||
void update_players(float dt);
|
||||
bool handle_event(const Event& e);
|
||||
const std::optional<LookBlock>& get_look_block_pos() const;
|
||||
ClientPlayer& get_player();
|
||||
const ClientPlayer& get_player() const;
|
||||
int get_block(const glm::ivec3& block_pos) const;
|
||||
bool is_solid(const glm::ivec3& block_pos) const;
|
||||
bool can_pass_block(const glm::ivec3& block_pos) const;
|
||||
BlockType get_block_tpye(const glm::ivec3& block_pos) const;
|
||||
int get_block(const glm::ivec3& block_pos) const override;
|
||||
bool is_solid(const glm::ivec3& block_pos) const override;
|
||||
bool can_pass_block(const glm::ivec3& block_pos) const override;
|
||||
BlockType get_block_tpye(const glm::ivec3& block_pos) const override;
|
||||
|
||||
void rebuild_world();
|
||||
|
||||
@@ -99,7 +91,7 @@ public:
|
||||
void request_exit();
|
||||
bool is_receive_exit();
|
||||
int chunk_size() const;
|
||||
static AABB get_block_aabb(const glm::ivec3& pos);
|
||||
|
||||
AudioEngine& get_audio();
|
||||
const AudioEngine& get_audio() const;
|
||||
Config& get_config();
|
||||
@@ -110,7 +102,8 @@ public:
|
||||
void send_chat_message(ChatMessage& message);
|
||||
void receive_voice_message(VoiceMsg& msg);
|
||||
bool enable_voice_chat() const;
|
||||
|
||||
const entt::registry& get_registry();
|
||||
int get_per_tick_time() const override;
|
||||
template <typename Fn>
|
||||
void register_ticktimer(std::string_view id, TickType threshold, Fn&& f) {
|
||||
m_ticktimers.emplace(
|
||||
@@ -118,6 +111,17 @@ public:
|
||||
std::forward_as_tuple(threshold, std::forward<Fn>(f)));
|
||||
}
|
||||
|
||||
template <typename... Components>
|
||||
entt::entity create_entity(Components&&... components) {
|
||||
auto e = m_registry.create();
|
||||
|
||||
(m_registry.emplace<std::remove_cvref_t<Components>>(
|
||||
e, std::forward<Components>(components)),
|
||||
...);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
private:
|
||||
struct VoiceMessage {
|
||||
std::string data;
|
||||
@@ -136,7 +140,6 @@ private:
|
||||
ChunkPos::TBBHash>;
|
||||
using ChunkPosSet = absl::flat_hash_set<ChunkPos, ChunkPos::Hash>;
|
||||
using ChunkPosVector = std::vector<ChunkPos>;
|
||||
using OtherPlayerHashMap = std::unordered_map<std::string, PlayerInfo>;
|
||||
using chunk_acc = ChunkHashMap::accessor;
|
||||
using chunk_cacc = ChunkHashMap::const_accessor;
|
||||
|
||||
@@ -147,8 +150,11 @@ private:
|
||||
|
||||
static constexpr int WORLD_EXIT_TIMEOUT = 200;
|
||||
static constexpr int MAX_UPLOAD_CHUNK_SUM = 16;
|
||||
|
||||
entt::registry m_registry;
|
||||
|
||||
ClientPlayer m_player;
|
||||
OtherPlayerHashMap m_player_info;
|
||||
std::unordered_map<std::string, entt::entity> m_player_entities;
|
||||
ChunkHashMap m_chunks;
|
||||
AudioEngine& m_audio;
|
||||
Config& m_config;
|
||||
@@ -156,7 +162,7 @@ private:
|
||||
std::vector<glm::vec4> m_planes;
|
||||
std::jthread m_client_thread;
|
||||
|
||||
mutable std::shared_mutex m_player_info_mutex;
|
||||
mutable std::shared_mutex m_registry_mutex;
|
||||
|
||||
tbb::concurrent_queue<std::unique_ptr<ClientChunk>> m_pending_upload_queue;
|
||||
tbb::concurrent_queue<ChunkPos> m_dirty_chunk_queue;
|
||||
@@ -176,6 +182,7 @@ private:
|
||||
std::atomic<int> m_rendering_distance{24};
|
||||
std::atomic<TickType> m_game_ticks{0};
|
||||
std::atomic<TickType> m_day_tick{6000};
|
||||
std::atomic<int> m_per_tick_time = DEFAULT_PER_TICK_TIME;
|
||||
std::atomic<bool> m_requesting_chunk{false};
|
||||
std::atomic<bool> m_is_rebuilding{false};
|
||||
std::atomic<int> m_chunk_task_id{0};
|
||||
|
||||
48
include/Cubed/gameplay/entity.hpp
Normal file
48
include/Cubed/gameplay/entity.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
#include "Cubed/AABB.hpp"
|
||||
#include "Cubed/gameplay/player.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <string>
|
||||
namespace Cubed {
|
||||
struct Transform {
|
||||
glm::vec3 pos{0, 0, 0};
|
||||
glm::vec3 render_pos{0, 0, 0};
|
||||
Gait gait = Gait::STOP;
|
||||
float walk_time = 0.0f;
|
||||
float moving_time = 0.0f;
|
||||
};
|
||||
|
||||
struct EntityInfo {
|
||||
std::string name;
|
||||
std::string uuid;
|
||||
};
|
||||
|
||||
struct Model {
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct Health {
|
||||
float hp = 0;
|
||||
float max_hp = 20;
|
||||
};
|
||||
|
||||
struct ViewAngles {
|
||||
float render_yaw = 0.0f;
|
||||
float yaw = 0.0f;
|
||||
float render_pitch = 0.0f;
|
||||
float pitch = 0.0f;
|
||||
float angle = 0.0f;
|
||||
};
|
||||
|
||||
struct Velocity {
|
||||
float dx = 0.0f;
|
||||
float dy = 0.0f;
|
||||
float dz = 0.0f;
|
||||
};
|
||||
|
||||
struct HitBoxes {
|
||||
std::vector<AABB> boxex;
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
24
include/Cubed/gameplay/hitbox_manager.hpp
Normal file
24
include/Cubed/gameplay/hitbox_manager.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "Cubed/AABB.hpp"
|
||||
|
||||
#include <tbb/concurrent_hash_map.h>
|
||||
namespace Cubed {
|
||||
class HitboxManager {
|
||||
public:
|
||||
HitboxManager();
|
||||
~HitboxManager();
|
||||
static HitboxManager& instance();
|
||||
|
||||
AABB get_aabb(const std::string& key);
|
||||
|
||||
static AABB aabb(const std::string& key);
|
||||
|
||||
private:
|
||||
using HitBoxMap = tbb::concurrent_hash_map<std::string, AABB>;
|
||||
using cacc = HitBoxMap::const_accessor;
|
||||
using acc = HitBoxMap::accessor;
|
||||
HitBoxMap m_hitboxes;
|
||||
|
||||
AABB load(const std::string& path);
|
||||
};
|
||||
} // namespace Cubed
|
||||
20
include/Cubed/gameplay/move_system.hpp
Normal file
20
include/Cubed/gameplay/move_system.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "Cubed/gameplay/entity.hpp"
|
||||
#include "Cubed/gameplay/world.hpp"
|
||||
|
||||
#include <entt/entt.hpp>
|
||||
namespace Cubed {
|
||||
|
||||
class MoveSystem {
|
||||
public:
|
||||
static void update(World& world, entt::registry& registry);
|
||||
|
||||
private:
|
||||
static void move_x(World& world, Transform& transform, Velocity& v,
|
||||
const EntityInfo& info);
|
||||
static void move_y(World& world, Transform& transform, Velocity& v,
|
||||
const EntityInfo& info);
|
||||
static void move_z(World& world, Transform& transform, Velocity& v,
|
||||
const EntityInfo& info);
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "Cubed/constants.hpp"
|
||||
#include "Cubed/gameplay/biome.hpp"
|
||||
#include "Cubed/gameplay/block.hpp"
|
||||
#include "Cubed/gameplay/chunk.hpp"
|
||||
#include "Cubed/gameplay/chunk_generator.hpp"
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
|
||||
@@ -11,7 +12,7 @@
|
||||
#include <tuple>
|
||||
namespace Cubed {
|
||||
class ServerWorld;
|
||||
class ServerChunk {
|
||||
class ServerChunk : public Chunk {
|
||||
public:
|
||||
ServerChunk(ServerWorld& world, ChunkPos chunk_pos,
|
||||
bool temp_chunk = false);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "Cubed/gameplay/river_worm.hpp"
|
||||
#include "Cubed/gameplay/server_chunk.hpp"
|
||||
#include "Cubed/gameplay/server_player.hpp"
|
||||
#include "Cubed/gameplay/world.hpp"
|
||||
#include "Cubed/tools/priority_thread_pool.hpp"
|
||||
#include "Cubed/tools/recent_queue.hpp"
|
||||
#include "Cubed/tools/sensitive_filter.hpp"
|
||||
@@ -25,7 +26,7 @@
|
||||
#include <vector>
|
||||
namespace Cubed {
|
||||
class Session;
|
||||
class ServerWorld {
|
||||
class ServerWorld : public World {
|
||||
public:
|
||||
enum class ThreadPoolKind { NET, GEN };
|
||||
ServerWorld(Config& config);
|
||||
@@ -85,6 +86,12 @@ public:
|
||||
void handle_chat_message(ChatMsg& msg);
|
||||
void handle_voice_message(VoiceMsg& msg);
|
||||
int chunk_size() const;
|
||||
|
||||
int get_block(const glm::ivec3& block_pos) const override;
|
||||
bool is_solid(const glm::ivec3& block_pos) const override;
|
||||
bool can_pass_block(const glm::ivec3& block_pos) const override;
|
||||
BlockType get_block_tpye(const glm::ivec3& block_pos) const override;
|
||||
int get_per_tick_time() const override;
|
||||
template <typename Fn>
|
||||
void register_timer(std::string_view id, TickType threshold, Fn&& f) {
|
||||
m_timers.emplace(std::piecewise_construct,
|
||||
@@ -119,7 +126,7 @@ private:
|
||||
using PlayerUUIDMap = tbb::concurrent_hash_map<std::string, std::string>;
|
||||
|
||||
using chunk_acc = ChunkHashMap::accessor;
|
||||
using chunk_caac = ChunkHashMap::const_accessor;
|
||||
using chunk_cacc = ChunkHashMap::const_accessor;
|
||||
|
||||
using uuid_acc = PlayerUUIDMap::accessor;
|
||||
using uuid_cacc = PlayerUUIDMap::const_accessor;
|
||||
|
||||
29
include/Cubed/gameplay/world.hpp
Normal file
29
include/Cubed/gameplay/world.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "Cubed/AABB.hpp"
|
||||
#include "Cubed/gameplay/block.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
namespace Cubed {
|
||||
class World {
|
||||
public:
|
||||
World() = default;
|
||||
World(const World&) = delete;
|
||||
World(World&&) = delete;
|
||||
World& operator=(const World&) = delete;
|
||||
World& operator=(World&&) = delete;
|
||||
virtual ~World() = default;
|
||||
|
||||
virtual int get_block(const glm::ivec3& block_pos) const = 0;
|
||||
virtual bool is_solid(const glm::ivec3& block_pos) const = 0;
|
||||
virtual bool can_pass_block(const glm::ivec3& block_pos) const = 0;
|
||||
virtual BlockType get_block_tpye(const glm::ivec3& block_pos) const = 0;
|
||||
virtual int get_per_tick_time() const = 0;
|
||||
|
||||
static AABB get_block_aabb(const glm::ivec3& pos) {
|
||||
return {glm::vec3{static_cast<float>(pos.x) + 0.5f,
|
||||
static_cast<float>(pos.y) + 0.5f,
|
||||
static_cast<float>(pos.z) + 0.5f},
|
||||
glm::vec3{0.5f, 0.5f, 0.5f}};
|
||||
}
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -13,10 +13,13 @@ public:
|
||||
void render_model(const std::string& name, const glm::vec3& pos,
|
||||
Camera& camera);
|
||||
|
||||
void shadow_pass(const std::string& name, const glm::vec3& pos,
|
||||
Camera& camera);
|
||||
|
||||
private:
|
||||
Renderer& m_renderer;
|
||||
void render_node(const ModelNode& node, const glm::mat4& parent,
|
||||
const glm::mat4& view, const Shader& shader);
|
||||
void render_mesh(const Mesh& mesh);
|
||||
const glm::mat4& view, const Shader& shader, bool shadow);
|
||||
void render_mesh(const Mesh& mesh, bool shadow);
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -14,8 +14,7 @@ public:
|
||||
~PlayerRenderer();
|
||||
void init();
|
||||
void render(const Shader& shader, ClientWorld& world);
|
||||
void shadow_render(const Shader& shader, glm::mat4& light_matrix,
|
||||
ClientWorld& world);
|
||||
void shadow_render(const Shader& shader, ClientWorld& world);
|
||||
|
||||
private:
|
||||
struct PlayerVertex {
|
||||
|
||||
@@ -82,10 +82,8 @@ public:
|
||||
|
||||
bool handle_event(const Event& e);
|
||||
|
||||
void render_model(const std::string& name, const glm::vec3& pos,
|
||||
Camera& camera);
|
||||
|
||||
ModelManager& model_manager();
|
||||
ModelRender& model_renderer();
|
||||
|
||||
private:
|
||||
TextureManager& m_texture_manager;
|
||||
|
||||
@@ -132,7 +132,8 @@ private:
|
||||
|
||||
void render_underwater(ClientWorld& world);
|
||||
void render_outline(ClientWorld& world);
|
||||
void render_player(ClientWorld& world);
|
||||
void shadow_entity(ClientWorld& world, const glm::mat4& light_matrix);
|
||||
void render_entity(ClientWorld& world);
|
||||
|
||||
void render_normal_block(const glm::mat4& model_mat,
|
||||
const glm::mat4& mv_mat, const glm::mat4& norm_mat,
|
||||
|
||||
@@ -95,4 +95,7 @@ target_sources(${PROJECT_NAME}
|
||||
tools/model_loader.cpp
|
||||
render/model_manager.cpp
|
||||
render/model_renderer.cpp
|
||||
gameplay/chunk.cpp
|
||||
gameplay/move_system.cpp
|
||||
gameplay/hitbox_manager.cpp
|
||||
)
|
||||
49
src/gameplay/chunk.cpp
Normal file
49
src/gameplay/chunk.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "Cubed/gameplay/chunk.hpp"
|
||||
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
int Chunk::index(int x, int y, int z) {
|
||||
ASSERT(!(x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y ||
|
||||
z >= CHUNK_SIZE));
|
||||
if ((x * WORLD_SIZE_Y + y) * CHUNK_SIZE + z < 0 ||
|
||||
(x * WORLD_SIZE_Y + y) * CHUNK_SIZE + z >=
|
||||
CHUNK_SIZE * CHUNK_SIZE * WORLD_SIZE_Y) {
|
||||
Logger::error("block pos x {} y {} z {} range error", x, y, z);
|
||||
ASSERT(0);
|
||||
}
|
||||
return (x * WORLD_SIZE_Y + y) * CHUNK_SIZE + z;
|
||||
}
|
||||
|
||||
int Chunk::index(const glm::vec3& pos) {
|
||||
return Chunk::index(pos.x, pos.y, pos.z);
|
||||
}
|
||||
std::tuple<int, int, int> Chunk::world_to_block(int world_x, int world_y,
|
||||
int world_z, int chunk_x,
|
||||
int chunk_z) {
|
||||
int x, y, z;
|
||||
y = world_y;
|
||||
x = world_x - chunk_x * CHUNK_SIZE;
|
||||
z = world_z - chunk_z * CHUNK_SIZE;
|
||||
return {x, y, z};
|
||||
}
|
||||
|
||||
std::tuple<int, int, int> Chunk::world_to_block(const glm::ivec3& block_pos,
|
||||
ChunkPos chunk_pos) {
|
||||
return world_to_block(block_pos.x, block_pos.y, block_pos.z, chunk_pos.x,
|
||||
chunk_pos.z);
|
||||
}
|
||||
|
||||
std::tuple<int, int, int> Chunk::block_to_world(int x, int y, int z,
|
||||
int chunk_x, int chunk_z) {
|
||||
int world_x = x + chunk_x * CHUNK_SIZE;
|
||||
int world_z = z + chunk_z * CHUNK_SIZE;
|
||||
int world_y = y;
|
||||
return {world_x, world_y, world_z};
|
||||
}
|
||||
std::tuple<int, int, int> Chunk::block_to_world(const glm::ivec3& block_pos,
|
||||
ChunkPos chunk_pos) {
|
||||
return block_to_world(block_pos.x, block_pos.y, block_pos.z, chunk_pos.x,
|
||||
chunk_pos.z);
|
||||
}
|
||||
} // namespace Cubed
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Cubed/gameplay/client_chunk.hpp"
|
||||
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
using OptionalBlockVectorArray =
|
||||
std::array<std::optional<std::vector<BlockType>>, 4>;
|
||||
@@ -128,49 +126,6 @@ ClientChunk& ClientChunk::operator=(ClientChunk&& other) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
int ClientChunk::index(int x, int y, int z) {
|
||||
ASSERT(!(x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y ||
|
||||
z >= CHUNK_SIZE));
|
||||
if ((x * WORLD_SIZE_Y + y) * CHUNK_SIZE + z < 0 ||
|
||||
(x * WORLD_SIZE_Y + y) * CHUNK_SIZE + z >=
|
||||
CHUNK_SIZE * CHUNK_SIZE * WORLD_SIZE_Y) {
|
||||
Logger::error("block pos x {} y {} z {} range error", x, y, z);
|
||||
ASSERT(0);
|
||||
}
|
||||
return (x * WORLD_SIZE_Y + y) * CHUNK_SIZE + z;
|
||||
}
|
||||
|
||||
int ClientChunk::index(const glm::vec3& pos) {
|
||||
return ClientChunk::index(pos.x, pos.y, pos.z);
|
||||
}
|
||||
std::tuple<int, int, int> ClientChunk::world_to_block(int world_x, int world_y,
|
||||
int world_z, int chunk_x,
|
||||
int chunk_z) {
|
||||
int x, y, z;
|
||||
y = world_y;
|
||||
x = world_x - chunk_x * CHUNK_SIZE;
|
||||
z = world_z - chunk_z * CHUNK_SIZE;
|
||||
return {x, y, z};
|
||||
}
|
||||
|
||||
std::tuple<int, int, int>
|
||||
ClientChunk::world_to_block(const glm::ivec3& block_pos, ChunkPos chunk_pos) {
|
||||
return world_to_block(block_pos.x, block_pos.y, block_pos.z, chunk_pos.x,
|
||||
chunk_pos.z);
|
||||
}
|
||||
|
||||
std::tuple<int, int, int>
|
||||
ClientChunk::block_to_world(int x, int y, int z, int chunk_x, int chunk_z) {
|
||||
int world_x = x + chunk_x * CHUNK_SIZE;
|
||||
int world_z = z + chunk_z * CHUNK_SIZE;
|
||||
int world_y = y;
|
||||
return {world_x, world_y, world_z};
|
||||
}
|
||||
std::tuple<int, int, int>
|
||||
ClientChunk::block_to_world(const glm::ivec3& block_pos, ChunkPos chunk_pos) {
|
||||
return block_to_world(block_pos.x, block_pos.y, block_pos.z, chunk_pos.x,
|
||||
chunk_pos.z);
|
||||
}
|
||||
BiomeType ClientChunk::get_biome() const { return m_biome.load(); }
|
||||
|
||||
ChunkPos ClientChunk::get_chunk_pos() const { return m_chunk_pos; }
|
||||
|
||||
@@ -12,14 +12,11 @@ ClientPlayer::ClientPlayer(ClientWorld& world) : m_world(world) {}
|
||||
ClientPlayer::~ClientPlayer() {}
|
||||
|
||||
AABB ClientPlayer::get_aabb(const glm::vec3& pos) {
|
||||
float half_width = M_SIZE.x / 2.0f;
|
||||
float half_depth = M_SIZE.z / 2.0f;
|
||||
glm::vec3 half = M_SIZE * 0.5f;
|
||||
|
||||
glm::vec3 min{pos.x - half_width, pos.y, pos.z - half_depth};
|
||||
glm::vec3 center{pos.x, pos.y + half.y, pos.z};
|
||||
|
||||
glm::vec3 max{pos.x + half_width, pos.y + M_SIZE.y, pos.z + half_depth};
|
||||
|
||||
return AABB{min, max};
|
||||
return AABB{center, half};
|
||||
}
|
||||
const glm::vec3& ClientPlayer::get_front() const { return m_front; }
|
||||
|
||||
@@ -442,12 +439,15 @@ void ClientPlayer::update_x_move(glm::vec3& player_pos) {
|
||||
return;
|
||||
}
|
||||
AABB player_box = get_aabb(player_pos);
|
||||
int minx = std::floor(player_box.min.x);
|
||||
int maxx = std::floor(player_box.max.x);
|
||||
int miny = std::floor(player_box.min.y);
|
||||
int maxy = std::floor(player_box.max.y);
|
||||
int minz = std::floor(player_box.min.z);
|
||||
int maxz = std::floor(player_box.max.z);
|
||||
glm::vec3 min = player_box.min();
|
||||
glm::vec3 max = player_box.max();
|
||||
|
||||
int minx = std::floor(min.x);
|
||||
int maxx = std::floor(max.x);
|
||||
int miny = std::floor(min.y);
|
||||
int maxy = std::floor(max.y);
|
||||
int minz = std::floor(min.z);
|
||||
int maxz = std::floor(max.z);
|
||||
|
||||
for (int x = minx; x <= maxx; ++x) {
|
||||
for (int y = miny; y <= maxy; ++y) {
|
||||
@@ -472,12 +472,15 @@ void ClientPlayer::update_y_move(glm::vec3& player_pos) {
|
||||
return;
|
||||
}
|
||||
AABB player_box = get_aabb(player_pos);
|
||||
int minx = std::floor(player_box.min.x);
|
||||
int maxx = std::floor(player_box.max.x);
|
||||
int miny = std::floor(player_box.min.y);
|
||||
int maxy = std::floor(player_box.max.y);
|
||||
int minz = std::floor(player_box.min.z);
|
||||
int maxz = std::floor(player_box.max.z);
|
||||
glm::vec3 min = player_box.min();
|
||||
glm::vec3 max = player_box.max();
|
||||
|
||||
int minx = std::floor(min.x);
|
||||
int maxx = std::floor(max.x);
|
||||
int miny = std::floor(min.y);
|
||||
int maxy = std::floor(max.y);
|
||||
int minz = std::floor(min.z);
|
||||
int maxz = std::floor(max.z);
|
||||
|
||||
for (int x = minx; x <= maxx; ++x) {
|
||||
for (int y = miny; y <= maxy; ++y) {
|
||||
@@ -506,12 +509,15 @@ void ClientPlayer::update_z_move(glm::vec3& player_pos) {
|
||||
return;
|
||||
}
|
||||
AABB player_box = get_aabb(player_pos);
|
||||
int minx = std::floor(player_box.min.x);
|
||||
int maxx = std::floor(player_box.max.x);
|
||||
int miny = std::floor(player_box.min.y);
|
||||
int maxy = std::floor(player_box.max.y);
|
||||
int minz = std::floor(player_box.min.z);
|
||||
int maxz = std::floor(player_box.max.z);
|
||||
glm::vec3 min = player_box.min();
|
||||
glm::vec3 max = player_box.max();
|
||||
|
||||
int minx = std::floor(min.x);
|
||||
int maxx = std::floor(max.x);
|
||||
int miny = std::floor(min.y);
|
||||
int maxy = std::floor(max.y);
|
||||
int minz = std::floor(min.z);
|
||||
int maxz = std::floor(max.z);
|
||||
|
||||
for (int x = minx; x <= maxx; ++x) {
|
||||
for (int y = miny; y <= maxy; ++y) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/gameplay/chunk_generator.hpp"
|
||||
#include "Cubed/gameplay/entity.hpp"
|
||||
#include "Cubed/gameplay/game_time.hpp"
|
||||
#include "Cubed/gameplay/packet.hpp"
|
||||
#include "Cubed/scene/world_scene.hpp"
|
||||
@@ -135,7 +136,6 @@ void ClientWorld::rebuild_world() {
|
||||
BlockType ClientWorld::get_block_tpye(const glm::ivec3& block_pos) const {
|
||||
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
||||
chunk_cacc cacc;
|
||||
;
|
||||
|
||||
if (!m_chunks.find(cacc, ChunkPos{chunk_x, chunk_z})) {
|
||||
// Logger::error("Can't Find Block {} {} {}", block_pos.x, block_pos.y,
|
||||
@@ -295,10 +295,13 @@ void ClientWorld::report_block_change(const glm::ivec3& pos,
|
||||
unsigned id) const {
|
||||
if (id != 0) {
|
||||
AABB block_box = get_block_aabb(pos);
|
||||
std::shared_lock lock(m_player_info_mutex);
|
||||
std::shared_lock lock(m_registry_mutex);
|
||||
|
||||
for (auto& [uuid, player] : m_player_info) {
|
||||
AABB box = ClientPlayer::get_aabb(player.target_pos);
|
||||
for (auto& [key, player] : m_player_entities) {
|
||||
auto [transform, entity_info] =
|
||||
m_registry.get<Transform, EntityInfo>(player);
|
||||
|
||||
AABB box = ClientPlayer::get_aabb(transform.pos);
|
||||
if (box.intersects(block_box)) {
|
||||
return;
|
||||
}
|
||||
@@ -330,20 +333,22 @@ void ClientWorld::receive_remote_player(const PlayerInfoRsp& rsp) {
|
||||
auto pitch = rsp.pitch();
|
||||
auto yaw = rsp.yaw();
|
||||
{
|
||||
std::lock_guard lock(m_player_info_mutex);
|
||||
std::lock_guard lock(m_registry_mutex);
|
||||
glm::vec3 pos{rsp.pos().x(), rsp.pos().y(), rsp.pos().z()};
|
||||
auto it = m_player_info.find(rsp.uuid());
|
||||
if (it == m_player_info.end()) {
|
||||
m_player_info.emplace(
|
||||
std::piecewise_construct, std::forward_as_tuple(rsp.uuid()),
|
||||
std::forward_as_tuple(rsp.name(), rsp.uuid(), pos, pos, yaw,
|
||||
yaw, pitch, pitch,
|
||||
get_gait_from_id(rsp.gait())));
|
||||
auto it = m_player_entities.find(rsp.uuid());
|
||||
if (it == m_player_entities.end()) {
|
||||
auto entity =
|
||||
create_entity(EntityInfo{rsp.name(), rsp.uuid()},
|
||||
Transform{pos, pos, get_gait_from_id(rsp.gait())},
|
||||
ViewAngles{yaw, yaw, pitch, pitch});
|
||||
m_player_entities.try_emplace(rsp.uuid(), entity);
|
||||
} else {
|
||||
it->second.target_pos = pos;
|
||||
it->second.yaw = yaw;
|
||||
it->second.pitch = pitch;
|
||||
it->second.gait = get_gait_from_id(rsp.gait());
|
||||
auto& transform = m_registry.get<Transform>(it->second);
|
||||
transform.pos = pos;
|
||||
transform.gait = get_gait_from_id(rsp.gait());
|
||||
auto& view_angles = m_registry.get<ViewAngles>(it->second);
|
||||
view_angles.yaw = yaw;
|
||||
view_angles.pitch = pitch;
|
||||
}
|
||||
// Logger::info("Player {} pos Update", rsp.name());
|
||||
}
|
||||
@@ -359,11 +364,13 @@ void ClientWorld::receive_player_logout(const LogoutRsp& rsp) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
std::lock_guard lock(m_player_info_mutex);
|
||||
int sum = m_player_info.erase(rsp.uuid());
|
||||
if (sum == 0) {
|
||||
std::lock_guard lock(m_registry_mutex);
|
||||
auto it = m_player_entities.find(rsp.uuid());
|
||||
if (it == m_player_entities.end()) {
|
||||
Logger::warn("Player {} not find", rsp.uuid());
|
||||
} else {
|
||||
m_registry.destroy(it->second);
|
||||
m_player_entities.erase(rsp.uuid());
|
||||
Logger::info("Player {} erase", rsp.uuid());
|
||||
}
|
||||
}
|
||||
@@ -473,6 +480,8 @@ void ClientWorld::init(std::string_view player_name,
|
||||
Logger::info("Send Login Request");
|
||||
m_client->send(make_packet(req), 0);
|
||||
m_audio.play_bgm();
|
||||
create_entity(Transform{glm::vec3{0.0f, 100.0f, 0.0f}},
|
||||
Model{"model/creature/pig.glb"});
|
||||
}
|
||||
|
||||
void ClientWorld::receive_login_rsp(LoginRsp& rsp) {
|
||||
@@ -496,7 +505,7 @@ void ClientWorld::start_client_thread(std::string_view uuid) {
|
||||
// Wait for 20 ticks, after the server's central chunk is generated, then
|
||||
// request chunks
|
||||
|
||||
std::this_thread::sleep_for(milliseconds(20 * DEFAULT_PER_TICK_TIME));
|
||||
std::this_thread::sleep_for(milliseconds(20 * m_per_tick_time));
|
||||
|
||||
request_chunk();
|
||||
}
|
||||
@@ -548,7 +557,7 @@ void ClientWorld::client_run(std::stop_token stoken) {
|
||||
Logger::info("Client Thread Started");
|
||||
using Clock = std::chrono::steady_clock;
|
||||
|
||||
constexpr auto TICK = std::chrono::milliseconds(DEFAULT_PER_TICK_TIME);
|
||||
const auto TICK = std::chrono::milliseconds(m_per_tick_time);
|
||||
|
||||
auto next = Clock::now();
|
||||
while (!stoken.stop_requested()) {
|
||||
@@ -721,16 +730,6 @@ bool ClientWorld::is_receive_exit() { return m_receive_exit; }
|
||||
|
||||
int ClientWorld::chunk_size() const { return m_chunks.size(); }
|
||||
|
||||
AABB ClientWorld::get_block_aabb(const glm::ivec3& pos) {
|
||||
auto x = pos.x;
|
||||
auto y = pos.y;
|
||||
auto z = pos.z;
|
||||
return {glm::vec3{static_cast<float>(x), static_cast<float>(y),
|
||||
static_cast<float>(z)},
|
||||
glm::vec3{static_cast<float>(x + 1), static_cast<float>(y + 1),
|
||||
static_cast<float>(z + 1)}};
|
||||
}
|
||||
|
||||
AudioEngine& ClientWorld::get_audio() { return m_audio; }
|
||||
const AudioEngine& ClientWorld::get_audio() const { return m_audio; }
|
||||
Config& ClientWorld::get_config() { return m_config; }
|
||||
@@ -749,7 +748,7 @@ void ClientWorld::request_exit() {
|
||||
if (m_client->is_connect_error() || m_exit_direct) {
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(milliseconds(DEFAULT_PER_TICK_TIME));
|
||||
std::this_thread::sleep_for(milliseconds(m_per_tick_time));
|
||||
++cnt;
|
||||
if (cnt >= WORLD_EXIT_TIMEOUT) {
|
||||
Logger::warn("Can't Receive Server Exit Sign");
|
||||
@@ -773,6 +772,8 @@ void ClientWorld::receive_voice_message(VoiceMsg& msg) {
|
||||
m_voice_queue.emplace(msg.opus_data(), pos);
|
||||
}
|
||||
bool ClientWorld::enable_voice_chat() const { return m_voice_chat.load(); }
|
||||
const entt::registry& ClientWorld::get_registry() { return m_registry; }
|
||||
int ClientWorld::get_per_tick_time() const { return m_per_tick_time; }
|
||||
void ClientWorld::send_chat_message(ChatMessage& message) {
|
||||
Arena arena;
|
||||
auto msg = Arena::Create<ChatMsg>(&arena);
|
||||
@@ -852,91 +853,7 @@ void ClientWorld::update(float delta_time) {
|
||||
}
|
||||
|
||||
m_render_player_data.clear();
|
||||
{
|
||||
std::lock_guard lock(m_player_info_mutex);
|
||||
for (auto& [uuid, player] : m_player_info) {
|
||||
player.render_pos =
|
||||
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;
|
||||
}
|
||||
player.render_yaw = glm::mix(player.render_yaw, player.yaw, 0.15);
|
||||
player.render_pitch =
|
||||
glm::mix(player.render_pitch, player.pitch, 0.15);
|
||||
|
||||
if (player.gait == Gait::WALK || player.gait == Gait::RUN) {
|
||||
|
||||
player.walk_time += delta_time;
|
||||
|
||||
float speed = player.gait == Gait::RUN ? 14.0f : 8.0f;
|
||||
float amp = player.gait == Gait::RUN ? 50.0f : 35.0f;
|
||||
// float amp = 90.0f;
|
||||
player.angle =
|
||||
glm::sin(player.walk_time * speed) * glm::radians(amp);
|
||||
} else if (player.gait == Gait::STOP) {
|
||||
float t = glm::clamp(delta_time * 10.0f, 0.0f, 1.0f);
|
||||
player.angle = glm::mix(player.angle, 0.0f, t);
|
||||
}
|
||||
|
||||
// walking sound
|
||||
if (player.gait == Gait::STOP) {
|
||||
player.moving_time = 0.0f;
|
||||
} else {
|
||||
player.moving_time += delta_time;
|
||||
}
|
||||
auto play_walk_sound = [&]() {
|
||||
glm::ivec3 block = glm::floor(player.render_pos);
|
||||
block.y -= 1;
|
||||
BlockType id = get_block_tpye(block);
|
||||
if (id == 0) {
|
||||
return;
|
||||
}
|
||||
std::string name = BlockManager::name_form_id(id);
|
||||
std::string sound = "block/" + name + "/walk.ogg";
|
||||
m_audio.play_3d(sound, player.render_pos);
|
||||
};
|
||||
if (player.gait == Gait::WALK) {
|
||||
if (player.moving_time >= ClientPlayer::WALK_SOUND_INTERVAL) {
|
||||
player.moving_time = 0.0f;
|
||||
play_walk_sound();
|
||||
}
|
||||
}
|
||||
if (player.gait == Gait::RUN) {
|
||||
if (player.moving_time >= ClientPlayer::RUN_SOUND_INTERVAL) {
|
||||
player.moving_time = 0.0f;
|
||||
play_walk_sound();
|
||||
}
|
||||
}
|
||||
|
||||
m_render_player_data.emplace_back(
|
||||
player.name, player.uuid, player.render_pos, player.render_yaw,
|
||||
player.render_pitch, player.gait, player.angle);
|
||||
}
|
||||
{
|
||||
auto gait = m_player.get_gait();
|
||||
auto& walk_time = m_player.walk_time();
|
||||
auto& angle = m_player.angle();
|
||||
if (gait == Gait::WALK || gait == Gait::RUN) {
|
||||
|
||||
walk_time += delta_time;
|
||||
|
||||
float speed = gait == Gait::RUN ? 14.0f : 8.0f;
|
||||
float amp = gait == Gait::RUN ? 50.0f : 35.0f;
|
||||
// float amp = 90.0f;
|
||||
angle = glm::sin(walk_time * speed) * glm::radians(amp);
|
||||
} else if (gait == Gait::STOP) {
|
||||
float t = glm::clamp(delta_time * 10.0f, 0.0f, 1.0f);
|
||||
angle = glm::mix(angle, 0.0f, t);
|
||||
}
|
||||
|
||||
m_render_player_data.emplace_back(
|
||||
m_player.get_name(), m_player.get_uuid(),
|
||||
m_player.get_player_pos(), m_player.yaw(), m_player.pitch(),
|
||||
m_player.get_gait(), m_player.angle());
|
||||
}
|
||||
}
|
||||
update_players(delta_time);
|
||||
|
||||
// sound
|
||||
PendingSound pending_sound;
|
||||
@@ -958,6 +875,104 @@ void ClientWorld::update(float delta_time) {
|
||||
}
|
||||
}
|
||||
|
||||
void ClientWorld::update_players(float dt) {
|
||||
|
||||
auto update_renderinfo = [this, dt](entt::entity player) {
|
||||
auto& transform = m_registry.get<Transform>(player);
|
||||
transform.render_pos =
|
||||
glm::mix(transform.render_pos, transform.pos, 0.15f);
|
||||
if (Math::distance2(transform.render_pos, m_player.get_player_pos()) >
|
||||
m_rendering_distance * CHUNK_SIZE * m_rendering_distance *
|
||||
CHUNK_SIZE) {
|
||||
return;
|
||||
}
|
||||
auto& view_angles = m_registry.get<ViewAngles>(player);
|
||||
view_angles.render_yaw =
|
||||
glm::mix(view_angles.render_yaw, view_angles.yaw, 0.15);
|
||||
view_angles.render_pitch =
|
||||
glm::mix(view_angles.render_pitch, view_angles.pitch, 0.15);
|
||||
|
||||
if (transform.gait == Gait::WALK || transform.gait == Gait::RUN) {
|
||||
|
||||
transform.walk_time += dt;
|
||||
|
||||
float speed = transform.gait == Gait::RUN ? 14.0f : 8.0f;
|
||||
float amp = transform.gait == Gait::RUN ? 50.0f : 35.0f;
|
||||
// float amp = 90.0f;
|
||||
view_angles.angle =
|
||||
glm::sin(transform.walk_time * speed) * glm::radians(amp);
|
||||
} else if (transform.gait == Gait::STOP) {
|
||||
float t = glm::clamp(dt * 10.0f, 0.0f, 1.0f);
|
||||
view_angles.angle = glm::mix(view_angles.angle, 0.0f, t);
|
||||
}
|
||||
|
||||
// walking sound
|
||||
if (transform.gait == Gait::STOP) {
|
||||
transform.moving_time = 0.0f;
|
||||
} else {
|
||||
transform.moving_time += dt;
|
||||
}
|
||||
auto play_walk_sound = [&]() {
|
||||
glm::ivec3 block = glm::floor(transform.render_pos);
|
||||
block.y -= 1;
|
||||
BlockType id = get_block_tpye(block);
|
||||
if (id == 0) {
|
||||
return;
|
||||
}
|
||||
std::string name = BlockManager::name_form_id(id);
|
||||
std::string sound = "block/" + name + "/walk.ogg";
|
||||
m_audio.play_3d(sound, transform.render_pos);
|
||||
};
|
||||
if (transform.gait == Gait::WALK) {
|
||||
if (transform.moving_time >= ClientPlayer::WALK_SOUND_INTERVAL) {
|
||||
transform.moving_time = 0.0f;
|
||||
play_walk_sound();
|
||||
}
|
||||
}
|
||||
if (transform.gait == Gait::RUN) {
|
||||
if (transform.moving_time >= ClientPlayer::RUN_SOUND_INTERVAL) {
|
||||
transform.moving_time = 0.0f;
|
||||
play_walk_sound();
|
||||
}
|
||||
}
|
||||
auto& player_info = m_registry.get<EntityInfo>(player);
|
||||
m_render_player_data.emplace_back(
|
||||
player_info.name, player_info.uuid, transform.render_pos,
|
||||
view_angles.render_yaw, view_angles.render_pitch, transform.gait,
|
||||
view_angles.angle);
|
||||
};
|
||||
|
||||
{
|
||||
std::lock_guard lock(m_registry_mutex);
|
||||
|
||||
for (auto& [_, player] : m_player_entities) {
|
||||
update_renderinfo(player);
|
||||
}
|
||||
{
|
||||
auto gait = m_player.get_gait();
|
||||
auto& walk_time = m_player.walk_time();
|
||||
auto& angle = m_player.angle();
|
||||
if (gait == Gait::WALK || gait == Gait::RUN) {
|
||||
|
||||
walk_time += dt;
|
||||
|
||||
float speed = gait == Gait::RUN ? 14.0f : 8.0f;
|
||||
float amp = gait == Gait::RUN ? 50.0f : 35.0f;
|
||||
// float amp = 90.0f;
|
||||
angle = glm::sin(walk_time * speed) * glm::radians(amp);
|
||||
} else if (gait == Gait::STOP) {
|
||||
float t = glm::clamp(dt * 10.0f, 0.0f, 1.0f);
|
||||
angle = glm::mix(angle, 0.0f, t);
|
||||
}
|
||||
|
||||
m_render_player_data.emplace_back(
|
||||
m_player.get_name(), m_player.get_uuid(),
|
||||
m_player.get_player_pos(), m_player.yaw(), m_player.pitch(),
|
||||
m_player.get_gait(), m_player.angle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientWorld::handle_event(const Event& e) {
|
||||
return std::visit(
|
||||
Overloaded{[this](const MouseButtonEvent& e) {
|
||||
|
||||
63
src/gameplay/hitbox_manager.cpp
Normal file
63
src/gameplay/hitbox_manager.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "Cubed/gameplay/hitbox_manager.hpp"
|
||||
|
||||
#include "Cubed/tools/log.hpp"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
namespace fs = std::filesystem;
|
||||
using nlohmann::json;
|
||||
namespace Cubed {
|
||||
HitboxManager::HitboxManager() {}
|
||||
HitboxManager::~HitboxManager() {}
|
||||
|
||||
HitboxManager& HitboxManager::instance() {
|
||||
static HitboxManager inst;
|
||||
return inst;
|
||||
}
|
||||
|
||||
AABB HitboxManager::aabb(const std::string& key) {
|
||||
return instance().get_aabb(key);
|
||||
}
|
||||
|
||||
AABB HitboxManager::get_aabb(const std::string& key) {
|
||||
{
|
||||
cacc c;
|
||||
if (m_hitboxes.find(c, key)) {
|
||||
return c->second;
|
||||
}
|
||||
}
|
||||
|
||||
return load(key);
|
||||
}
|
||||
|
||||
AABB HitboxManager::load(const std::string& path) {
|
||||
fs::path p = ASSETS_PATH + path;
|
||||
try {
|
||||
glm::vec3 center;
|
||||
glm::vec3 half;
|
||||
std::ifstream s{p};
|
||||
json j = json::parse(s);
|
||||
if (j.contains("boxes")) {
|
||||
if (j["boxes"].contains("center")) {
|
||||
center.x = j["boxes"]["center"].at(0).get<float>();
|
||||
center.y = j["boxes"]["center"].at(1).get<float>();
|
||||
center.z = j["boxes"]["center"].at(2).get<float>();
|
||||
}
|
||||
if (j["boxes"].contains("half")) {
|
||||
half.x = j["boxes"]["half"].at(0).get<float>();
|
||||
half.y = j["boxes"]["half"].at(1).get<float>();
|
||||
half.z = j["boxes"]["half"].at(2).get<float>();
|
||||
}
|
||||
}
|
||||
acc a;
|
||||
if (m_hitboxes.insert(
|
||||
a, std::pair<std::string, AABB>{path, AABB{center, half}})) {
|
||||
return a->second;
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
Logger::error("Load Hitbox error {}", e.what());
|
||||
}
|
||||
Logger::error("Load hitbox {} Failed", path);
|
||||
return AABB{glm::vec3(0.0f), glm::vec3(0.0f)};
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
123
src/gameplay/move_system.cpp
Normal file
123
src/gameplay/move_system.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
#include "Cubed/gameplay/move_system.hpp"
|
||||
|
||||
#include "Cubed/gameplay/entity.hpp"
|
||||
#include "Cubed/gameplay/hitbox_manager.hpp"
|
||||
namespace Cubed {
|
||||
void MoveSystem::update(World& world, entt::registry& registry) {
|
||||
auto view = registry.view<Transform, Velocity, EntityInfo>();
|
||||
for (auto entity : view) {
|
||||
auto [transform, v, info] =
|
||||
view.get<Transform, Velocity, EntityInfo>(entity);
|
||||
move_x(world, transform, v, info);
|
||||
move_y(world, transform, v, info);
|
||||
move_z(world, transform, v, info);
|
||||
}
|
||||
}
|
||||
|
||||
void MoveSystem::move_x(World& world, Transform& transform, Velocity& v,
|
||||
const EntityInfo& info) {
|
||||
|
||||
auto& pos = transform.pos;
|
||||
float distance = v.dx * world.get_per_tick_time() / 1000.0f;
|
||||
pos.x += distance;
|
||||
|
||||
AABB box = HitboxManager::aabb(
|
||||
std::format("model/creature/{}/collision.json", info.name));
|
||||
glm::vec3 min = box.min();
|
||||
glm::vec3 max = box.max();
|
||||
|
||||
int minx = std::floor(min.x);
|
||||
int maxx = std::floor(max.x);
|
||||
int miny = std::floor(min.y);
|
||||
int maxy = std::floor(max.y);
|
||||
int minz = std::floor(min.z);
|
||||
int maxz = std::floor(max.z);
|
||||
|
||||
for (int x = minx; x <= maxx; ++x) {
|
||||
for (int y = miny; y <= maxy; ++y) {
|
||||
for (int z = minz; z <= maxz; ++z) {
|
||||
glm::ivec3 block_pos{x, y, z};
|
||||
if (!world.can_pass_block(block_pos)) {
|
||||
AABB block_box = World::get_block_aabb(block_pos);
|
||||
if (box.intersects(block_box)) {
|
||||
pos.x -= distance;
|
||||
v.dx = 0.0f;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MoveSystem::move_y(World& world, Transform& transform, Velocity& v,
|
||||
const EntityInfo& info) {
|
||||
auto& pos = transform.pos;
|
||||
float distance = v.dy * world.get_per_tick_time() / 1000.0f;
|
||||
pos.y += distance;
|
||||
|
||||
AABB box = HitboxManager::aabb(
|
||||
std::format("model/creature/{}/collision.json", info.name));
|
||||
glm::vec3 min = box.min();
|
||||
glm::vec3 max = box.max();
|
||||
|
||||
int minx = std::floor(min.x);
|
||||
int maxx = std::floor(max.x);
|
||||
int miny = std::floor(min.y);
|
||||
int maxy = std::floor(max.y);
|
||||
int minz = std::floor(min.z);
|
||||
int maxz = std::floor(max.z);
|
||||
|
||||
for (int x = minx; x <= maxx; ++x) {
|
||||
for (int y = miny; y <= maxy; ++y) {
|
||||
for (int z = minz; z <= maxz; ++z) {
|
||||
glm::ivec3 block_pos{x, y, z};
|
||||
if (!world.can_pass_block(block_pos)) {
|
||||
AABB block_box = World::get_block_aabb(block_pos);
|
||||
if (box.intersects(block_box)) {
|
||||
pos.y -= distance;
|
||||
v.dy = 0.0f;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MoveSystem::move_z(World& world, Transform& transform, Velocity& v,
|
||||
const EntityInfo& info) {
|
||||
auto& pos = transform.pos;
|
||||
float distance = v.dz * world.get_per_tick_time() / 1000.0f;
|
||||
pos.z += distance;
|
||||
|
||||
AABB box = HitboxManager::aabb(
|
||||
std::format("model/creature/{}/collision.json", info.name));
|
||||
glm::vec3 min = box.min();
|
||||
glm::vec3 max = box.max();
|
||||
|
||||
int minx = std::floor(min.x);
|
||||
int maxx = std::floor(max.x);
|
||||
int miny = std::floor(min.y);
|
||||
int maxy = std::floor(max.y);
|
||||
int minz = std::floor(min.z);
|
||||
int maxz = std::floor(max.z);
|
||||
|
||||
for (int x = minx; x <= maxx; ++x) {
|
||||
for (int y = miny; y <= maxy; ++y) {
|
||||
for (int z = minz; z <= maxz; ++z) {
|
||||
glm::ivec3 block_pos{x, y, z};
|
||||
if (!world.can_pass_block(block_pos)) {
|
||||
AABB block_box = World::get_block_aabb(block_pos);
|
||||
if (box.intersects(block_box)) {
|
||||
pos.z -= distance;
|
||||
v.dz = 0.0f;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -113,7 +113,7 @@ void ServerWorld::send_chunk(int task_id, const std::string& uuid,
|
||||
rsq_pos->set_x(pos.x);
|
||||
rsq_pos->set_z(pos.z);
|
||||
{
|
||||
chunk_caac cacc;
|
||||
chunk_cacc cacc;
|
||||
if (!m_chunks.find(cacc, pos)) {
|
||||
// No chunk found and not generating
|
||||
Logger::error("Chunk {} {} neither pending nor ready", pos.x,
|
||||
@@ -454,7 +454,7 @@ void ServerWorld::serever_run(std::stop_token stoken) {
|
||||
Logger::info("Server Thread Started!");
|
||||
|
||||
using Clock = std::chrono::steady_clock;
|
||||
constexpr auto TICK = std::chrono::milliseconds(DEFAULT_PER_TICK_TIME);
|
||||
const auto TICK = std::chrono::milliseconds(m_per_tick_time);
|
||||
|
||||
auto next = Clock::now();
|
||||
while (!stoken.stop_requested()) {
|
||||
@@ -990,4 +990,90 @@ void ServerWorld::set_chunk_load_style(int id) {
|
||||
|
||||
int ServerWorld::chunk_size() const { return m_chunks.size(); }
|
||||
|
||||
int ServerWorld::get_block(const glm::ivec3& block_pos) const {
|
||||
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
||||
chunk_cacc cacc;
|
||||
|
||||
if (!m_chunks.find(cacc, ChunkPos{chunk_x, chunk_z})) {
|
||||
return 0;
|
||||
}
|
||||
if (cacc->second.state != ChunkState::READY) {
|
||||
return 0;
|
||||
}
|
||||
const auto& chunk_blocks = cacc->second.chunk->get_chunk_blocks();
|
||||
auto [x, y, z] = Chunk::world_to_block(block_pos, {chunk_x, chunk_z});
|
||||
if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y ||
|
||||
z >= CHUNK_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
return chunk_blocks[Chunk::index(x, y, z)];
|
||||
}
|
||||
bool ServerWorld::is_solid(const glm::ivec3& block_pos) const {
|
||||
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
||||
chunk_cacc cacc;
|
||||
|
||||
if (!m_chunks.find(cacc, ChunkPos{chunk_x, chunk_z})) {
|
||||
return false;
|
||||
}
|
||||
if (cacc->second.state != ChunkState::READY) {
|
||||
return 0;
|
||||
}
|
||||
const auto& chunk_blocks = cacc->second.chunk->get_chunk_blocks();
|
||||
auto [x, y, z] = Chunk::world_to_block(block_pos, {chunk_x, chunk_z});
|
||||
if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y ||
|
||||
z >= CHUNK_SIZE) {
|
||||
return false;
|
||||
}
|
||||
auto id = chunk_blocks[Chunk::index(x, y, z)];
|
||||
if (BlockManager::is_gas(id) || BlockManager::is_liquid(id)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bool ServerWorld::can_pass_block(const glm::ivec3& block_pos) const {
|
||||
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
||||
chunk_cacc cacc;
|
||||
|
||||
if (!m_chunks.find(cacc, ChunkPos{chunk_x, chunk_z})) {
|
||||
return true;
|
||||
}
|
||||
if (cacc->second.state != ChunkState::READY) {
|
||||
return 0;
|
||||
}
|
||||
const auto& chunk_blocks = cacc->second.chunk->get_chunk_blocks();
|
||||
auto [x, y, z] = Chunk::world_to_block(block_pos, {chunk_x, chunk_z});
|
||||
if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y ||
|
||||
z >= CHUNK_SIZE) {
|
||||
return true;
|
||||
}
|
||||
auto id = chunk_blocks[Chunk::index(x, y, z)];
|
||||
return BlockManager::is_passable(id);
|
||||
}
|
||||
|
||||
BlockType ServerWorld::get_block_tpye(const glm::ivec3& block_pos) const {
|
||||
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
||||
chunk_cacc cacc;
|
||||
|
||||
if (!m_chunks.find(cacc, ChunkPos{chunk_x, chunk_z})) {
|
||||
// Logger::error("Can't Find Block {} {} {}", block_pos.x, block_pos.y,
|
||||
// block_pos.z);
|
||||
return 0;
|
||||
}
|
||||
if (cacc->second.state != ChunkState::READY) {
|
||||
return 0;
|
||||
}
|
||||
const auto& chunk_blocks = cacc->second.chunk->get_chunk_blocks();
|
||||
auto [x, y, z] = Chunk::world_to_block(block_pos, {chunk_x, chunk_z});
|
||||
if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y ||
|
||||
z >= CHUNK_SIZE) {
|
||||
// Logger::error("Can't Find Block {} {} {}", block_pos.x, block_pos.y,
|
||||
// block_pos.z);
|
||||
return 0;
|
||||
}
|
||||
return chunk_blocks[Chunk::index(x, y, z)];
|
||||
}
|
||||
|
||||
int ServerWorld::get_per_tick_time() const { return m_per_tick_time; }
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -13,30 +13,48 @@ void ModelRender::render_model(const std::string& name, const glm::vec3& pos,
|
||||
glm::mat4 transform = glm::translate(glm::mat4(1.0f), pos);
|
||||
auto& shader = m_renderer.get_shader("model_shader");
|
||||
glm::mat4 view = camera.get_camera_lookat();
|
||||
shader.use();
|
||||
shader.set_loc("proj_matrix", m_renderer.p_mat());
|
||||
render_node(root, transform, view, shader);
|
||||
render_node(root, transform, view, shader, false);
|
||||
}
|
||||
|
||||
void ModelRender::shadow_pass(const std::string& name, const glm::vec3& pos,
|
||||
Camera& camera) {
|
||||
auto& model_manager = m_renderer.model_manager();
|
||||
auto& root = model_manager.get_model(name);
|
||||
glm::mat4 transform = glm::translate(glm::mat4(1.0f), pos);
|
||||
auto& shader = m_renderer.get_shader("depth_model");
|
||||
glm::mat4 view = camera.get_camera_lookat();
|
||||
|
||||
render_node(root, transform, view, shader, true);
|
||||
}
|
||||
|
||||
void ModelRender::render_node(const ModelNode& node, const glm::mat4& parent,
|
||||
const glm::mat4& view, const Shader& shader) {
|
||||
const glm::mat4& view, const Shader& shader,
|
||||
bool shadow) {
|
||||
|
||||
glm::mat4 transform = parent * node.transform;
|
||||
if (shadow) {
|
||||
shader.set_loc("modelMatrix", transform);
|
||||
} else {
|
||||
glm::mat4 mv_matrix = view * transform;
|
||||
shader.set_loc("modelMatrix", transform);
|
||||
shader.set_loc("mv_matrix", mv_matrix);
|
||||
shader.set_loc("norm_matrix", glm::transpose(glm::inverse(mv_matrix)));
|
||||
}
|
||||
|
||||
shader.set_loc("mv_matrix", view * transform);
|
||||
for (auto& mesh : node.meshes) {
|
||||
render_mesh(mesh);
|
||||
render_mesh(mesh, shadow);
|
||||
}
|
||||
|
||||
for (auto& child : node.children) {
|
||||
render_node(child, transform, view, shader);
|
||||
render_node(child, transform, view, shader, shadow);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelRender::render_mesh(const Mesh& mesh) {
|
||||
void ModelRender::render_mesh(const Mesh& mesh, bool) {
|
||||
mesh.vao->bind();
|
||||
if (mesh.texture) {
|
||||
mesh.texture->bind(0);
|
||||
mesh.texture->bind(1);
|
||||
} else {
|
||||
Logger::error("Model Texture Not Find");
|
||||
}
|
||||
|
||||
@@ -302,15 +302,12 @@ void PlayerRenderer::render(const Shader& shader, ClientWorld& world) {
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerRenderer::shadow_render(const Shader& shader,
|
||||
glm::mat4& light_matrix,
|
||||
ClientWorld& world) {
|
||||
void PlayerRenderer::shadow_render(const Shader& shader, ClientWorld& world) {
|
||||
if (!m_inited) {
|
||||
Logger::error("Player Renderer isn't init");
|
||||
return;
|
||||
}
|
||||
shader.use();
|
||||
shader.set_loc("lightSpaceMatrix", light_matrix);
|
||||
|
||||
auto& players = world.render_player_data();
|
||||
|
||||
for (auto& player : players) {
|
||||
|
||||
@@ -250,12 +250,6 @@ void Renderer::render_dev_panel(DevPanel& dev_panel) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void Renderer::render_model(const std::string& name, const glm::vec3& pos,
|
||||
Camera& camera) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
m_model_renderer.render_model(name, pos, camera);
|
||||
}
|
||||
|
||||
bool Renderer::handle_event(const Event& e) {
|
||||
return std::visit(Overloaded{[](const MouseMoveEvent&) { return false; },
|
||||
[](const MouseButtonEvent&) { return false; },
|
||||
@@ -348,4 +342,5 @@ float Renderer::frame_width() const { return m_frame_width; }
|
||||
const glm::mat4& Renderer::p_mat() const { return m_world_proj_matrix; }
|
||||
const std::vector<VertexArray>& Renderer::vao() const { return m_vao; }
|
||||
ModelManager& Renderer::model_manager() { return m_model_manager; }
|
||||
ModelRender& Renderer::model_renderer() { return m_model_renderer; }
|
||||
} // namespace Cubed
|
||||
@@ -29,8 +29,6 @@ void ShaderManager::init() {
|
||||
"shaders/billboard_f_shader.glsl");
|
||||
register_shader("water", "shaders/water_v_shader.glsl",
|
||||
"shaders/water_f_shader.glsl");
|
||||
register_shader("player", "shaders/player_v_shader.glsl",
|
||||
"shaders/player_f_shader.glsl");
|
||||
register_shader("depth_model", "shaders/depth_model_vert.glsl",
|
||||
"shaders/depth_model_frag.glsl");
|
||||
register_shader("rect", "shaders/rect_v_shader.glsl",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "Cubed/camera.hpp"
|
||||
#include "Cubed/debug_collector.hpp"
|
||||
#include "Cubed/gameplay/client_world.hpp"
|
||||
#include "Cubed/gameplay/entity.hpp"
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/render/renderer_constants.hpp"
|
||||
#include "Cubed/scene/world_scene.hpp"
|
||||
@@ -44,9 +45,12 @@ void WorldRenderer::render(ClientWorld& world) {
|
||||
day_night_calculation(world);
|
||||
|
||||
render_sky(world);
|
||||
if (m_shader_on) {
|
||||
shadow_map_generate(world);
|
||||
}
|
||||
render_world(world);
|
||||
render_outline(world);
|
||||
render_player(world);
|
||||
render_entity(world);
|
||||
|
||||
FrameBuffer::unbind();
|
||||
|
||||
@@ -227,10 +231,6 @@ void WorldRenderer::render_world(ClientWorld& world) {
|
||||
|
||||
glm::mat4 norm_mat = glm::transpose(glm::inverse(mv_mat));
|
||||
|
||||
if (m_shader_on) {
|
||||
shadow_map_generate(world);
|
||||
}
|
||||
|
||||
m_world_fbo->bind();
|
||||
|
||||
glCullFace(GL_BACK);
|
||||
@@ -290,6 +290,21 @@ void WorldRenderer::render_outline(ClientWorld& world) {
|
||||
}
|
||||
}
|
||||
|
||||
void WorldRenderer::shadow_entity(ClientWorld& world,
|
||||
const glm::mat4& light_matrix) {
|
||||
auto& registry = world.get_registry();
|
||||
auto view = registry.view<Transform, Model>();
|
||||
auto& shader = m_renderer.get_shader("depth_model");
|
||||
shader.use();
|
||||
shader.set_loc("lightSpaceMatrix", light_matrix);
|
||||
for (auto entity : view) {
|
||||
auto [transform, model] = view.get<Transform, Model>(entity);
|
||||
m_renderer.model_renderer().shadow_pass(model.name, transform.pos,
|
||||
world.world_scene().camera());
|
||||
}
|
||||
m_player_renderer.shadow_render(shader, world);
|
||||
}
|
||||
|
||||
void WorldRenderer::shadow_map_generate(ClientWorld& world) {
|
||||
float texels_per_unit = 0.0f;
|
||||
const auto& lightdir = m_parallel_light.lightdir;
|
||||
@@ -392,9 +407,8 @@ void WorldRenderer::shadow_map_generate(ClientWorld& world) {
|
||||
snapshot->normal_discard_vertices_count);
|
||||
}
|
||||
}
|
||||
// player
|
||||
auto& player_shadow = m_renderer.get_shader("depth_model");
|
||||
m_player_renderer.shadow_render(player_shadow, light_space_matrix, world);
|
||||
|
||||
shadow_entity(world, light_space_matrix);
|
||||
}
|
||||
|
||||
void WorldRenderer::render_underwater(ClientWorld& world) {
|
||||
@@ -676,8 +690,8 @@ void WorldRenderer::render_transparent_block(const glm::mat4& mv_mat,
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void WorldRenderer::render_player(ClientWorld& world) {
|
||||
auto& shader = m_renderer.get_shader("player");
|
||||
void WorldRenderer::render_entity(ClientWorld& world) {
|
||||
auto& shader = m_renderer.get_shader("model_shader");
|
||||
shader.use();
|
||||
glm::vec3 light_dir_view =
|
||||
glm::normalize(glm::mat3(view_matrix) * m_parallel_light.lightdir);
|
||||
@@ -698,6 +712,16 @@ void WorldRenderer::render_player(ClientWorld& world) {
|
||||
// shader.set_loc("skyColor", m_sky_uniform.sky_top);
|
||||
|
||||
m_depth_map_texture->bind(0);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
auto& registry = world.get_registry();
|
||||
auto view = registry.view<Transform, Model>();
|
||||
for (auto entity : view) {
|
||||
auto [transform, model] = view.get<Transform, Model>(entity);
|
||||
m_renderer.model_renderer().render_model(model.name, transform.pos,
|
||||
world.world_scene().camera());
|
||||
}
|
||||
|
||||
m_player_renderer.render(shader, world);
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,6 @@ void WorldScene::render(Renderer& renderer) {
|
||||
return;
|
||||
}
|
||||
renderer.render_world(m_client_world);
|
||||
renderer.render_model("model/creature/pig.glb", {0, 100, 0}, m_camera);
|
||||
if (m_show_hud) {
|
||||
m_hud_ui.render(renderer);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user