-
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,3 +11,4 @@
|
|||||||
/cmake_install.cmake
|
/cmake_install.cmake
|
||||||
/libassets.a
|
/libassets.a
|
||||||
/resources.cpp
|
/resources.cpp
|
||||||
|
/imgui.ini
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections -DGLM_FORCE_DEPTH_ZERO_TO_ONE")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -UNDEBUG")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -UNDEBUG")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") # -rdynamic
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") # -rdynamic
|
||||||
|
|
||||||
|
# gprof
|
||||||
|
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
|
||||||
|
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg")
|
||||||
|
|
||||||
|
# sanitizer
|
||||||
|
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
|
||||||
|
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
||||||
|
|
||||||
|
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment")
|
||||||
|
|
||||||
project (LuaVox VERSION 0.0 DESCRIPTION "LuaVox Description")
|
project (LuaVox VERSION 0.0 DESCRIPTION "LuaVox Description")
|
||||||
add_executable(${PROJECT_NAME})
|
add_executable(${PROJECT_NAME})
|
||||||
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
|
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
|
||||||
@@ -11,20 +21,41 @@ file(GLOB_RECURSE SOURCES RELATIVE ${PROJECT_SOURCE_DIR} "Src/*.cpp")
|
|||||||
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})
|
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC "${PROJECT_SOURCE_DIR}/Src")
|
target_include_directories(${PROJECT_NAME} PUBLIC "${PROJECT_SOURCE_DIR}/Src")
|
||||||
|
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
# Boost
|
# Boost
|
||||||
if(POLICY CMP0167)
|
if(POLICY CMP0167)
|
||||||
cmake_policy(SET CMP0167 NEW)
|
cmake_policy(SET CMP0167 NEW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
find_package(Boost REQUIRED COMPONENTS thread json)
|
# find_package(Boost REQUIRED COMPONENTS thread json)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${Boost_INCLUDE_DIR})
|
# target_include_directories(${PROJECT_NAME} PUBLIC ${Boost_INCLUDE_DIR})
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Boost::thread Boost::json)
|
# target_link_libraries(${PROJECT_NAME} PUBLIC Boost::thread Boost::json)
|
||||||
|
|
||||||
|
set(BOOST_INCLUDE_LIBRARIES asio thread json)
|
||||||
|
set(BOOST_ENABLE_CMAKE ON)
|
||||||
|
FetchContent_Declare(
|
||||||
|
Boost
|
||||||
|
URL https://github.com/boostorg/boost/releases/download/boost-1.87.0/boost-1.87.0-cmake.7z
|
||||||
|
USES_TERMINAL_DOWNLOAD TRUE
|
||||||
|
DOWNLOAD_NO_EXTRACT FALSE
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(Boost)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC Boost::asio Boost::thread Boost::json)
|
||||||
|
|
||||||
# glm
|
# glm
|
||||||
find_package(glm REQUIRED)
|
# find_package(glm REQUIRED)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${GLM_INCLUDE_DIR})
|
# target_include_directories(${PROJECT_NAME} PUBLIC ${GLM_INCLUDE_DIR})
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${GLM_LIBRARY})
|
# target_link_libraries(${PROJECT_NAME} PUBLIC ${GLM_LIBRARY})
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
glm
|
||||||
|
GIT_REPOSITORY https://github.com/g-truc/glm.git
|
||||||
|
GIT_TAG 1.0.1
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(glm)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC glm)
|
||||||
|
|
||||||
# JPEG
|
# JPEG
|
||||||
find_package(JPEG REQUIRED)
|
find_package(JPEG REQUIRED)
|
||||||
@@ -40,13 +71,26 @@ target_link_libraries(${PROJECT_NAME} PUBLIC PNG::PNG)
|
|||||||
target_include_directories(${PROJECT_NAME} PUBLIC "${PROJECT_SOURCE_DIR}/Libs/png++")
|
target_include_directories(${PROJECT_NAME} PUBLIC "${PROJECT_SOURCE_DIR}/Libs/png++")
|
||||||
|
|
||||||
# GLFW3
|
# GLFW3
|
||||||
find_package(glfw3 REQUIRED)
|
# find_package(glfw3 REQUIRED)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${GLFW_INCLUDE_DIRS})
|
# target_include_directories(${PROJECT_NAME} PUBLIC ${GLFW_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
glfw
|
||||||
|
GIT_REPOSITORY https://github.com/glfw/glfw.git
|
||||||
|
GIT_TAG 3.4
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(glfw)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC glfw)
|
target_link_libraries(${PROJECT_NAME} PUBLIC glfw)
|
||||||
|
|
||||||
# FreeType
|
# FreeType
|
||||||
find_package(Freetype REQUIRED)
|
find_package(Freetype REQUIRED)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${GLM_INCLUDE_DIRS})
|
# FetchContent_Declare(
|
||||||
|
# freetype
|
||||||
|
# GIT_REPOSITORY https://github.com/freetype/freetype.git
|
||||||
|
# GIT_TAG freetype
|
||||||
|
# )
|
||||||
|
# FetchContent_MakeAvailable(freetype)
|
||||||
|
target_include_directories(${PROJECT_NAME} PUBLIC ${freetype_INCLUDE_DIRS})
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Freetype::Freetype)
|
target_link_libraries(${PROJECT_NAME} PUBLIC Freetype::Freetype)
|
||||||
|
|
||||||
# ImGui
|
# ImGui
|
||||||
@@ -70,5 +114,3 @@ SET_SOURCE_FILES_PROPERTIES(assets.o PROPERTIES EXTERNAL_OBJECT true GENERATED t
|
|||||||
add_library(assets STATIC resources.cpp assets.o)
|
add_library(assets STATIC resources.cpp assets.o)
|
||||||
SET_TARGET_PROPERTIES(assets PROPERTIES LINKER_LANGUAGE C)
|
SET_TARGET_PROPERTIES(assets PROPERTIES LINKER_LANGUAGE C)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC assets uring)
|
target_link_libraries(${PROJECT_NAME} PUBLIC assets uring)
|
||||||
|
|
||||||
#set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment")
|
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <Common/Abstract.hpp>
|
#include <Common/Abstract.hpp>
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ public:
|
|||||||
virtual void onDefEntityUpdates(const std::vector<DefEntityId_c> &updates) = 0;
|
virtual void onDefEntityUpdates(const std::vector<DefEntityId_c> &updates) = 0;
|
||||||
|
|
||||||
// Сообщаем об изменившихся чанках
|
// Сообщаем об изменившихся чанках
|
||||||
virtual void onChunksChange(WorldId_c worldId, const std::vector<Pos::GlobalChunk> &changeOrAddList, const std::vector<Pos::GlobalChunk> &remove) = 0;
|
virtual void onChunksChange(WorldId_c worldId, const std::unordered_set<Pos::GlobalChunk> &changeOrAddList, const std::unordered_set<Pos::GlobalChunk> &remove) = 0;
|
||||||
// Установить позицию для камеры
|
// Установить позицию для камеры
|
||||||
virtual void setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) = 0;
|
virtual void setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) = 0;
|
||||||
|
|
||||||
@@ -90,7 +91,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
struct Region {
|
struct Region {
|
||||||
std::unordered_map<Pos::Local4_u::Key, Chunk[4][4][4]> Subs;
|
std::unordered_map<Pos::Local16_u, Chunk> Chunks;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -147,6 +148,10 @@ public:
|
|||||||
std::unordered_map<EntityId_c, EntityInfo> Entityes;
|
std::unordered_map<EntityId_c, EntityInfo> Entityes;
|
||||||
} Registry;
|
} Registry;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
std::unordered_map<WorldId_c, World> Worlds;
|
||||||
|
} External;
|
||||||
|
|
||||||
virtual ~IServerSession();
|
virtual ~IServerSession();
|
||||||
|
|
||||||
virtual void atFreeDrawTime(GlobalTime gTime, float dTime) = 0;
|
virtual void atFreeDrawTime(GlobalTime gTime, float dTime) = 0;
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <Common/Packets.hpp>
|
#include <Common/Packets.hpp>
|
||||||
#include <glm/ext.hpp>
|
#include <glm/ext.hpp>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
|
||||||
namespace LV::Client {
|
namespace LV::Client {
|
||||||
@@ -163,6 +165,9 @@ void ServerSession::onCursorPosChange(int32_t width, int32_t height) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ServerSession::onCursorMove(float xMove, float yMove) {
|
void ServerSession::onCursorMove(float xMove, float yMove) {
|
||||||
|
xMove /= 10.f;
|
||||||
|
yMove /= 10.f;
|
||||||
|
|
||||||
glm::vec3 deltaPYR;
|
glm::vec3 deltaPYR;
|
||||||
|
|
||||||
static constexpr float PI = glm::pi<float>(), PI2 = PI*2, PI_HALF = PI/2, PI_DEG = PI/180;
|
static constexpr float PI = glm::pi<float>(), PI2 = PI*2, PI_HALF = PI/2, PI_DEG = PI/180;
|
||||||
@@ -186,6 +191,26 @@ void ServerSession::onCursorBtn(ISurfaceEventListener::EnumCursorBtn btn, bool s
|
|||||||
void ServerSession::onKeyboardBtn(int btn, int state) {
|
void ServerSession::onKeyboardBtn(int btn, int state) {
|
||||||
if(btn == GLFW_KEY_TAB && !state) {
|
if(btn == GLFW_KEY_TAB && !state) {
|
||||||
CursorMode = CursorMode == EnumCursorMoveMode::Default ? EnumCursorMoveMode::MoveAndHidden : EnumCursorMoveMode::Default;
|
CursorMode = CursorMode == EnumCursorMoveMode::Default ? EnumCursorMoveMode::MoveAndHidden : EnumCursorMoveMode::Default;
|
||||||
|
Keys.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(CursorMode == EnumCursorMoveMode::MoveAndHidden)
|
||||||
|
{
|
||||||
|
if(btn == GLFW_KEY_W)
|
||||||
|
Keys.W = state;
|
||||||
|
else if(btn == GLFW_KEY_A)
|
||||||
|
Keys.A = state;
|
||||||
|
else if(btn == GLFW_KEY_S)
|
||||||
|
Keys.S = state;
|
||||||
|
else if(btn == GLFW_KEY_D)
|
||||||
|
Keys.D = state;
|
||||||
|
else if(btn == GLFW_KEY_LEFT_SHIFT)
|
||||||
|
Keys.SHIFT = state;
|
||||||
|
else if(btn == GLFW_KEY_SPACE)
|
||||||
|
Keys.SPACE = state;
|
||||||
|
else if(btn == GLFW_KEY_LEFT_CONTROL)
|
||||||
|
Keys.CTRL = state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,17 +221,62 @@ void ServerSession::onJoystick() {
|
|||||||
void ServerSession::atFreeDrawTime(GlobalTime gTime, float dTime) {
|
void ServerSession::atFreeDrawTime(GlobalTime gTime, float dTime) {
|
||||||
GTime = gTime;
|
GTime = gTime;
|
||||||
|
|
||||||
|
Pos += glm::vec3(Speed) * dTime;
|
||||||
|
Speed -= glm::dvec3(Speed) * double(dTime);
|
||||||
|
|
||||||
|
glm::mat4 rot(1);
|
||||||
|
float deltaTime = 1-std::min<float>(gTime-PYR_At, 1/PYR_TIME_DELTA)*PYR_TIME_DELTA;
|
||||||
|
rot = glm::rotate(rot, PYR.y-deltaTime*PYR_Offset.y, {0, 1, 0});
|
||||||
|
|
||||||
|
float mltpl = 16*dTime*Pos::Object_t::BS;
|
||||||
|
if(Keys.CTRL)
|
||||||
|
mltpl *= 16;
|
||||||
|
|
||||||
|
Speed += glm::vec3(rot*glm::vec4(0, 0, 1, 1)*float(Keys.W))*mltpl;
|
||||||
|
Speed += glm::vec3(rot*glm::vec4(-1, 0, 0, 1)*float(Keys.A))*mltpl;
|
||||||
|
Speed += glm::vec3(rot*glm::vec4(0, 0, -1, 1)*float(Keys.S))*mltpl;
|
||||||
|
Speed += glm::vec3(rot*glm::vec4(1, 0, 0, 1)*float(Keys.D))*mltpl;
|
||||||
|
Speed += glm::vec3(0, -1, 0)*float(Keys.SHIFT)*mltpl;
|
||||||
|
Speed += glm::vec3(0, 1, 0)*float(Keys.SPACE)*mltpl;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unordered_map<WorldId_c, std::tuple<std::unordered_set<Pos::GlobalChunk>, std::unordered_set<Pos::GlobalChunk>>> changeOrAddList_removeList;
|
||||||
|
|
||||||
|
// Пакеты
|
||||||
|
ParsedPacket *pack;
|
||||||
|
while(NetInputPackets.pop(pack)) {
|
||||||
|
if(pack->Level1 == ToClient::L1::Content && ToClient::L2Content(pack->Level2) == ToClient::L2Content::ChunkVoxels) {
|
||||||
|
PP_Content_ChunkVoxels &p = *dynamic_cast<PP_Content_ChunkVoxels*>(pack);
|
||||||
|
Pos::GlobalRegion rPos(p.Pos.X >> 4, p.Pos.Y >> 4, p.Pos.Z >> 4);
|
||||||
|
Pos::Local16_u cPos(p.Pos.X & 0xf, p.Pos.Y & 0xf, p.Pos.Z & 0xf);
|
||||||
|
External.Worlds[p.Id].Regions[rPos].Chunks[cPos].Voxels = std::move(p.Cubes);
|
||||||
|
|
||||||
|
auto &pair = changeOrAddList_removeList[p.Id];
|
||||||
|
std::get<0>(pair).insert(p.Pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete pack;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(RS && !changeOrAddList_removeList.empty()) {
|
||||||
|
for(auto &pair : changeOrAddList_removeList) {
|
||||||
|
RS->onChunksChange(pair.first, std::get<0>(pair.second), std::get<1>(pair.second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!RS)
|
if(!RS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Расчёт камеры
|
// Расчёт камеры
|
||||||
{
|
{
|
||||||
float deltaTime = 1-std::min<float>(gTime-PYR_At, 1/PYR_TIME_DELTA)*PYR_TIME_DELTA;
|
float deltaTime = 1-std::min<float>(gTime-PYR_At, 1/PYR_TIME_DELTA)*PYR_TIME_DELTA;
|
||||||
glm::quat quat =
|
|
||||||
glm::angleAxis(PYR.x-deltaTime*PYR_Offset.x, glm::vec3(1.f, 0.f, 0.f))
|
|
||||||
* glm::angleAxis(PYR.y-deltaTime*PYR_Offset.y, glm::vec3(0.f, 1.f, 0.f));
|
|
||||||
|
|
||||||
RS->setCameraPos(0, {0, 0, 0}, quat);
|
glm::quat quat =
|
||||||
|
glm::angleAxis(PYR.x-deltaTime*PYR_Offset.x, glm::vec3(-1.f, 0.f, 0.f))
|
||||||
|
* glm::angleAxis(PYR.y-deltaTime*PYR_Offset.y, glm::vec3(0.f, -1.f, 0.f));
|
||||||
|
|
||||||
|
RS->setCameraPos(0, Pos, quat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,6 +457,7 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) {
|
|||||||
Pos::GlobalChunk pos = *(Pos::GlobalChunk*) &posKey;
|
Pos::GlobalChunk pos = *(Pos::GlobalChunk*) &posKey;
|
||||||
|
|
||||||
std::vector<VoxelCube> cubes(co_await sock.read<uint16_t>());
|
std::vector<VoxelCube> cubes(co_await sock.read<uint16_t>());
|
||||||
|
uint16_t debugCubesCount = cubes.size();
|
||||||
|
|
||||||
for(size_t iter = 0; iter < cubes.size(); iter++) {
|
for(size_t iter = 0; iter < cubes.size(); iter++) {
|
||||||
VoxelCube &cube = cubes[iter];
|
VoxelCube &cube = cubes[iter];
|
||||||
@@ -409,7 +480,7 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) {
|
|||||||
|
|
||||||
while(!NetInputPackets.push(packet));
|
while(!NetInputPackets.push(packet));
|
||||||
|
|
||||||
LOG.info() << "Приняты воксели чанка " << int(wcId) << " / " << pos.X << ":" << pos.Y << ":" << pos.Z << " Вокселей " << cubes.size();
|
LOG.info() << "Приняты воксели чанка " << int(wcId) << " / " << pos.X << ":" << pos.Y << ":" << pos.Z << " Вокселей " << debugCubesCount;
|
||||||
|
|
||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Abstract.hpp"
|
#include "Abstract.hpp"
|
||||||
|
#include "Common/Abstract.hpp"
|
||||||
#include "Common/Async.hpp"
|
#include "Common/Async.hpp"
|
||||||
#include "Common/Lockable.hpp"
|
#include "Common/Lockable.hpp"
|
||||||
#include "Common/Net.hpp"
|
#include "Common/Net.hpp"
|
||||||
@@ -31,10 +32,6 @@ class ServerSession : public AsyncObject, public IServerSession, public ISurface
|
|||||||
|
|
||||||
TOS::Logger LOG = "ServerSession";
|
TOS::Logger LOG = "ServerSession";
|
||||||
|
|
||||||
struct {
|
|
||||||
glm::quat Quat;
|
|
||||||
} Camera;
|
|
||||||
|
|
||||||
boost::lockfree::spsc_queue<ParsedPacket*> NetInputPackets;
|
boost::lockfree::spsc_queue<ParsedPacket*> NetInputPackets;
|
||||||
|
|
||||||
// PYR - поворот камеры по осям xyz в радианах, PYR_Offset для сглаживание поворота
|
// PYR - поворот камеры по осям xyz в радианах, PYR_Offset для сглаживание поворота
|
||||||
@@ -43,6 +40,17 @@ class ServerSession : public AsyncObject, public IServerSession, public ISurface
|
|||||||
static constexpr float PYR_TIME_DELTA = 30;
|
static constexpr float PYR_TIME_DELTA = 30;
|
||||||
GlobalTime GTime;
|
GlobalTime GTime;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool W = false, A = false, S = false, D = false, SHIFT = false, SPACE = false;
|
||||||
|
bool CTRL = false;
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
std::memset(this, 0, sizeof(*this));
|
||||||
|
}
|
||||||
|
} Keys;
|
||||||
|
Pos::Object Pos = Pos::Object(0), Speed = Pos::Object(0);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Нужен сокет, на котором только что был согласован игровой протокол (asyncInitGameProtocol)
|
// Нужен сокет, на котором только что был согласован игровой протокол (asyncInitGameProtocol)
|
||||||
ServerSession(asio::io_context &ioc, std::unique_ptr<Net::AsyncSocket> &&socket, IRenderSession *rs = nullptr)
|
ServerSession(asio::io_context &ioc, std::unique_ptr<Net::AsyncSocket> &&socket, IRenderSession *rs = nullptr)
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ void Vulkan::run()
|
|||||||
while(!NeedShutdown)
|
while(!NeedShutdown)
|
||||||
{
|
{
|
||||||
float dTime = glfwGetTime()-prevTime;
|
float dTime = glfwGetTime()-prevTime;
|
||||||
prevTime = glfwGetTime();
|
prevTime += dTime;
|
||||||
|
|
||||||
Screen.State = DrawState::Begin;
|
Screen.State = DrawState::Begin;
|
||||||
{
|
{
|
||||||
@@ -176,15 +176,15 @@ void Vulkan::run()
|
|||||||
// Спрятать или показать курсор
|
// Спрятать или показать курсор
|
||||||
{
|
{
|
||||||
int mode = glfwGetInputMode(Graphics.Window, GLFW_CURSOR);
|
int mode = glfwGetInputMode(Graphics.Window, GLFW_CURSOR);
|
||||||
if(mode == GLFW_CURSOR_HIDDEN && sobj.CursorMode != ISurfaceEventListener::EnumCursorMoveMode::MoveAndHidden)
|
if(mode == GLFW_CURSOR_DISABLED && sobj.CursorMode != ISurfaceEventListener::EnumCursorMoveMode::MoveAndHidden)
|
||||||
glfwSetInputMode(Graphics.Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
glfwSetInputMode(Graphics.Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||||
else if(mode == GLFW_CURSOR_NORMAL && sobj.CursorMode != ISurfaceEventListener::EnumCursorMoveMode::Default) {
|
else if(mode == GLFW_CURSOR_NORMAL && sobj.CursorMode != ISurfaceEventListener::EnumCursorMoveMode::Default) {
|
||||||
glfwSetInputMode(Graphics.Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
|
||||||
glfwSetCursorPos(Graphics.Window, Screen.Width/2., Screen.Height/2.);
|
glfwSetCursorPos(Graphics.Window, Screen.Width/2., Screen.Height/2.);
|
||||||
|
Game.MLastPosX = Screen.Width/2.;
|
||||||
|
Game.MLastPosY = Screen.Height/2.;
|
||||||
|
glfwSetInputMode(Graphics.Window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if(CallBeforeDraw)
|
// if(CallBeforeDraw)
|
||||||
@@ -197,7 +197,8 @@ void Vulkan::run()
|
|||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
VkResult err;
|
VkResult err;
|
||||||
err = vkAcquireNextImageKHR(Graphics.Device, Graphics.Swapchain, UINT64_MAX, SemaphoreImageAcquired, (VkFence) 0, &Graphics.DrawBufferCurrent);
|
err = vkAcquireNextImageKHR(Graphics.Device, Graphics.Swapchain, 1000000000ULL/20, SemaphoreImageAcquired, (VkFence) 0, &Graphics.DrawBufferCurrent);
|
||||||
|
GlobalTime gTime = glfwGetTime();
|
||||||
|
|
||||||
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||||
{
|
{
|
||||||
@@ -207,9 +208,7 @@ void Vulkan::run()
|
|||||||
} else if (err == VK_SUBOPTIMAL_KHR)
|
} else if (err == VK_SUBOPTIMAL_KHR)
|
||||||
{
|
{
|
||||||
LOGGER.debug() << "VK_SUBOPTIMAL_KHR Pre";
|
LOGGER.debug() << "VK_SUBOPTIMAL_KHR Pre";
|
||||||
} else
|
} else if(err == VK_SUCCESS) {
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
|
|
||||||
Screen.State = DrawState::Drawing;
|
Screen.State = DrawState::Drawing;
|
||||||
//Готовим инструкции рисовки
|
//Готовим инструкции рисовки
|
||||||
@@ -277,8 +276,6 @@ void Vulkan::run()
|
|||||||
vkCmdSetScissor(Graphics.CommandBufferRender, 0, 1, &scissor);
|
vkCmdSetScissor(Graphics.CommandBufferRender, 0, 1, &scissor);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalTime gTime = glfwGetTime();
|
|
||||||
|
|
||||||
if(Game.RSession) {
|
if(Game.RSession) {
|
||||||
auto &robj = *Game.RSession;
|
auto &robj = *Game.RSession;
|
||||||
// Рендер мира
|
// Рендер мира
|
||||||
@@ -528,6 +525,8 @@ void Vulkan::run()
|
|||||||
else
|
else
|
||||||
assert(!err);
|
assert(!err);
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
assert(err == VK_TIMEOUT);
|
||||||
|
|
||||||
if(Game.Session) {
|
if(Game.Session) {
|
||||||
Game.Session->atFreeDrawTime(gTime, dTime);
|
Game.Session->atFreeDrawTime(gTime, dTime);
|
||||||
@@ -996,8 +995,15 @@ void Vulkan::glfwCallbackOnResize(GLFWwindow *window, int width, int height)
|
|||||||
handler->freeSwapchains();
|
handler->freeSwapchains();
|
||||||
handler->buildSwapchains();
|
handler->buildSwapchains();
|
||||||
|
|
||||||
if(handler->Game.Session)
|
if(handler->Game.Session) {
|
||||||
handler->Game.Session->onResize(width, height);
|
handler->Game.Session->onResize(width, height);
|
||||||
|
|
||||||
|
if(handler->Game.Session->CursorMode == ISurfaceEventListener::EnumCursorMoveMode::MoveAndHidden) {
|
||||||
|
glfwSetCursorPos(window, width/2., height/2.);
|
||||||
|
handler->Game.MLastPosX = width/2.;
|
||||||
|
handler->Game.MLastPosY = height/2.;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1018,8 +1024,9 @@ void Vulkan::glfwCallbackOnCursorPos(GLFWwindow* window, double xpos, double ypo
|
|||||||
if(sobj.CursorMode == ISurfaceEventListener::EnumCursorMoveMode::Default) {
|
if(sobj.CursorMode == ISurfaceEventListener::EnumCursorMoveMode::Default) {
|
||||||
sobj.onCursorPosChange((int32_t) xpos, (int32_t) ypos);
|
sobj.onCursorPosChange((int32_t) xpos, (int32_t) ypos);
|
||||||
} else {
|
} else {
|
||||||
glfwSetCursorPos(handler->Graphics.Window, handler->Screen.Width/2., handler->Screen.Height/2.);
|
sobj.onCursorMove(xpos-handler->Game.MLastPosX, handler->Game.MLastPosY-ypos);
|
||||||
sobj.onCursorMove(xpos-handler->Screen.Width/2., handler->Screen.Height/2.-ypos);
|
handler->Game.MLastPosX = xpos;
|
||||||
|
handler->Game.MLastPosY = ypos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,7 @@
|
|||||||
|
|
||||||
#define HAS_IMGUI
|
#define HAS_IMGUI
|
||||||
|
|
||||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
#include "freetype/freetype.h"
|
||||||
|
|
||||||
#include <freetype/freetype.h>
|
|
||||||
|
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
#include <glm/ext.hpp>
|
#include <glm/ext.hpp>
|
||||||
@@ -28,6 +26,8 @@
|
|||||||
#define GLFW_INCLUDE_NONE
|
#define GLFW_INCLUDE_NONE
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
static_assert(GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_ZO);
|
||||||
|
|
||||||
#define IMGUI_ENABLE_STB_TEXTEDIT_UNICODE
|
#define IMGUI_ENABLE_STB_TEXTEDIT_UNICODE
|
||||||
|
|
||||||
namespace LV::Client::VK {
|
namespace LV::Client::VK {
|
||||||
@@ -245,6 +245,8 @@ public:
|
|||||||
|
|
||||||
std::list<void (Vulkan::*)()> ImGuiInterfaces;
|
std::list<void (Vulkan::*)()> ImGuiInterfaces;
|
||||||
std::unique_ptr<ServerObj> Server;
|
std::unique_ptr<ServerObj> Server;
|
||||||
|
|
||||||
|
double MLastPosX, MLastPosY;
|
||||||
} Game;
|
} Game;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
#include "VulkanRenderSession.hpp"
|
#include "VulkanRenderSession.hpp"
|
||||||
#include "Client/Vulkan/Vulkan.hpp"
|
#include "Client/Vulkan/Vulkan.hpp"
|
||||||
|
#include "Common/Abstract.hpp"
|
||||||
#include "assets.hpp"
|
#include "assets.hpp"
|
||||||
#include <glm/ext/matrix_transform.hpp>
|
#include <memory>
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
namespace LV::Client::VK {
|
namespace LV::Client::VK {
|
||||||
|
|
||||||
@@ -92,7 +94,7 @@ void VulkanRenderSession::init(Vulkan *instance) {
|
|||||||
.binding = 1,
|
.binding = 1,
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
.pImmutableSamplers = nullptr
|
.pImmutableSamplers = nullptr
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -136,7 +138,7 @@ void VulkanRenderSession::init(Vulkan *instance) {
|
|||||||
.binding = 1,
|
.binding = 1,
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
.pImmutableSamplers = nullptr
|
.pImmutableSamplers = nullptr
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -188,13 +190,28 @@ void VulkanRenderSession::init(Vulkan *instance) {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
int width, height;
|
||||||
|
bool hasAlpha;
|
||||||
|
ByteBuffer image = VK::loadPNG(std::ifstream("/home/mr_s/Workspace/Alpha/LuaVox/assets/grass.png"), width, height, hasAlpha);
|
||||||
|
uint16_t texId = VKCTX->MainTest.atlasAddTexture(width, height);
|
||||||
|
VKCTX->MainTest.atlasChangeTextureData(texId, (const uint32_t*) image.data());
|
||||||
|
|
||||||
|
/*
|
||||||
|
x left -1 ~ right 1
|
||||||
|
y up -1 ~ down 1
|
||||||
|
z far 1 ~ near 0
|
||||||
|
|
||||||
|
glm
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
NodeVertexStatic *array = (NodeVertexStatic*) VKCTX->TestQuad.mapMemory();
|
NodeVertexStatic *array = (NodeVertexStatic*) VKCTX->TestQuad.mapMemory();
|
||||||
array[0] = {112, 114, 113, 0, 0, 0, 0, 0, 0};
|
array[0] = {112, 114, 50, 0, 0, 0, 0, 0, 0};
|
||||||
array[1] = {114, 114, 113, 0, 0, 0, 0, 65535, 0};
|
array[1] = {114, 114, 50, 0, 0, 0, 0, 65535, 0};
|
||||||
array[2] = {114, 112, 113, 0, 0, 0, 0, 65535, 65535};
|
array[2] = {114, 112, 50, 0, 0, 0, 0, 65535, 65535};
|
||||||
array[3] = {112, 114, 113, 0, 0, 0, 0, 0, 0};
|
array[3] = {112, 114, 50, 0, 0, 0, 0, 0, 0};
|
||||||
array[4] = {114, 112, 113, 0, 0, 0, 0, 65535, 65535};
|
array[4] = {114, 112, 50, 0, 0, 0, 0, 65535, 65535};
|
||||||
array[5] = {112, 112, 113, 0, 0, 0, 0, 0, 65535};
|
array[5] = {112, 112, 50, 0, 0, 0, 0, 0, 65535};
|
||||||
VKCTX->TestQuad.unMapMemory();
|
VKCTX->TestQuad.unMapMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,8 +593,32 @@ void VulkanRenderSession::onDefEntityUpdates(const std::vector<DefEntityId_c> &u
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderSession::onChunksChange(WorldId_c worldId, const std::vector<Pos::GlobalChunk> &changeOrAddList, const std::vector<Pos::GlobalChunk> &remove) {
|
void VulkanRenderSession::onChunksChange(WorldId_c worldId, const std::unordered_set<Pos::GlobalChunk> &changeOrAddList, const std::unordered_set<Pos::GlobalChunk> &remove) {
|
||||||
|
for(Pos::GlobalChunk pos : changeOrAddList) {
|
||||||
|
Pos::GlobalRegion rPos(pos.X >> 4, pos.Y >> 4, pos.Z >> 4);
|
||||||
|
Pos::Local16_u cPos(pos.X & 0xf, pos.Y & 0xf, pos.Z & 0xf);
|
||||||
|
|
||||||
|
const auto &voxels = ServerSession->External.Worlds[worldId].Regions[rPos].Chunks[cPos].Voxels;
|
||||||
|
auto &table = External.ChunkVoxelMesh[worldId];
|
||||||
|
|
||||||
|
if(voxels.empty()) {
|
||||||
|
auto iter = table.find(pos);
|
||||||
|
if(iter != table.end())
|
||||||
|
table.erase(iter);
|
||||||
|
|
||||||
|
if(table.empty())
|
||||||
|
External.ChunkVoxelMesh.erase(External.ChunkVoxelMesh.find(worldId));
|
||||||
|
} else {
|
||||||
|
auto &buffer = table[pos] = std::make_unique<Buffer>(VkInst, voxels.size()*6*6*sizeof(NodeVertexStatic));
|
||||||
|
NodeVertexStatic *vertex = (NodeVertexStatic*) buffer->mapMemory();
|
||||||
|
|
||||||
|
for(const VoxelCube &cube : voxels) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->unMapMemory();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderSession::setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) {
|
void VulkanRenderSession::setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) {
|
||||||
@@ -587,14 +628,19 @@ void VulkanRenderSession::setCameraPos(WorldId_c worldId, Pos::Object pos, glm::
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderSession::beforeDraw() {
|
void VulkanRenderSession::beforeDraw() {
|
||||||
|
if(VKCTX) {
|
||||||
|
VKCTX->MainTest.atlasUpdateDynamicData();
|
||||||
|
VKCTX->LightDummy.atlasUpdateDynamicData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuffer drawCmd) {
|
void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuffer drawCmd) {
|
||||||
glm::mat4 proj = glm::perspective<float>(75, float(VkInst->Screen.Width)/float(VkInst->Screen.Height), 0.5, std::pow(2, 17));
|
glm::mat4 proj = glm::perspective<float>(75, float(VkInst->Screen.Width)/float(VkInst->Screen.Height), 0.5, std::pow(2, 17));
|
||||||
PCO.ProjView = glm::mat4(Quat);
|
// Сместить в координаты игрока, повернуть относительно взгляда, ещё поворот на 180 и проецировать на экран
|
||||||
//PCO.ProjView *= proj;
|
PCO.ProjView = glm::mat4(1);
|
||||||
PCO.Model = glm::mat4(1); //= glm::rotate(glm::mat4(1), float(gTime/10), glm::vec3(0, 1, 0));
|
PCO.ProjView = glm::translate(PCO.ProjView, -glm::vec3(Pos)/float(Pos::Object_t::BS));
|
||||||
|
PCO.ProjView = proj*glm::mat4(Quat)*glm::rotate(glm::mat4(1), glm::pi<float>(), glm::vec3(0, 1, 0))*PCO.ProjView;
|
||||||
|
PCO.Model = glm::mat4(1);
|
||||||
|
|
||||||
vkCmdBindPipeline(drawCmd, VK_PIPELINE_BIND_POINT_GRAPHICS, NodeStaticOpaquePipeline);
|
vkCmdBindPipeline(drawCmd, VK_PIPELINE_BIND_POINT_GRAPHICS, NodeStaticOpaquePipeline);
|
||||||
vkCmdPushConstants(drawCmd, MainAtlas_LightMap_PipelineLayout,
|
vkCmdPushConstants(drawCmd, MainAtlas_LightMap_PipelineLayout,
|
||||||
@@ -606,9 +652,16 @@ void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuff
|
|||||||
VkDeviceSize vkOffsets = 0;
|
VkDeviceSize vkOffsets = 0;
|
||||||
VkBuffer vkBuffer = VKCTX->TestQuad;
|
VkBuffer vkBuffer = VKCTX->TestQuad;
|
||||||
vkCmdBindVertexBuffers(drawCmd, 0, 1, &vkBuffer, &vkOffsets);
|
vkCmdBindVertexBuffers(drawCmd, 0, 1, &vkBuffer, &vkOffsets);
|
||||||
|
|
||||||
|
for(int i = 0; i < 16; i++) {
|
||||||
|
PCO.Model = glm::rotate(PCO.Model, glm::half_pi<float>()*i/4, glm::vec3(0, 1, 0));
|
||||||
|
vkCmdPushConstants(drawCmd, MainAtlas_LightMap_PipelineLayout,
|
||||||
|
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT, 0, sizeof(WorldPCO), &PCO);
|
||||||
vkCmdDraw(drawCmd, 6, 1, 0, 0);
|
vkCmdDraw(drawCmd, 6, 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void VulkanRenderSession::updateDescriptor_MainAtlas() {
|
void VulkanRenderSession::updateDescriptor_MainAtlas() {
|
||||||
VkDescriptorBufferInfo bufferInfo = VKCTX->MainTest;
|
VkDescriptorBufferInfo bufferInfo = VKCTX->MainTest;
|
||||||
VkDescriptorImageInfo imageInfo = VKCTX->MainTest;
|
VkDescriptorImageInfo imageInfo = VKCTX->MainTest;
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Client/Abstract.hpp"
|
#include "Client/Abstract.hpp"
|
||||||
#include "Common/Abstract.hpp"
|
#include "Common/Abstract.hpp"
|
||||||
#include <Client/Vulkan/Vulkan.hpp>
|
#include <Client/Vulkan/Vulkan.hpp>
|
||||||
#include <glm/ext/matrix_transform.hpp>
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
У движка есть один текстурный атлас VK_IMAGE_VIEW_TYPE_2D_ARRAY(RGBA_UINT) и к нему Storage с инфой о положении текстур
|
У движка есть один текстурный атлас VK_IMAGE_VIEW_TYPE_2D_ARRAY(RGBA_UINT) и к нему Storage с инфой о положении текстур
|
||||||
Это общий для всех VkDescriptorSetLayout и VkDescriptorSet
|
Это общий для всех VkDescriptorSetLayout и VkDescriptorSet
|
||||||
@@ -127,6 +130,10 @@ class VulkanRenderSession : public IRenderSession, public IVulkanDependent {
|
|||||||
|
|
||||||
std::map<TextureId_c, uint16_t> ServerToAtlas;
|
std::map<TextureId_c, uint16_t> ServerToAtlas;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
std::unordered_map<WorldId_c, std::unordered_map<Pos::GlobalChunk, std::unique_ptr<Buffer>>> ChunkVoxelMesh;
|
||||||
|
} External;
|
||||||
|
|
||||||
virtual void free(Vulkan *instance) override;
|
virtual void free(Vulkan *instance) override;
|
||||||
virtual void init(Vulkan *instance) override;
|
virtual void init(Vulkan *instance) override;
|
||||||
|
|
||||||
@@ -153,7 +160,7 @@ public:
|
|||||||
virtual void onDefPortalUpdates(const std::vector<DefPortalId_c> &updates) override;
|
virtual void onDefPortalUpdates(const std::vector<DefPortalId_c> &updates) override;
|
||||||
virtual void onDefEntityUpdates(const std::vector<DefEntityId_c> &updates) override;
|
virtual void onDefEntityUpdates(const std::vector<DefEntityId_c> &updates) override;
|
||||||
|
|
||||||
virtual void onChunksChange(WorldId_c worldId, const std::vector<Pos::GlobalChunk> &changeOrAddList, const std::vector<Pos::GlobalChunk> &remove) override;
|
virtual void onChunksChange(WorldId_c worldId, const std::unordered_set<Pos::GlobalChunk> &changeOrAddList, const std::unordered_set<Pos::GlobalChunk> &remove) override;
|
||||||
virtual void setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) override;
|
virtual void setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) override;
|
||||||
|
|
||||||
glm::mat4 calcViewMatrix(glm::quat quat, glm::vec3 camOffset = glm::vec3(0)) {
|
glm::mat4 calcViewMatrix(glm::quat quat, glm::vec3 camOffset = glm::vec3(0)) {
|
||||||
|
|||||||
@@ -8,10 +8,12 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <glm/geometric.hpp>
|
#include <glm/geometric.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include "SaveBackends/Filesystem.hpp"
|
#include "SaveBackends/Filesystem.hpp"
|
||||||
|
#include "Server/SaveBackend.hpp"
|
||||||
|
|
||||||
namespace LV::Server {
|
namespace LV::Server {
|
||||||
|
|
||||||
@@ -27,9 +29,10 @@ static thread_local std::vector<ContentViewCircle> TL_Circles;
|
|||||||
|
|
||||||
std::vector<ContentViewCircle> GameServer::WorldObj::calcCVCs(ContentViewCircle circle, int depth)
|
std::vector<ContentViewCircle> GameServer::WorldObj::calcCVCs(ContentViewCircle circle, int depth)
|
||||||
{
|
{
|
||||||
TL_Circles.reserve(4096);
|
TL_Circles.clear();
|
||||||
|
TL_Circles.reserve(256);
|
||||||
TL_Circles.push_back(circle);
|
TL_Circles.push_back(circle);
|
||||||
_calcContentViewCircles(TL_Circles.front(), depth);
|
_calcContentViewCircles(circle, depth);
|
||||||
return TL_Circles;
|
return TL_Circles;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,6 +218,42 @@ coro<> GameServer::pushSocketGameProtocol(tcp::socket socket, const std::string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Region* GameServer::forceGetRegion(WorldId_t worldId, Pos::GlobalRegion pos) {
|
||||||
|
auto worldIter = Expanse.Worlds.find(worldId);
|
||||||
|
assert(worldIter != Expanse.Worlds.end());
|
||||||
|
World &world = *worldIter->second;
|
||||||
|
|
||||||
|
auto iterRegion = world.Regions.find(pos);
|
||||||
|
if(iterRegion == world.Regions.end() || !iterRegion->second->IsLoaded) {
|
||||||
|
std::unique_ptr<Region> ®ion = world.Regions[pos];
|
||||||
|
|
||||||
|
if(!region)
|
||||||
|
region = std::make_unique<Region>();
|
||||||
|
|
||||||
|
std::string worldName = "world_"+std::to_string(worldId);
|
||||||
|
if(SaveBackend.World->isExist(worldName, pos)) {
|
||||||
|
SB_Region data;
|
||||||
|
SaveBackend.World->load(worldName, pos, &data);
|
||||||
|
|
||||||
|
region->IsLoaded = true;
|
||||||
|
region->load(&data);
|
||||||
|
} else {
|
||||||
|
region->IsLoaded = true;
|
||||||
|
if(pos.Y == 0) {
|
||||||
|
for(int z = 0; z < 16; z++)
|
||||||
|
for(int x = 0; x < 16; x++) {
|
||||||
|
region->Voxels[x][0][z].push_back({{0, 0, 0}, {255, 255, 255}, 0});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::fill(region->IsChunkChanged_Voxels, region->IsChunkChanged_Voxels+64, ~0);
|
||||||
|
return region.get();
|
||||||
|
} else {
|
||||||
|
return iterRegion->second.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GameServer::init(fs::path worldPath) {
|
void GameServer::init(fs::path worldPath) {
|
||||||
Expanse.Worlds[0] = std::make_unique<World>(0);
|
Expanse.Worlds[0] = std::make_unique<World>(0);
|
||||||
|
|
||||||
@@ -302,16 +341,16 @@ void GameServer::run() {
|
|||||||
// Сон или подгонка длительности такта при высоких нагрузках
|
// Сон или подгонка длительности такта при высоких нагрузках
|
||||||
std::chrono::steady_clock::time_point atTickEnd = std::chrono::steady_clock::now();
|
std::chrono::steady_clock::time_point atTickEnd = std::chrono::steady_clock::now();
|
||||||
float currentWastedTime = double((atTickEnd-atTickStart).count() * std::chrono::steady_clock::duration::period::num) / std::chrono::steady_clock::duration::period::den;
|
float currentWastedTime = double((atTickEnd-atTickStart).count() * std::chrono::steady_clock::duration::period::num) / std::chrono::steady_clock::duration::period::den;
|
||||||
float freeTime = CurrentTickDuration-currentWastedTime-GlobalTickLagTime;
|
GlobalTickLagTime += CurrentTickDuration-currentWastedTime;
|
||||||
|
|
||||||
if(freeTime > 0) {
|
if(GlobalTickLagTime > 0) {
|
||||||
CurrentTickDuration -= PerTickAdjustment;
|
CurrentTickDuration -= PerTickAdjustment;
|
||||||
if(CurrentTickDuration < PerTickDuration)
|
if(CurrentTickDuration < PerTickDuration)
|
||||||
CurrentTickDuration = PerTickDuration;
|
CurrentTickDuration = PerTickDuration;
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(uint32_t(1000*freeTime)));
|
std::this_thread::sleep_for(std::chrono::milliseconds(uint32_t(1000*GlobalTickLagTime)));
|
||||||
|
GlobalTickLagTime = 0;
|
||||||
} else {
|
} else {
|
||||||
GlobalTickLagTime = freeTime;
|
|
||||||
CurrentTickDuration += PerTickAdjustment;
|
CurrentTickDuration += PerTickAdjustment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -558,7 +597,7 @@ void GameServer::stepWorlds() {
|
|||||||
|
|
||||||
if(rPos != pRegion.first || pWorld.first != entity.WorldId) {
|
if(rPos != pRegion.first || pWorld.first != entity.WorldId) {
|
||||||
|
|
||||||
Region *toRegion = Expanse.Worlds[entity.WorldId]->forceLoadOrGetRegion(rPos);
|
Region *toRegion = forceGetRegion(entity.WorldId, rPos);
|
||||||
LocalEntityId_t newId = toRegion->pushEntity(entity);
|
LocalEntityId_t newId = toRegion->pushEntity(entity);
|
||||||
// toRegion->Entityes[newId].WorldId = Если мир изменился
|
// toRegion->Entityes[newId].WorldId = Если мир изменился
|
||||||
|
|
||||||
@@ -808,6 +847,11 @@ void GameServer::stepWorlds() {
|
|||||||
if(needToUnload) {
|
if(needToUnload) {
|
||||||
regionsToRemove.push_back(pRegion.first);
|
regionsToRemove.push_back(pRegion.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Сброс информации об изменившихся данных
|
||||||
|
|
||||||
|
std::fill(region.IsChunkChanged_Voxels, region.IsChunkChanged_Voxels+64, 0);
|
||||||
|
std::fill(region.IsChunkChanged_Nodes, region.IsChunkChanged_Nodes+64, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Pos::GlobalRegion regionPos : regionsToRemove) {
|
for(Pos::GlobalRegion regionPos : regionsToRemove) {
|
||||||
@@ -962,7 +1006,13 @@ void GameServer::stepSendPlayersPackets() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GameServer::stepLoadRegions() {
|
void GameServer::stepLoadRegions() {
|
||||||
|
for(auto &iterWorld : Expanse.Worlds) {
|
||||||
|
for(Pos::GlobalRegion pos : iterWorld.second->NeedToLoad) {
|
||||||
|
forceGetRegion(iterWorld.first, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterWorld.second->NeedToLoad.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameServer::stepGlobal() {
|
void GameServer::stepGlobal() {
|
||||||
|
|||||||
@@ -134,6 +134,9 @@ public:
|
|||||||
// Инициализация игрового протокола для сокета (onSocketAuthorized() может передать сокет в onSocketGame())
|
// Инициализация игрового протокола для сокета (onSocketAuthorized() может передать сокет в onSocketGame())
|
||||||
coro<> pushSocketGameProtocol(tcp::socket socket, const std::string username);
|
coro<> pushSocketGameProtocol(tcp::socket socket, const std::string username);
|
||||||
|
|
||||||
|
/* Загрузит, сгенерирует или просто выдаст регион из мира, который должен существовать */
|
||||||
|
Region* forceGetRegion(WorldId_t worldId, Pos::GlobalRegion pos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init(fs::path worldPath);
|
void init(fs::path worldPath);
|
||||||
void prerun();
|
void prerun();
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ struct SB_Region {
|
|||||||
std::unordered_map<Pos::Local16_u, Node> Nodes;
|
std::unordered_map<Pos::Local16_u, Node> Nodes;
|
||||||
std::unordered_map<DefNodeId_t, std::string> NodeMap;
|
std::unordered_map<DefNodeId_t, std::string> NodeMap;
|
||||||
std::vector<Entity> Entityes;
|
std::vector<Entity> Entityes;
|
||||||
|
std::unordered_map<DefEntityId_t, std::string> EntityMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IWorldSaveBackend {
|
class IWorldSaveBackend {
|
||||||
|
|||||||
@@ -46,17 +46,4 @@ void World::onCEC_RegionsLost(ContentEventController *cec, const std::vector<Pos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Region* World::forceLoadOrGetRegion(Pos::GlobalRegion pos) {
|
|
||||||
std::unique_ptr<Region> ®ion = Regions[pos];
|
|
||||||
if(!region)
|
|
||||||
region = std::make_unique<Region>();
|
|
||||||
|
|
||||||
if(!region->IsLoaded) {
|
|
||||||
region->IsLoaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return region.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,8 +3,10 @@
|
|||||||
#include "Common/Abstract.hpp"
|
#include "Common/Abstract.hpp"
|
||||||
#include "Server/Abstract.hpp"
|
#include "Server/Abstract.hpp"
|
||||||
#include "Server/ContentEventController.hpp"
|
#include "Server/ContentEventController.hpp"
|
||||||
|
#include "Server/SaveBackend.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
namespace LV::Server {
|
namespace LV::Server {
|
||||||
@@ -15,7 +17,7 @@ class Region {
|
|||||||
public:
|
public:
|
||||||
uint64_t IsChunkChanged_Voxels[64] = {0};
|
uint64_t IsChunkChanged_Voxels[64] = {0};
|
||||||
uint64_t IsChunkChanged_Nodes[64] = {0};
|
uint64_t IsChunkChanged_Nodes[64] = {0};
|
||||||
bool IsChanged = false;
|
bool IsChanged = false; // Изменён ли был регион, относительно последнего сохранения
|
||||||
// cx cy cz
|
// cx cy cz
|
||||||
std::vector<VoxelCube> Voxels[16][16][16];
|
std::vector<VoxelCube> Voxels[16][16][16];
|
||||||
// x y cx cy cz
|
// x y cx cy cz
|
||||||
@@ -132,6 +134,15 @@ public:
|
|||||||
|
|
||||||
return LocalEntityId_t(-1);
|
return LocalEntityId_t(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void load(SB_Region *data) {
|
||||||
|
convertRegionVoxelsToChunks(data->Voxels, (std::vector<VoxelCube>*) Voxels);
|
||||||
|
}
|
||||||
|
|
||||||
|
void save(SB_Region *data) {
|
||||||
|
data->Voxels.clear();
|
||||||
|
convertChunkVoxelsToRegion((const std::vector<VoxelCube>*) Voxels, data->Voxels);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class World {
|
class World {
|
||||||
@@ -154,8 +165,6 @@ public:
|
|||||||
void onCEC_RegionsEnter(ContentEventController *cec, const std::vector<Pos::GlobalRegion> &enter);
|
void onCEC_RegionsEnter(ContentEventController *cec, const std::vector<Pos::GlobalRegion> &enter);
|
||||||
void onCEC_RegionsLost(ContentEventController *cec, const std::vector<Pos::GlobalRegion> &lost);
|
void onCEC_RegionsLost(ContentEventController *cec, const std::vector<Pos::GlobalRegion> &lost);
|
||||||
|
|
||||||
Region* forceLoadOrGetRegion(Pos::GlobalRegion pos);
|
|
||||||
|
|
||||||
DefWorldId_t getDefId() const { return DefId; }
|
DefWorldId_t getDefId() const { return DefId; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
BIN
assets/grass.png
Normal file
BIN
assets/grass.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
@@ -8,16 +8,67 @@ layout(location = 0) in FragmentObj {
|
|||||||
|
|
||||||
layout(location = 0) out vec4 Frame;
|
layout(location = 0) out vec4 Frame;
|
||||||
|
|
||||||
uniform layout(set = 0, binding = 0) sampler2DArray MainAtlas;
|
struct InfoSubTexture {
|
||||||
|
uint Flags; // 1 isExist
|
||||||
|
uint PosXY, WidthHeight;
|
||||||
|
|
||||||
|
uint AnimationFrames_AnimationTimePerFrame;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform layout(set = 0, binding = 0) sampler2D MainAtlas;
|
||||||
layout(set = 0, binding = 1) readonly buffer MainAtlasLayoutObj {
|
layout(set = 0, binding = 1) readonly buffer MainAtlasLayoutObj {
|
||||||
vec3 Color;
|
uint SubsCount;
|
||||||
|
uint Counter;
|
||||||
|
uint WidthHeight;
|
||||||
|
|
||||||
|
InfoSubTexture SubTextures[];
|
||||||
} MainAtlasLayout;
|
} MainAtlasLayout;
|
||||||
|
|
||||||
uniform layout(set = 1, binding = 0) sampler2DArray LightMap;
|
uniform layout(set = 1, binding = 0) sampler2D LightMap;
|
||||||
layout(set = 1, binding = 1) readonly buffer LightMapLayoutObj {
|
layout(set = 1, binding = 1) readonly buffer LightMapLayoutObj {
|
||||||
vec3 Color;
|
vec3 Color;
|
||||||
} LightMapLayout;
|
} LightMapLayout;
|
||||||
|
|
||||||
void main() {
|
vec4 atlasColor(uint texId, vec2 uv)
|
||||||
Frame = vec4(1);
|
{
|
||||||
|
uint flags = (texId & 0xffff0000) >> 16;
|
||||||
|
texId &= 0xffff;
|
||||||
|
vec4 color = vec4(uv, 0, 1);
|
||||||
|
|
||||||
|
if((flags & (2 | 4)) > 0)
|
||||||
|
{
|
||||||
|
if((flags & 2) > 0)
|
||||||
|
color = vec4(1, 1, 1, 1);
|
||||||
|
else if((flags & 4) > 0)
|
||||||
|
{
|
||||||
|
color = vec4(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(texId >= uint(MainAtlasLayout.SubsCount))
|
||||||
|
return vec4(((int(gl_FragCoord.x / 128) + int(gl_FragCoord.y / 128)) % 2 ) * vec3(0, 1, 1), 1);
|
||||||
|
else {
|
||||||
|
InfoSubTexture texInfo = MainAtlasLayout.SubTextures[texId];
|
||||||
|
if(texInfo.Flags == 0)
|
||||||
|
return vec4(((int(gl_FragCoord.x / 128) + int(gl_FragCoord.y / 128)) % 2 ) * vec3(1, 0, 1), 1);
|
||||||
|
|
||||||
|
uint posX = texInfo.PosXY & 0xffff;
|
||||||
|
uint posY = (texInfo.PosXY >> 16) & 0xffff;
|
||||||
|
uint width = texInfo.WidthHeight & 0xffff;
|
||||||
|
uint height = (texInfo.WidthHeight >> 16) & 0xffff;
|
||||||
|
uint awidth = MainAtlasLayout.WidthHeight & 0xffff;
|
||||||
|
uint aheight = (MainAtlasLayout.WidthHeight >> 16) & 0xffff;
|
||||||
|
|
||||||
|
if((flags & 1) > 0)
|
||||||
|
color = texture(MainAtlas, vec2((posX+0.5f+uv.x*(width-1))/awidth, (posY+0.5f+(1-uv.y)*(height-1))/aheight));
|
||||||
|
else
|
||||||
|
color = texture(MainAtlas, vec2((posX+uv.x*width)/awidth, (posY+(1-uv.y)*height)/aheight));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
Frame = atlasColor(Fragment.Texture, Fragment.UV);
|
||||||
}
|
}
|
||||||
Binary file not shown.
Reference in New Issue
Block a user