mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-25 11:52:40 +01:00
Map IPL Viewer
This commit is contained in:
parent
713c94f344
commit
69afb86bee
@ -26,6 +26,11 @@ static constexpr std::array<
|
||||
{GameRenderer::ZoneCylinderB, "zonecylb.dff", "particle"},
|
||||
{GameRenderer::Arrow, "arrow.dff", ""}}};
|
||||
const auto kViewerFov = glm::radians(90.f);
|
||||
|
||||
auto viewAnglesToQuat(float yaw, float pitch) {
|
||||
return glm::angleAxis(glm::radians(yaw), glm::vec3(0.f, 0.f, -1.f)) *
|
||||
glm::angleAxis(glm::radians(pitch), glm::vec3(0.f, 1.f, 0.f));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
RWViewer::RWViewer(Logger& log, const std::optional<RWArgConfigLayer>& args)
|
||||
@ -47,6 +52,7 @@ RWViewer::RWViewer(Logger& log, const std::optional<RWArgConfigLayer>& args)
|
||||
|
||||
data_.load();
|
||||
textViewer_.emplace(data_);
|
||||
iplViewer_.emplace(log, data_);
|
||||
|
||||
for (const auto& [specialModel, fileName, name] : kSpecialModels) {
|
||||
auto model = data_.loadClump(fileName, name);
|
||||
@ -133,15 +139,15 @@ bool RWViewer::updateInput() {
|
||||
break;
|
||||
|
||||
case SDL_MOUSEWHEEL:
|
||||
viewParams_.z =
|
||||
glm::max(1.f, viewParams_.z +
|
||||
-(event.wheel.y * viewParams_.z * 0.1f));
|
||||
viewAngles_.z =
|
||||
glm::max(1.f, viewAngles_.z +
|
||||
-(event.wheel.y * viewAngles_.z * 0.1f));
|
||||
break;
|
||||
|
||||
case SDL_MOUSEMOTION:
|
||||
if (mouseMode_ == MouseMode::Dragging) {
|
||||
viewParams_.x += event.motion.xrel * 0.5f;
|
||||
viewParams_.y += event.motion.yrel * 0.5f;
|
||||
viewAngles_.x += event.motion.xrel * 0.5f;
|
||||
viewAngles_.y += event.motion.yrel * 0.5f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -166,26 +172,28 @@ void RWViewer::render(float alpha, float time) {
|
||||
|
||||
ViewCamera viewCam{};
|
||||
viewCam.frustum.fov = kViewerFov;
|
||||
|
||||
if (viewedObject_) {
|
||||
auto rotation = glm::angleAxis(glm::radians(viewParams_.x),
|
||||
glm::vec3(0.f, 0.f, -1.f)) *
|
||||
glm::angleAxis(glm::radians(viewParams_.y),
|
||||
glm::vec3(0.f, 1.f, 0.f));
|
||||
auto viewDirection = rotation * glm::vec3{-1.f, 0.f, 0.f};
|
||||
viewCam.position = viewDirection * viewParams_.z;
|
||||
viewCam.rotation = rotation;
|
||||
}
|
||||
|
||||
viewCam.frustum.aspectRatio =
|
||||
windowSize.x / static_cast<float>(windowSize.y);
|
||||
|
||||
viewCam.rotation = viewAnglesToQuat(viewAngles_.x, viewAngles_.y);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
|
||||
renderer_.getRenderer().pushDebugGroup("World");
|
||||
|
||||
renderer_.renderWorld(world_.get(), viewCam, alpha);
|
||||
switch (viewMode_) {
|
||||
case ViewMode::Model: {
|
||||
auto viewDirection = viewCam.rotation * glm::vec3{-1.f, 0.f, 0.f};
|
||||
viewCam.position = viewDirection * viewAngles_.z;
|
||||
renderer_.renderWorld(world_.get(), viewCam, alpha);
|
||||
break;
|
||||
}
|
||||
case ViewMode::World:
|
||||
viewCam.position = viewPosition_;
|
||||
renderer_.renderWorld(iplViewer_->world(), viewCam, alpha);
|
||||
break;
|
||||
}
|
||||
|
||||
renderer_.getRenderer().popDebugGroup();
|
||||
|
||||
@ -196,6 +204,7 @@ void RWViewer::render(float alpha, float time) {
|
||||
}
|
||||
|
||||
void RWViewer::globalKeyEvent(const SDL_Event& event) {
|
||||
auto r = viewAnglesToQuat(viewAngles_.x, viewAngles_.y);
|
||||
switch (event.key.keysym.sym) {
|
||||
case SDLK_LEFTBRACKET:
|
||||
world_->offsetGameTime(-30);
|
||||
@ -203,6 +212,24 @@ void RWViewer::globalKeyEvent(const SDL_Event& event) {
|
||||
case SDLK_RIGHTBRACKET:
|
||||
world_->offsetGameTime(30);
|
||||
break;
|
||||
|
||||
case SDLK_w:
|
||||
case SDLK_UP:
|
||||
viewPosition_ += r * glm::vec3{1.f, 0.f, 0.f};
|
||||
break;
|
||||
case SDLK_s:
|
||||
case SDLK_DOWN:
|
||||
viewPosition_ -= r * glm::vec3{1.f, 0.f, 0.f};
|
||||
break;
|
||||
case SDLK_a:
|
||||
case SDLK_LEFT:
|
||||
viewPosition_ += r * glm::vec3{0.f, 1.f, 0.f};
|
||||
break;
|
||||
case SDLK_d:
|
||||
case SDLK_RIGHT:
|
||||
viewPosition_ -= r * glm::vec3{0.f, 1.f, 0.f};
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -220,7 +247,10 @@ void RWViewer::drawMenu() {
|
||||
}
|
||||
});
|
||||
menu("View", [&]() {
|
||||
ImGui::MenuItem("Model", "", viewedObject_ != nullptr);
|
||||
if (ImGui::MenuItem("Model", "", viewMode_ == ViewMode::Model))
|
||||
viewMode_ = ViewMode::Model;
|
||||
if (ImGui::MenuItem("World", "", viewMode_ == ViewMode::World))
|
||||
viewMode_ = ViewMode::World;
|
||||
if (ImGui::MenuItem("Remove Object", "")) {
|
||||
if (viewedObject_) {
|
||||
world_->destroyObject(viewedObject_);
|
||||
@ -231,6 +261,7 @@ void RWViewer::drawMenu() {
|
||||
menu("Windows", [&]() {
|
||||
ImGui::MenuItem("Models", "", &showModelList_);
|
||||
ImGui::MenuItem("Texts", "", &showTextViewer_);
|
||||
ImGui::MenuItem("Map", "", &showIplViewer_);
|
||||
ImGui::Separator();
|
||||
ImGui::MenuItem("Demo", "", &showImGuiDemo_);
|
||||
});
|
||||
@ -297,6 +328,9 @@ void RWViewer::drawWindows() {
|
||||
window("Texts", showTextViewer_, {920, 320},
|
||||
[&]() { textViewer_->draw(renderer_); });
|
||||
|
||||
window("Map", showIplViewer_, {320, 320},
|
||||
[&]() { iplViewer_->draw(renderer_); });
|
||||
|
||||
if (showImGuiDemo_) ImGui::ShowDemoWindow(&showImGuiDemo_);
|
||||
}
|
||||
|
||||
@ -327,6 +361,7 @@ void RWViewer::drawModelWindow(ModelID id) {
|
||||
}
|
||||
|
||||
void RWViewer::viewModel(ModelID model) {
|
||||
viewMode_ = ViewMode::Model;
|
||||
if (viewedObject_) {
|
||||
world_->destroyObject(viewedObject_);
|
||||
viewedObject_ = nullptr;
|
||||
@ -357,5 +392,5 @@ void RWViewer::viewModel(ModelID model) {
|
||||
radius = glm::length(geo.center) + geo.radius;
|
||||
}
|
||||
constexpr auto kViewSlop = 1.f;
|
||||
viewParams_.z = kViewSlop * ((radius * 2) / (glm::tan(kViewerFov / 2.f)));
|
||||
viewAngles_.z = kViewSlop * ((radius * 2) / (glm::tan(kViewerFov / 2.f)));
|
||||
}
|
||||
|
@ -71,12 +71,22 @@ private:
|
||||
bool showTextViewer_ = false;
|
||||
std::optional<TextViewer> textViewer_;
|
||||
bool showImGuiDemo_ = false;
|
||||
bool showIplViewer_ = false;
|
||||
std::optional<IPLViewer> iplViewer_;
|
||||
std::set<ModelID> showModels_;
|
||||
|
||||
GameObject* viewedObject_ = nullptr;
|
||||
glm::vec3 viewParams_{};
|
||||
enum MouseMode { Hovering, Dragging };
|
||||
enum class ViewMode {
|
||||
World,
|
||||
Model,
|
||||
};
|
||||
ViewMode viewMode_ = ViewMode::World;
|
||||
enum class MouseMode { Hovering, Dragging };
|
||||
MouseMode mouseMode_ = MouseMode::Hovering;
|
||||
|
||||
GameObject* viewedObject_ = nullptr;
|
||||
glm::vec3 viewAngles_{};
|
||||
|
||||
glm::vec3 viewPosition_{};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,10 +1,14 @@
|
||||
#include <viewer/RWViewerWindows.hpp>
|
||||
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <loaders/LoaderGXT.hpp>
|
||||
#include <objects/InstanceObject.hpp>
|
||||
#include <platform/FileHandle.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
std::array<int, 3> kFonts{{FONT_PAGER, FONT_PRICEDOWN, FONT_ARIAL}};
|
||||
std::array<const char*, 3> kFontNames{{"Pager", "Pricedown", "Arial"}};
|
||||
@ -158,3 +162,47 @@ void TextViewer::draw(GameRenderer& r) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IPLViewer::IPLViewer(Logger& log, GameData& data)
|
||||
: data_(data), world_(std::make_unique<GameWorld>(&log, &data)) {
|
||||
std::transform(begin(data_.iplLocations), end(data_.iplLocations),
|
||||
std::back_inserter(ipls_), [](const auto& a) -> IPLFileData {
|
||||
return {false, a.first, a.second, {}, {}};
|
||||
});
|
||||
world_->state = &state_;
|
||||
}
|
||||
|
||||
void IPLViewer::draw(GameRenderer& r) {
|
||||
for (auto& ipl : ipls_) {
|
||||
if (ImGui::Checkbox(ipl.name.c_str(), &ipl.enabled)) {
|
||||
if (ipl.enabled)
|
||||
showIPL(ipl);
|
||||
else
|
||||
hideIPL(ipl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IPLViewer::showIPL(IPLViewer::IPLFileData& ipl) {
|
||||
if (ipl.loader.m_instances.empty()) {
|
||||
ipl.loader.load(ipl.path);
|
||||
}
|
||||
|
||||
for (const auto& inst : ipl.loader.m_instances) {
|
||||
auto instance = world_->createInstance(inst.id, inst.pos, inst.rot);
|
||||
if (!instance) {
|
||||
world_->logger->error("World", "No object data for instance " +
|
||||
std::to_string(inst.id) +
|
||||
" in " + ipl.name);
|
||||
} else {
|
||||
ipl.objects.push_back(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IPLViewer::hideIPL(IPLViewer::IPLFileData& ipl) {
|
||||
for (auto& object : ipl.objects) {
|
||||
world_->destroyObject(object);
|
||||
}
|
||||
ipl.objects.clear();
|
||||
}
|
||||
|
@ -2,10 +2,16 @@
|
||||
#define RWGAME_RWVIEWERWINDOWS_HPP
|
||||
|
||||
#include <engine/GameData.hpp>
|
||||
#include <engine/GameState.hpp>
|
||||
#include <fonts/GameTexts.hpp>
|
||||
#include <loaders/LoaderIPL.hpp>
|
||||
#include <objects/GameObject.hpp>
|
||||
#include <render/GameRenderer.hpp>
|
||||
|
||||
#include <core/Logger.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class TextViewer {
|
||||
public:
|
||||
@ -26,4 +32,32 @@ private:
|
||||
bool drawPreview_ = true;
|
||||
};
|
||||
|
||||
class IPLViewer {
|
||||
public:
|
||||
IPLViewer(Logger&, GameData& data);
|
||||
|
||||
void draw(GameRenderer& r);
|
||||
|
||||
GameWorld* world() const {
|
||||
return world_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
struct IPLFileData {
|
||||
bool enabled;
|
||||
std::string name;
|
||||
std::string path;
|
||||
LoaderIPL loader;
|
||||
std::vector<GameObject*> objects;
|
||||
};
|
||||
|
||||
void showIPL(IPLFileData&);
|
||||
void hideIPL(IPLFileData&);
|
||||
|
||||
GameData& data_;
|
||||
GameState state_;
|
||||
std::unique_ptr<GameWorld> world_;
|
||||
std::vector<IPLFileData> ipls_;
|
||||
};
|
||||
|
||||
#endif // RWGAME_RWVIEWERWINDOWS_HPP
|
||||
|
Loading…
Reference in New Issue
Block a user