#include "vulkan_engine/vulkan/engine.h" #include "precomp.h" #include "socket/packet.h" namespace veng { void Engine::init() { glm::ivec2 window_size_ = vulkan_graphics->window->GetFramebufferSize(); view = glm::lookAt(glm::vec3(0.f, 0.f, -5.f), glm::vec3(0.f, 0.f, 0.f), glm::vec3(0.f, -1.f, 0.f)); projection = glm::perspective( glm::radians(103.f), (std::float_t)window_size_.x / (std::float_t)window_size_.y, 0.1f, 1000.f); vulkan_graphics->SetViewProjection(view, projection); if (BeginPlay != nullptr) BeginPlay(*this); } void Engine::LoadModelAsset(std::string path, std::string name) { veng::Model model(vulkan_graphics); asset_loader_.setPath(path); asset_loader_.loadModel(model); model.vertex_buffer = vulkan_graphics->CreateVertexBuffer(model.vertices); model.index_buffer = vulkan_graphics->CreateIndexBuffer(model.indices); model.material.texture_handle = vulkan_graphics->CreateTexture(asset_loader_.readTexture()); model_assets_[name] = std::move(model); } const Model* Engine::GetStaticModel(std::string name) { if (model_assets_.find(name) != model_assets_.end()) return &model_assets_[name]; return nullptr; } Model* Engine::SpawnLifedModel(std::string asset_name, std::string name, std::float_t lifespan) { if (asset_name == "") { Model model_to_spawn(nullptr); model_to_spawn.asset_name = ""; model_to_spawn.name = name; model_to_spawn.visible = false; model_to_spawn.lifespan = lifespan; models_[name] = std::move(model_to_spawn); return &models_[name]; } if (models_.find(name) == models_.end()) { Model model_to_spawn(*GetStaticModel(asset_name)); model_to_spawn.asset_name = asset_name; model_to_spawn.name = name; model_to_spawn.lifespan = lifespan; models_[name] = std::move(model_to_spawn); return &models_[name]; } std::uint32_t i = 0; for (i = 0; i < std::numeric_limits::max();) { if (models_.find(name + std::to_string(i)) == models_.end()) { Model model_to_spawn(*GetStaticModel(asset_name)); model_to_spawn.asset_name = asset_name; model_to_spawn.name = name + std::to_string(i); model_to_spawn.lifespan = lifespan; models_[name + std::to_string(i)] = std::move(model_to_spawn); break; } i++; } if (i == std::numeric_limits::max() - 1) return nullptr; else return &models_[name + std::to_string(i)]; } Model* Engine::GetSpawnedObject(std::string name) { for (auto it = models_.begin(); it != models_.end();) { if (it->first == name) return &it->second; ++it; } return nullptr; } void Engine::Update() { glm::ivec2 framebuffer_size = vulkan_graphics->window->GetFramebufferSize(); if (framebuffer_size != window_size_ && framebuffer_size.x != 0 && framebuffer_size.y != 0) { window_size_ = framebuffer_size; auto grater = (framebuffer_size.x > framebuffer_size.y) ? framebuffer_size.x : framebuffer_size.y; view = glm::lookAt(glm::vec3(0.f, 0.f, -5.f), glm::vec3(0.f, 0.f, 0.f), glm::vec3(0.f, -1.f, 0.f)); projection = glm::perspective( glm::radians(103.f), (std::float_t)framebuffer_size.x / (std::float_t)framebuffer_size.y, 0.1f, 1000.f); } vulkan_graphics->SetViewProjection(view, projection); if (vulkan_graphics->BeginFrame()) { std::double_t current_time = glfwGetTime(); std::float_t delta_time = static_cast(current_time - last_frame_time_); last_frame_time_ = current_time; if (Tick != nullptr) Tick(*this, delta_time); std::vector models; models.reserve(models_.size()); for (auto it = models_.begin(); it != models_.end();) { auto& model = it->second; if (std::abs(model.lifespan + 1.f) < std::numeric_limits::epsilon()) { models.push_back(&model); ++it; continue; } if (model.lifespan <= 0.f) { it = models_.erase(it); continue; } if (model.shouldBeDestroyed) { it = models_.erase(it); continue; } model.lifespan -= delta_time; models.push_back(&model); ++it; } for (auto& it : models_) { it.second.Update(delta_time); vulkan_graphics->RenderModel(&it.second); } physics_controller_.invokeOnColisionEvent(thread_pool_, {models.data(), models.size()}); vulkan_graphics->EndFrame(); } } void Engine::NetUpdate(std::shared_ptr sock) { NetworkUpload(sock); ResponseToServerAndRefresh(sock); } void Engine::NetworkUpload(std::shared_ptr sock) { std::vector data; for (auto& it : models_) { if (!it.second.networkReplicated) continue; if (!it.second.needsUpdate) continue; Packet::Header header; header.opcode = Packet::Opcode::UPDATEMODEL; std::vector model = it.second.Serialize(); header.body_length = model.size(); std::vector header_serialized = header.Serialize(); data.insert(data.end(), header_serialized.begin(), header_serialized.end()); data.insert(data.end(), model.begin(), model.end()); it.second.needsUpdate = false; } iocp_->send(*sock, data); } int recv_partial(Network::IOCP* iocp, Network::Socket& sock, std::vector& buffer) { size_t total_received = 0; size_t expected = buffer.size(); while (total_received < expected) { if (total_received != 0) Sleep(100); // 너무 빨리 재시도해서 큐가 채워질 틈이 없는 듯? if (sock.sock == 0) return 0; std::vector temp(expected - total_received); size_t received = iocp->recv(sock, temp); if (received == 0) return 0; std::copy(temp.begin(), temp.begin() + received, buffer.begin() + total_received); total_received += received; } return total_received; } void recv_fully(Network::IOCP* iocp, Network::Socket& sock, std::vector& buffer) { size_t total_received = 0; size_t expected = buffer.size(); while (total_received < expected) { if (total_received != 0) Sleep(100); // 너무 빨리 재시도해서 큐가 채워질 틈이 없는 듯? if (sock.sock == 0) return; std::vector temp(expected - total_received); size_t received = iocp->recv(sock, temp); std::copy(temp.begin(), temp.begin() + received, buffer.begin() + total_received); total_received += received; } } void Engine::ResponseToServerAndRefresh(std::shared_ptr sock) { if (sock->sock == 0) return; std::vector recv_data(6); if (recv_partial(iocp_, *sock, recv_data) == 0) return; Packet::Header header; header.Deserialize(recv_data); recv_data.resize(header.body_length); recv_fully(iocp_, *sock, recv_data); switch (header.opcode) { case Packet::Opcode::UPDATEMODEL: { veng::Model model; model.Deserialize(recv_data); bool found = false; for (auto& it : models_) { if (it.second.ID == model.ID) { it.second.position = model.position; it.second.linear_velocity = model.linear_velocity; it.second.linear_acceleration = model.linear_acceleration; it.second.rotation = model.rotation; it.second.angular_velocity = model.angular_velocity; it.second.angular_acceleration = model.angular_acceleration; it.second.scale = model.scale; it.second.transform = model.transform; it.second.original_offset = model.original_offset; it.second.radius = model.radius; it.second.lifespan = model.lifespan; it.second.visible = model.visible; it.second.colision = model.colision; spdlog::info("model updated: {}", model.name); spdlog::info("model pos: ({},{},{})", model.position.x, model.position.y, model.position.z); found = true; break; } } if (!found) { auto spawnedModel = SpawnLifedModel(model.asset_name, model.name, model.lifespan); spawnedModel->ID = model.ID; spawnedModel->position = model.position; spawnedModel->linear_velocity = model.linear_velocity; spawnedModel->linear_acceleration = model.linear_acceleration; spawnedModel->rotation = model.rotation; spawnedModel->angular_velocity = model.angular_velocity; spawnedModel->angular_acceleration = model.angular_acceleration; spawnedModel->scale = model.scale; spawnedModel->transform = model.transform; spawnedModel->original_offset = model.original_offset; spawnedModel->radius = model.radius; spawnedModel->lifespan = model.lifespan; spawnedModel->visible = model.visible; spawnedModel->colision = model.colision; spawnedModel->networkReplicated = false; spdlog::info("model spawned: {}", model.ID.snowflake); } } break; default: spdlog::error("unknown data type"); } } } // namespace veng