188 lines
6.1 KiB
C++
188 lines
6.1 KiB
C++
#include "Engine/EngineSceneViewportBridge.h"
|
|
|
|
#include <XCEngine/Components/CameraComponent.h>
|
|
#include <XCEngine/Components/GameObject.h>
|
|
#include <XCEngine/Components/TransformComponent.h>
|
|
#include <XCEngine/Rendering/Execution/SceneRenderer.h>
|
|
#include <XCEngine/Rendering/Picking/RenderObjectIdRegistry.h>
|
|
#include <XCEngine/Scene/Scene.h>
|
|
#include <XCEngine/Scene/SceneManager.h>
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <vector>
|
|
|
|
namespace XCEngine::UI::Editor::App {
|
|
|
|
namespace {
|
|
|
|
using ::XCEngine::Components::GameObject;
|
|
using ::XCEngine::Components::Scene;
|
|
using ::XCEngine::Components::SceneManager;
|
|
using ::XCEngine::Components::TransformComponent;
|
|
using ::XCEngine::Math::Quaternion;
|
|
using ::XCEngine::Math::Vector3;
|
|
using ::XCEngine::Rendering::RenderObjectId;
|
|
using ::XCEngine::Rendering::RenderObjectIdRegistry;
|
|
|
|
Scene* ResolvePrimaryScene(SceneManager& sceneManager) {
|
|
if (Scene* activeScene = sceneManager.GetActiveScene();
|
|
activeScene != nullptr) {
|
|
return activeScene;
|
|
}
|
|
|
|
const std::vector<Scene*> scenes = sceneManager.GetAllScenes();
|
|
if (!scenes.empty() && scenes.front() != nullptr) {
|
|
sceneManager.SetActiveScene(scenes.front());
|
|
return scenes.front();
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
EngineSceneViewportBridge::~EngineSceneViewportBridge() = default;
|
|
|
|
void EngineSceneViewportBridge::Shutdown() {
|
|
m_sceneViewportCamera = nullptr;
|
|
m_sceneViewportCameraObject.reset();
|
|
}
|
|
|
|
SceneViewportFramePlanBuildStatus EngineSceneViewportBridge::BuildFramePlan(
|
|
const SceneViewportRenderRequest& request,
|
|
const ::XCEngine::Rendering::RenderContext& renderContext,
|
|
const ::XCEngine::Rendering::RenderSurface& surface,
|
|
::XCEngine::Rendering::CameraFramePlan& outFramePlan) {
|
|
outFramePlan = {};
|
|
if (!request.IsValid()) {
|
|
return SceneViewportFramePlanBuildStatus::InvalidRequest;
|
|
}
|
|
|
|
Scene* scene = ResolvePrimaryScene(SceneManager::Get());
|
|
if (scene == nullptr) {
|
|
return SceneViewportFramePlanBuildStatus::NoActiveScene;
|
|
}
|
|
|
|
if (!EnsureSceneViewportCamera()) {
|
|
return SceneViewportFramePlanBuildStatus::Failed;
|
|
}
|
|
|
|
ConfigureSceneViewportCamera(request.camera);
|
|
const std::vector<::XCEngine::Rendering::CameraFramePlan> framePlans =
|
|
m_sceneViewportRenderer.BuildFramePlans(
|
|
*scene,
|
|
m_sceneViewportCamera,
|
|
renderContext,
|
|
surface);
|
|
if (framePlans.empty() || !framePlans.front().IsValid()) {
|
|
return SceneViewportFramePlanBuildStatus::Failed;
|
|
}
|
|
|
|
outFramePlan = framePlans.front();
|
|
return SceneViewportFramePlanBuildStatus::Success;
|
|
}
|
|
|
|
bool EngineSceneViewportBridge::RenderFramePlan(
|
|
const ::XCEngine::Rendering::CameraFramePlan& framePlan) {
|
|
return framePlan.IsValid() &&
|
|
m_sceneViewportRenderer.Render(framePlan);
|
|
}
|
|
|
|
bool EngineSceneViewportBridge::TryResolveActiveSceneRenderObjectId(
|
|
RenderObjectId renderObjectId,
|
|
EditorSceneObjectId& outRuntimeObjectId) const {
|
|
outRuntimeObjectId = kInvalidEditorSceneObjectId;
|
|
|
|
std::uint64_t runtimeObjectId = kInvalidEditorSceneObjectId;
|
|
if (!RenderObjectIdRegistry::Get().TryResolveRuntimeObjectId(
|
|
renderObjectId,
|
|
runtimeObjectId)) {
|
|
return false;
|
|
}
|
|
|
|
Scene* scene = ResolvePrimaryScene(SceneManager::Get());
|
|
GameObject* gameObject =
|
|
scene != nullptr
|
|
? scene->FindByID(static_cast<EditorSceneObjectId>(runtimeObjectId))
|
|
: nullptr;
|
|
if (gameObject == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
outRuntimeObjectId = gameObject->GetID();
|
|
return true;
|
|
}
|
|
|
|
bool EngineSceneViewportBridge::EnsureSceneViewportCamera() {
|
|
if (m_sceneViewportCameraObject != nullptr &&
|
|
m_sceneViewportCamera != nullptr) {
|
|
return true;
|
|
}
|
|
|
|
m_sceneViewportCamera = nullptr;
|
|
m_sceneViewportCameraObject =
|
|
std::make_unique<GameObject>("EditorSceneViewportCamera");
|
|
m_sceneViewportCamera =
|
|
m_sceneViewportCameraObject->AddComponent<
|
|
::XCEngine::Components::CameraComponent>();
|
|
if (m_sceneViewportCamera == nullptr) {
|
|
m_sceneViewportCameraObject.reset();
|
|
return false;
|
|
}
|
|
|
|
m_sceneViewportCamera->SetPrimary(false);
|
|
m_sceneViewportCamera->SetProjectionType(
|
|
::XCEngine::Components::CameraProjectionType::Perspective);
|
|
m_sceneViewportCamera->SetFieldOfView(60.0f);
|
|
m_sceneViewportCamera->SetNearClipPlane(0.03f);
|
|
m_sceneViewportCamera->SetFarClipPlane(2000.0f);
|
|
return true;
|
|
}
|
|
|
|
void EngineSceneViewportBridge::ConfigureSceneViewportCamera(
|
|
const EditorSceneCameraSnapshot& snapshot) {
|
|
if (!EnsureSceneViewportCamera() ||
|
|
m_sceneViewportCameraObject == nullptr ||
|
|
m_sceneViewportCamera == nullptr) {
|
|
return;
|
|
}
|
|
|
|
TransformComponent* transform =
|
|
m_sceneViewportCameraObject->GetTransform();
|
|
if (transform == nullptr) {
|
|
return;
|
|
}
|
|
|
|
Vector3 forward = snapshot.forward.SqrMagnitude() >
|
|
::XCEngine::Math::EPSILON
|
|
? snapshot.forward.Normalized()
|
|
: Vector3::Forward();
|
|
Vector3 up = snapshot.up.SqrMagnitude() >
|
|
::XCEngine::Math::EPSILON
|
|
? snapshot.up.Normalized()
|
|
: Vector3::Up();
|
|
if (Vector3::Cross(forward, up).SqrMagnitude() <=
|
|
::XCEngine::Math::EPSILON) {
|
|
up = std::abs(Vector3::Dot(forward, Vector3::Up())) < 0.999f
|
|
? Vector3::Up()
|
|
: Vector3::Right();
|
|
}
|
|
|
|
transform->SetPosition(snapshot.position);
|
|
transform->SetRotation(Quaternion::LookRotation(forward, up));
|
|
|
|
const float nearClipPlane = (std::max)(snapshot.nearClipPlane, 0.001f);
|
|
const float farClipPlane =
|
|
(std::max)(snapshot.farClipPlane, nearClipPlane + 0.001f);
|
|
m_sceneViewportCamera->SetPrimary(false);
|
|
m_sceneViewportCamera->SetProjectionType(
|
|
::XCEngine::Components::CameraProjectionType::Perspective);
|
|
m_sceneViewportCamera->SetFieldOfView(
|
|
std::clamp(snapshot.verticalFovDegrees, 1.0f, 179.0f));
|
|
m_sceneViewportCamera->SetNearClipPlane(nearClipPlane);
|
|
m_sceneViewportCamera->SetFarClipPlane(farClipPlane);
|
|
}
|
|
|
|
} // namespace XCEngine::UI::Editor::App
|