1
0
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:
Daniel Evans 2019-06-03 20:58:17 +01:00
parent 713c94f344
commit 69afb86bee
4 changed files with 149 additions and 22 deletions

View File

@ -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)));
}

View File

@ -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

View File

@ -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();
}

View File

@ -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