Extract scene viewport overlay frame cache module
This commit is contained in:
@@ -89,6 +89,7 @@ add_executable(${PROJECT_NAME} WIN32
|
||||
src/Viewport/SceneViewportTransformGizmoCoordinator.cpp
|
||||
src/Viewport/SceneViewportOrientationGizmo.cpp
|
||||
src/Viewport/SceneViewportOverlayBuilder.cpp
|
||||
src/Viewport/SceneViewportOverlayFrameCache.cpp
|
||||
src/Viewport/SceneViewportOverlaySpriteResources.cpp
|
||||
src/Viewport/SceneViewportOverlayProviders.cpp
|
||||
src/Viewport/Passes/SceneViewportEditorOverlayPass.cpp
|
||||
|
||||
200
editor/src/Viewport/SceneViewportOverlayFrameCache.cpp
Normal file
200
editor/src/Viewport/SceneViewportOverlayFrameCache.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
#include "Viewport/SceneViewportOverlayFrameCache.h"
|
||||
|
||||
#include <XCEngine/Components/CameraComponent.h>
|
||||
#include <XCEngine/Components/GameObject.h>
|
||||
#include <XCEngine/Components/LightComponent.h>
|
||||
#include <XCEngine/Components/TransformComponent.h>
|
||||
#include <XCEngine/Scene/Scene.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr uint64_t kSceneViewportOverlaySignatureOffsetBasis = 14695981039346656037ull;
|
||||
constexpr uint64_t kSceneViewportOverlaySignaturePrime = 1099511628211ull;
|
||||
|
||||
void HashSceneViewportOverlayBytes(uint64_t& hash, const void* data, size_t size) {
|
||||
const auto* bytes = static_cast<const uint8_t*>(data);
|
||||
for (size_t index = 0; index < size; ++index) {
|
||||
hash ^= static_cast<uint64_t>(bytes[index]);
|
||||
hash *= kSceneViewportOverlaySignaturePrime;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
void HashSceneViewportOverlayValue(uint64_t& hash, const TValue& value) {
|
||||
HashSceneViewportOverlayBytes(hash, &value, sizeof(TValue));
|
||||
}
|
||||
|
||||
void HashSceneViewportOverlayFloat(uint64_t& hash, float value) {
|
||||
uint32_t bits = 0u;
|
||||
std::memcpy(&bits, &value, sizeof(bits));
|
||||
HashSceneViewportOverlayValue(hash, bits);
|
||||
}
|
||||
|
||||
void HashSceneViewportOverlayVector3(uint64_t& hash, const Math::Vector3& value) {
|
||||
HashSceneViewportOverlayFloat(hash, value.x);
|
||||
HashSceneViewportOverlayFloat(hash, value.y);
|
||||
HashSceneViewportOverlayFloat(hash, value.z);
|
||||
}
|
||||
|
||||
void HashSceneViewportOverlayQuaternion(uint64_t& hash, const Math::Quaternion& value) {
|
||||
HashSceneViewportOverlayFloat(hash, value.x);
|
||||
HashSceneViewportOverlayFloat(hash, value.y);
|
||||
HashSceneViewportOverlayFloat(hash, value.z);
|
||||
HashSceneViewportOverlayFloat(hash, value.w);
|
||||
}
|
||||
|
||||
void HashSceneViewportOverlayRect(uint64_t& hash, const Math::Rect& value) {
|
||||
HashSceneViewportOverlayFloat(hash, value.x);
|
||||
HashSceneViewportOverlayFloat(hash, value.y);
|
||||
HashSceneViewportOverlayFloat(hash, value.width);
|
||||
HashSceneViewportOverlayFloat(hash, value.height);
|
||||
}
|
||||
|
||||
void HashSceneViewportOverlayTransform(uint64_t& hash, const Components::TransformComponent& transform) {
|
||||
HashSceneViewportOverlayVector3(hash, transform.GetPosition());
|
||||
HashSceneViewportOverlayQuaternion(hash, transform.GetRotation());
|
||||
HashSceneViewportOverlayVector3(hash, transform.GetScale());
|
||||
}
|
||||
|
||||
bool AreEqualSceneViewportVector3(const Math::Vector3& lhs, const Math::Vector3& rhs) {
|
||||
constexpr float kEpsilon = 1e-4f;
|
||||
return std::abs(lhs.x - rhs.x) <= kEpsilon &&
|
||||
std::abs(lhs.y - rhs.y) <= kEpsilon &&
|
||||
std::abs(lhs.z - rhs.z) <= kEpsilon;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void ResetSceneViewportOverlayFrameCacheState(
|
||||
SceneViewportOverlayFrameCacheState& cacheState) {
|
||||
cacheState = {};
|
||||
}
|
||||
|
||||
void ResolveSceneViewportOverlayFrameViewportSize(
|
||||
uint32_t requestedWidth,
|
||||
uint32_t requestedHeight,
|
||||
uint32_t renderWidth,
|
||||
uint32_t renderHeight,
|
||||
uint32_t& outWidth,
|
||||
uint32_t& outHeight) {
|
||||
outWidth = requestedWidth > 0u ? requestedWidth : renderWidth;
|
||||
outHeight = requestedHeight > 0u ? requestedHeight : renderHeight;
|
||||
}
|
||||
|
||||
bool AreEqualSceneViewportOverlayData(
|
||||
const SceneViewportOverlayData& lhs,
|
||||
const SceneViewportOverlayData& rhs) {
|
||||
constexpr float kEpsilon = 1e-4f;
|
||||
return lhs.valid == rhs.valid &&
|
||||
AreEqualSceneViewportVector3(lhs.cameraPosition, rhs.cameraPosition) &&
|
||||
AreEqualSceneViewportVector3(lhs.cameraForward, rhs.cameraForward) &&
|
||||
AreEqualSceneViewportVector3(lhs.cameraRight, rhs.cameraRight) &&
|
||||
AreEqualSceneViewportVector3(lhs.cameraUp, rhs.cameraUp) &&
|
||||
std::abs(lhs.verticalFovDegrees - rhs.verticalFovDegrees) <= kEpsilon &&
|
||||
std::abs(lhs.nearClipPlane - rhs.nearClipPlane) <= kEpsilon &&
|
||||
std::abs(lhs.farClipPlane - rhs.farClipPlane) <= kEpsilon &&
|
||||
std::abs(lhs.orbitDistance - rhs.orbitDistance) <= kEpsilon;
|
||||
}
|
||||
|
||||
uint64_t BuildSceneViewportOverlayContentSignature(
|
||||
const Components::Scene* scene,
|
||||
const std::vector<uint64_t>& selectedObjectIds) {
|
||||
uint64_t hash = kSceneViewportOverlaySignatureOffsetBasis;
|
||||
|
||||
HashSceneViewportOverlayValue(hash, static_cast<uint64_t>(selectedObjectIds.size()));
|
||||
for (uint64_t entityId : selectedObjectIds) {
|
||||
HashSceneViewportOverlayValue(hash, entityId);
|
||||
}
|
||||
|
||||
if (scene == nullptr) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
for (Components::CameraComponent* camera : scene->FindObjectsOfType<Components::CameraComponent>()) {
|
||||
Components::GameObject* gameObject = camera != nullptr ? camera->GetGameObject() : nullptr;
|
||||
HashSceneViewportOverlayValue(hash, static_cast<uint8_t>(1u));
|
||||
HashSceneViewportOverlayValue(hash, gameObject != nullptr ? gameObject->GetID() : 0ull);
|
||||
HashSceneViewportOverlayValue(hash, camera != nullptr && camera->IsEnabled());
|
||||
HashSceneViewportOverlayValue(hash, gameObject != nullptr && gameObject->IsActiveInHierarchy());
|
||||
if (camera == nullptr ||
|
||||
gameObject == nullptr ||
|
||||
!camera->IsEnabled() ||
|
||||
!gameObject->IsActiveInHierarchy() ||
|
||||
gameObject->GetTransform() == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
HashSceneViewportOverlayTransform(hash, *gameObject->GetTransform());
|
||||
HashSceneViewportOverlayValue(hash, static_cast<uint32_t>(camera->GetProjectionType()));
|
||||
HashSceneViewportOverlayFloat(hash, camera->GetFieldOfView());
|
||||
HashSceneViewportOverlayFloat(hash, camera->GetOrthographicSize());
|
||||
HashSceneViewportOverlayFloat(hash, camera->GetNearClipPlane());
|
||||
HashSceneViewportOverlayFloat(hash, camera->GetFarClipPlane());
|
||||
HashSceneViewportOverlayRect(hash, camera->GetViewportRect());
|
||||
}
|
||||
|
||||
for (Components::LightComponent* light : scene->FindObjectsOfType<Components::LightComponent>()) {
|
||||
Components::GameObject* gameObject = light != nullptr ? light->GetGameObject() : nullptr;
|
||||
HashSceneViewportOverlayValue(hash, static_cast<uint8_t>(2u));
|
||||
HashSceneViewportOverlayValue(hash, gameObject != nullptr ? gameObject->GetID() : 0ull);
|
||||
HashSceneViewportOverlayValue(hash, light != nullptr && light->IsEnabled());
|
||||
HashSceneViewportOverlayValue(hash, gameObject != nullptr && gameObject->IsActiveInHierarchy());
|
||||
if (light == nullptr ||
|
||||
gameObject == nullptr ||
|
||||
!light->IsEnabled() ||
|
||||
!gameObject->IsActiveInHierarchy() ||
|
||||
gameObject->GetTransform() == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
HashSceneViewportOverlayTransform(hash, *gameObject->GetTransform());
|
||||
HashSceneViewportOverlayValue(hash, static_cast<uint32_t>(light->GetLightType()));
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
bool ShouldRebuildSceneViewportOverlayFrameCache(
|
||||
const SceneViewportOverlayFrameCacheState& cacheState,
|
||||
const Components::Scene* scene,
|
||||
const SceneViewportOverlayData& overlay,
|
||||
uint32_t viewportWidth,
|
||||
uint32_t viewportHeight,
|
||||
const std::vector<uint64_t>& selectedObjectIds,
|
||||
uint64_t contentSignature,
|
||||
bool transformGizmoOverlayDirty) {
|
||||
return transformGizmoOverlayDirty ||
|
||||
!cacheState.cached ||
|
||||
cacheState.scene != scene ||
|
||||
cacheState.viewportWidth != viewportWidth ||
|
||||
cacheState.viewportHeight != viewportHeight ||
|
||||
cacheState.selectedObjectIds != selectedObjectIds ||
|
||||
cacheState.contentSignature != contentSignature ||
|
||||
!AreEqualSceneViewportOverlayData(cacheState.frameData.overlay, overlay);
|
||||
}
|
||||
|
||||
void UpdateSceneViewportOverlayFrameCacheState(
|
||||
SceneViewportOverlayFrameCacheState& cacheState,
|
||||
const Components::Scene* scene,
|
||||
uint32_t viewportWidth,
|
||||
uint32_t viewportHeight,
|
||||
const std::vector<uint64_t>& selectedObjectIds,
|
||||
uint64_t contentSignature,
|
||||
const SceneViewportOverlayFrameData& frameData) {
|
||||
cacheState.frameData = frameData;
|
||||
cacheState.scene = scene;
|
||||
cacheState.selectedObjectIds = selectedObjectIds;
|
||||
cacheState.viewportWidth = viewportWidth;
|
||||
cacheState.viewportHeight = viewportHeight;
|
||||
cacheState.contentSignature = contentSignature;
|
||||
cacheState.cached = true;
|
||||
}
|
||||
|
||||
} // namespace Editor
|
||||
} // namespace XCEngine
|
||||
64
editor/src/Viewport/SceneViewportOverlayFrameCache.h
Normal file
64
editor/src/Viewport/SceneViewportOverlayFrameCache.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include "SceneViewportEditorOverlayData.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
class Scene;
|
||||
} // namespace Components
|
||||
|
||||
namespace Editor {
|
||||
|
||||
struct SceneViewportOverlayFrameCacheState {
|
||||
SceneViewportOverlayFrameData frameData = {};
|
||||
const Components::Scene* scene = nullptr;
|
||||
std::vector<uint64_t> selectedObjectIds = {};
|
||||
uint32_t viewportWidth = 0u;
|
||||
uint32_t viewportHeight = 0u;
|
||||
uint64_t contentSignature = 0u;
|
||||
bool cached = false;
|
||||
};
|
||||
|
||||
void ResetSceneViewportOverlayFrameCacheState(
|
||||
SceneViewportOverlayFrameCacheState& cacheState);
|
||||
|
||||
void ResolveSceneViewportOverlayFrameViewportSize(
|
||||
uint32_t requestedWidth,
|
||||
uint32_t requestedHeight,
|
||||
uint32_t renderWidth,
|
||||
uint32_t renderHeight,
|
||||
uint32_t& outWidth,
|
||||
uint32_t& outHeight);
|
||||
|
||||
bool AreEqualSceneViewportOverlayData(
|
||||
const SceneViewportOverlayData& lhs,
|
||||
const SceneViewportOverlayData& rhs);
|
||||
|
||||
uint64_t BuildSceneViewportOverlayContentSignature(
|
||||
const Components::Scene* scene,
|
||||
const std::vector<uint64_t>& selectedObjectIds);
|
||||
|
||||
bool ShouldRebuildSceneViewportOverlayFrameCache(
|
||||
const SceneViewportOverlayFrameCacheState& cacheState,
|
||||
const Components::Scene* scene,
|
||||
const SceneViewportOverlayData& overlay,
|
||||
uint32_t viewportWidth,
|
||||
uint32_t viewportHeight,
|
||||
const std::vector<uint64_t>& selectedObjectIds,
|
||||
uint64_t contentSignature,
|
||||
bool transformGizmoOverlayDirty);
|
||||
|
||||
void UpdateSceneViewportOverlayFrameCacheState(
|
||||
SceneViewportOverlayFrameCacheState& cacheState,
|
||||
const Components::Scene* scene,
|
||||
uint32_t viewportWidth,
|
||||
uint32_t viewportHeight,
|
||||
const std::vector<uint64_t>& selectedObjectIds,
|
||||
uint64_t contentSignature,
|
||||
const SceneViewportOverlayFrameData& frameData);
|
||||
|
||||
} // namespace Editor
|
||||
} // namespace XCEngine
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "Passes/SceneViewportSelectionOutlinePass.h"
|
||||
#include "SceneViewportCameraController.h"
|
||||
#include "SceneViewportEditorOverlayData.h"
|
||||
#include "SceneViewportOverlayFrameCache.h"
|
||||
#include "SceneViewportOverlayHandleBuilder.h"
|
||||
#include "SceneViewportOverlayBuilder.h"
|
||||
#include "SceneViewportRenderPlan.h"
|
||||
@@ -19,22 +20,18 @@
|
||||
|
||||
#include <XCEngine/Components/CameraComponent.h>
|
||||
#include <XCEngine/Components/GameObject.h>
|
||||
#include <XCEngine/Components/LightComponent.h>
|
||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
||||
#include <XCEngine/RHI/RHIDevice.h>
|
||||
#include <XCEngine/RHI/RHIEnums.h>
|
||||
#include <XCEngine/RHI/RHIResourceView.h>
|
||||
#include <XCEngine/RHI/RHITexture.h>
|
||||
#include <XCEngine/Rendering/Passes/BuiltinInfiniteGridPass.h>
|
||||
#include <XCEngine/Rendering/RenderContext.h>
|
||||
#include <XCEngine/Rendering/RenderSurface.h>
|
||||
#include <XCEngine/Rendering/SceneRenderer.h>
|
||||
#include <XCEngine/Scene/Scene.h>
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -45,133 +42,6 @@ namespace Editor {
|
||||
namespace {
|
||||
|
||||
constexpr bool kDebugSceneSelectionMask = false;
|
||||
constexpr uint64_t kSceneViewportOverlaySignatureOffsetBasis = 14695981039346656037ull;
|
||||
constexpr uint64_t kSceneViewportOverlaySignaturePrime = 1099511628211ull;
|
||||
|
||||
void HashSceneViewportOverlayBytes(uint64_t& hash, const void* data, size_t size) {
|
||||
const auto* bytes = static_cast<const uint8_t*>(data);
|
||||
for (size_t index = 0; index < size; ++index) {
|
||||
hash ^= static_cast<uint64_t>(bytes[index]);
|
||||
hash *= kSceneViewportOverlaySignaturePrime;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
void HashSceneViewportOverlayValue(uint64_t& hash, const TValue& value) {
|
||||
HashSceneViewportOverlayBytes(hash, &value, sizeof(TValue));
|
||||
}
|
||||
|
||||
void HashSceneViewportOverlayFloat(uint64_t& hash, float value) {
|
||||
uint32_t bits = 0u;
|
||||
std::memcpy(&bits, &value, sizeof(bits));
|
||||
HashSceneViewportOverlayValue(hash, bits);
|
||||
}
|
||||
|
||||
void HashSceneViewportOverlayVector3(uint64_t& hash, const Math::Vector3& value) {
|
||||
HashSceneViewportOverlayFloat(hash, value.x);
|
||||
HashSceneViewportOverlayFloat(hash, value.y);
|
||||
HashSceneViewportOverlayFloat(hash, value.z);
|
||||
}
|
||||
|
||||
void HashSceneViewportOverlayQuaternion(uint64_t& hash, const Math::Quaternion& value) {
|
||||
HashSceneViewportOverlayFloat(hash, value.x);
|
||||
HashSceneViewportOverlayFloat(hash, value.y);
|
||||
HashSceneViewportOverlayFloat(hash, value.z);
|
||||
HashSceneViewportOverlayFloat(hash, value.w);
|
||||
}
|
||||
|
||||
void HashSceneViewportOverlayRect(uint64_t& hash, const Math::Rect& value) {
|
||||
HashSceneViewportOverlayFloat(hash, value.x);
|
||||
HashSceneViewportOverlayFloat(hash, value.y);
|
||||
HashSceneViewportOverlayFloat(hash, value.width);
|
||||
HashSceneViewportOverlayFloat(hash, value.height);
|
||||
}
|
||||
|
||||
void HashSceneViewportOverlayTransform(uint64_t& hash, const Components::TransformComponent& transform) {
|
||||
HashSceneViewportOverlayVector3(hash, transform.GetPosition());
|
||||
HashSceneViewportOverlayQuaternion(hash, transform.GetRotation());
|
||||
HashSceneViewportOverlayVector3(hash, transform.GetScale());
|
||||
}
|
||||
|
||||
uint64_t BuildSceneViewEditorOverlayContentSignature(
|
||||
const Components::Scene* scene,
|
||||
const std::vector<uint64_t>& selectedObjectIds) {
|
||||
uint64_t hash = kSceneViewportOverlaySignatureOffsetBasis;
|
||||
|
||||
HashSceneViewportOverlayValue(hash, static_cast<uint64_t>(selectedObjectIds.size()));
|
||||
for (uint64_t entityId : selectedObjectIds) {
|
||||
HashSceneViewportOverlayValue(hash, entityId);
|
||||
}
|
||||
|
||||
if (scene == nullptr) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
for (Components::CameraComponent* camera : scene->FindObjectsOfType<Components::CameraComponent>()) {
|
||||
Components::GameObject* gameObject = camera != nullptr ? camera->GetGameObject() : nullptr;
|
||||
HashSceneViewportOverlayValue(hash, static_cast<uint8_t>(1u));
|
||||
HashSceneViewportOverlayValue(hash, gameObject != nullptr ? gameObject->GetID() : 0ull);
|
||||
HashSceneViewportOverlayValue(hash, camera != nullptr && camera->IsEnabled());
|
||||
HashSceneViewportOverlayValue(hash, gameObject != nullptr && gameObject->IsActiveInHierarchy());
|
||||
if (camera == nullptr ||
|
||||
gameObject == nullptr ||
|
||||
!camera->IsEnabled() ||
|
||||
!gameObject->IsActiveInHierarchy() ||
|
||||
gameObject->GetTransform() == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
HashSceneViewportOverlayTransform(hash, *gameObject->GetTransform());
|
||||
HashSceneViewportOverlayValue(hash, static_cast<uint32_t>(camera->GetProjectionType()));
|
||||
HashSceneViewportOverlayFloat(hash, camera->GetFieldOfView());
|
||||
HashSceneViewportOverlayFloat(hash, camera->GetOrthographicSize());
|
||||
HashSceneViewportOverlayFloat(hash, camera->GetNearClipPlane());
|
||||
HashSceneViewportOverlayFloat(hash, camera->GetFarClipPlane());
|
||||
HashSceneViewportOverlayRect(hash, camera->GetViewportRect());
|
||||
}
|
||||
|
||||
for (Components::LightComponent* light : scene->FindObjectsOfType<Components::LightComponent>()) {
|
||||
Components::GameObject* gameObject = light != nullptr ? light->GetGameObject() : nullptr;
|
||||
HashSceneViewportOverlayValue(hash, static_cast<uint8_t>(2u));
|
||||
HashSceneViewportOverlayValue(hash, gameObject != nullptr ? gameObject->GetID() : 0ull);
|
||||
HashSceneViewportOverlayValue(hash, light != nullptr && light->IsEnabled());
|
||||
HashSceneViewportOverlayValue(hash, gameObject != nullptr && gameObject->IsActiveInHierarchy());
|
||||
if (light == nullptr ||
|
||||
gameObject == nullptr ||
|
||||
!light->IsEnabled() ||
|
||||
!gameObject->IsActiveInHierarchy() ||
|
||||
gameObject->GetTransform() == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
HashSceneViewportOverlayTransform(hash, *gameObject->GetTransform());
|
||||
HashSceneViewportOverlayValue(hash, static_cast<uint32_t>(light->GetLightType()));
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
bool AreEqualSceneViewportVector3(const Math::Vector3& lhs, const Math::Vector3& rhs) {
|
||||
constexpr float kEpsilon = 1e-4f;
|
||||
return std::abs(lhs.x - rhs.x) <= kEpsilon &&
|
||||
std::abs(lhs.y - rhs.y) <= kEpsilon &&
|
||||
std::abs(lhs.z - rhs.z) <= kEpsilon;
|
||||
}
|
||||
|
||||
bool AreEqualSceneViewportOverlayData(
|
||||
const SceneViewportOverlayData& lhs,
|
||||
const SceneViewportOverlayData& rhs) {
|
||||
constexpr float kEpsilon = 1e-4f;
|
||||
return lhs.valid == rhs.valid &&
|
||||
AreEqualSceneViewportVector3(lhs.cameraPosition, rhs.cameraPosition) &&
|
||||
AreEqualSceneViewportVector3(lhs.cameraForward, rhs.cameraForward) &&
|
||||
AreEqualSceneViewportVector3(lhs.cameraRight, rhs.cameraRight) &&
|
||||
AreEqualSceneViewportVector3(lhs.cameraUp, rhs.cameraUp) &&
|
||||
std::abs(lhs.verticalFovDegrees - rhs.verticalFovDegrees) <= kEpsilon &&
|
||||
std::abs(lhs.nearClipPlane - rhs.nearClipPlane) <= kEpsilon &&
|
||||
std::abs(lhs.farClipPlane - rhs.farClipPlane) <= kEpsilon &&
|
||||
std::abs(lhs.orbitDistance - rhs.orbitDistance) <= kEpsilon;
|
||||
}
|
||||
|
||||
Math::Vector3 GetSceneViewportOrientationAxisVector(SceneViewportOrientationAxis axis) {
|
||||
switch (axis) {
|
||||
@@ -212,7 +82,7 @@ public:
|
||||
m_sceneViewportGridRenderer.Shutdown();
|
||||
m_sceneViewportEditorOverlayRenderer.Shutdown();
|
||||
m_sceneViewCamera = {};
|
||||
ResetSceneViewEditorOverlayFrameData();
|
||||
ResetSceneViewportOverlayFrameCacheState(m_sceneViewEditorOverlayFrameCache);
|
||||
m_sceneViewTransformGizmoOverlayState = {};
|
||||
m_sceneViewTransformGizmoOverlayDirty = false;
|
||||
m_sceneViewLastRenderContext = {};
|
||||
@@ -359,7 +229,7 @@ public:
|
||||
|
||||
const SceneViewportOverlayFrameData& GetSceneViewEditorOverlayFrameData(IEditorContext& context) override {
|
||||
EnsureSceneViewEditorOverlayFrameData(context);
|
||||
return m_sceneViewEditorOverlayFrameData;
|
||||
return m_sceneViewEditorOverlayFrameCache.frameData;
|
||||
}
|
||||
|
||||
void SetSceneViewTransformGizmoOverlayState(
|
||||
@@ -520,22 +390,17 @@ private:
|
||||
return BuildViewportColorSurface(entry.renderTargets);
|
||||
}
|
||||
|
||||
void ResetSceneViewEditorOverlayFrameData() {
|
||||
m_sceneViewEditorOverlayFrameData = {};
|
||||
m_sceneViewEditorOverlayScene = nullptr;
|
||||
m_sceneViewEditorOverlaySelectedObjectIds.clear();
|
||||
m_sceneViewEditorOverlayViewportWidth = 0u;
|
||||
m_sceneViewEditorOverlayViewportHeight = 0u;
|
||||
m_sceneViewEditorOverlayContentSignature = 0u;
|
||||
m_sceneViewEditorOverlayCached = false;
|
||||
}
|
||||
|
||||
void ResolveSceneViewEditorOverlayViewportSize(
|
||||
const ViewportEntry& entry,
|
||||
uint32_t& outWidth,
|
||||
uint32_t& outHeight) const {
|
||||
outWidth = entry.requestedWidth > 0u ? entry.requestedWidth : entry.renderTargets.width;
|
||||
outHeight = entry.requestedHeight > 0u ? entry.requestedHeight : entry.renderTargets.height;
|
||||
ResolveSceneViewportOverlayFrameViewportSize(
|
||||
entry.requestedWidth,
|
||||
entry.requestedHeight,
|
||||
entry.renderTargets.width,
|
||||
entry.renderTargets.height,
|
||||
outWidth,
|
||||
outHeight);
|
||||
}
|
||||
|
||||
bool ShouldRebuildSceneViewEditorOverlayFrameData(
|
||||
@@ -545,19 +410,20 @@ private:
|
||||
uint32_t viewportHeight,
|
||||
const std::vector<uint64_t>& selectedObjectIds,
|
||||
uint64_t contentSignature) const {
|
||||
return m_sceneViewTransformGizmoOverlayDirty ||
|
||||
!m_sceneViewEditorOverlayCached ||
|
||||
m_sceneViewEditorOverlayScene != scene ||
|
||||
m_sceneViewEditorOverlayViewportWidth != viewportWidth ||
|
||||
m_sceneViewEditorOverlayViewportHeight != viewportHeight ||
|
||||
m_sceneViewEditorOverlaySelectedObjectIds != selectedObjectIds ||
|
||||
m_sceneViewEditorOverlayContentSignature != contentSignature ||
|
||||
!AreEqualSceneViewportOverlayData(m_sceneViewEditorOverlayFrameData.overlay, overlay);
|
||||
return ShouldRebuildSceneViewportOverlayFrameCache(
|
||||
m_sceneViewEditorOverlayFrameCache,
|
||||
scene,
|
||||
overlay,
|
||||
viewportWidth,
|
||||
viewportHeight,
|
||||
selectedObjectIds,
|
||||
contentSignature,
|
||||
m_sceneViewTransformGizmoOverlayDirty);
|
||||
}
|
||||
|
||||
void EnsureSceneViewEditorOverlayFrameData(IEditorContext& context) {
|
||||
if (!EnsureSceneViewCamera()) {
|
||||
ResetSceneViewEditorOverlayFrameData();
|
||||
ResetSceneViewportOverlayFrameCacheState(m_sceneViewEditorOverlayFrameCache);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -570,7 +436,7 @@ private:
|
||||
const SceneViewportOverlayData overlay = GetSceneViewOverlayData();
|
||||
const std::vector<uint64_t> selectedObjectIds = context.GetSelectionManager().GetSelectedEntities();
|
||||
const uint64_t contentSignature =
|
||||
BuildSceneViewEditorOverlayContentSignature(scene, selectedObjectIds);
|
||||
BuildSceneViewportOverlayContentSignature(scene, selectedObjectIds);
|
||||
if (!ShouldRebuildSceneViewEditorOverlayFrameData(
|
||||
scene,
|
||||
overlay,
|
||||
@@ -581,10 +447,10 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
m_sceneViewEditorOverlayFrameData = {};
|
||||
m_sceneViewEditorOverlayFrameData.overlay = overlay;
|
||||
SceneViewportOverlayFrameData frameData = {};
|
||||
frameData.overlay = overlay;
|
||||
if (scene != nullptr && overlay.valid && viewportWidth > 0u && viewportHeight > 0u) {
|
||||
m_sceneViewEditorOverlayFrameData = m_sceneViewportOverlayBuilder.Build(
|
||||
frameData = m_sceneViewportOverlayBuilder.Build(
|
||||
context,
|
||||
overlay,
|
||||
viewportWidth,
|
||||
@@ -593,12 +459,14 @@ private:
|
||||
&m_sceneViewTransformGizmoOverlayState);
|
||||
}
|
||||
|
||||
m_sceneViewEditorOverlayScene = scene;
|
||||
m_sceneViewEditorOverlaySelectedObjectIds = selectedObjectIds;
|
||||
m_sceneViewEditorOverlayViewportWidth = viewportWidth;
|
||||
m_sceneViewEditorOverlayViewportHeight = viewportHeight;
|
||||
m_sceneViewEditorOverlayContentSignature = contentSignature;
|
||||
m_sceneViewEditorOverlayCached = true;
|
||||
UpdateSceneViewportOverlayFrameCacheState(
|
||||
m_sceneViewEditorOverlayFrameCache,
|
||||
scene,
|
||||
viewportWidth,
|
||||
viewportHeight,
|
||||
selectedObjectIds,
|
||||
contentSignature,
|
||||
frameData);
|
||||
m_sceneViewTransformGizmoOverlayDirty = false;
|
||||
}
|
||||
|
||||
@@ -861,14 +729,8 @@ private:
|
||||
Rendering::RenderContext m_sceneViewLastRenderContext = {};
|
||||
std::array<ViewportEntry, 2> m_entries = {};
|
||||
SceneViewCameraState m_sceneViewCamera;
|
||||
SceneViewportOverlayFrameData m_sceneViewEditorOverlayFrameData = {};
|
||||
SceneViewportTransformGizmoOverlayState m_sceneViewTransformGizmoOverlayState = {};
|
||||
const Components::Scene* m_sceneViewEditorOverlayScene = nullptr;
|
||||
std::vector<uint64_t> m_sceneViewEditorOverlaySelectedObjectIds = {};
|
||||
uint32_t m_sceneViewEditorOverlayViewportWidth = 0u;
|
||||
uint32_t m_sceneViewEditorOverlayViewportHeight = 0u;
|
||||
uint64_t m_sceneViewEditorOverlayContentSignature = 0u;
|
||||
bool m_sceneViewEditorOverlayCached = false;
|
||||
SceneViewportOverlayFrameCacheState m_sceneViewEditorOverlayFrameCache = {};
|
||||
bool m_sceneViewTransformGizmoOverlayDirty = false;
|
||||
SceneViewportGridPassRenderer m_sceneViewportGridRenderer;
|
||||
SceneViewportSelectionOutlinePassRenderer m_sceneViewportSelectionOutlineRenderer;
|
||||
|
||||
@@ -18,6 +18,7 @@ set(EDITOR_TEST_SOURCES
|
||||
test_scene_viewport_chrome.cpp
|
||||
test_scene_viewport_transform_gizmo_coordinator.cpp
|
||||
test_scene_viewport_shader_paths.cpp
|
||||
test_scene_viewport_overlay_frame_cache.cpp
|
||||
test_scene_viewport_overlay_sprite_resources.cpp
|
||||
test_scene_viewport_overlay_renderer.cpp
|
||||
test_scene_viewport_overlay_providers.cpp
|
||||
@@ -50,6 +51,7 @@ set(EDITOR_TEST_SOURCES
|
||||
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportTransformGizmoCoordinator.cpp
|
||||
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportOrientationGizmo.cpp
|
||||
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportOverlayBuilder.cpp
|
||||
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportOverlayFrameCache.cpp
|
||||
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportOverlaySpriteResources.cpp
|
||||
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportOverlayProviders.cpp
|
||||
)
|
||||
|
||||
162
tests/editor/test_scene_viewport_overlay_frame_cache.cpp
Normal file
162
tests/editor/test_scene_viewport_overlay_frame_cache.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Core/EditorContext.h"
|
||||
#include "Viewport/SceneViewportOverlayFrameCache.h"
|
||||
|
||||
#include <XCEngine/Components/CameraComponent.h>
|
||||
#include <XCEngine/Components/LightComponent.h>
|
||||
|
||||
namespace XCEngine::Editor {
|
||||
namespace {
|
||||
|
||||
SceneViewportOverlayData CreateValidOverlay() {
|
||||
SceneViewportOverlayData overlay = {};
|
||||
overlay.valid = true;
|
||||
overlay.cameraPosition = Math::Vector3(1.0f, 2.0f, 3.0f);
|
||||
overlay.cameraForward = Math::Vector3::Forward();
|
||||
overlay.cameraRight = Math::Vector3::Right();
|
||||
overlay.cameraUp = Math::Vector3::Up();
|
||||
overlay.verticalFovDegrees = 60.0f;
|
||||
overlay.nearClipPlane = 0.1f;
|
||||
overlay.farClipPlane = 1000.0f;
|
||||
overlay.orbitDistance = 6.0f;
|
||||
return overlay;
|
||||
}
|
||||
|
||||
TEST(SceneViewportOverlayFrameCacheTest, ResolveViewportSizePrefersRequestedDimensions) {
|
||||
uint32_t width = 0u;
|
||||
uint32_t height = 0u;
|
||||
|
||||
ResolveSceneViewportOverlayFrameViewportSize(
|
||||
1280u,
|
||||
720u,
|
||||
960u,
|
||||
540u,
|
||||
width,
|
||||
height);
|
||||
|
||||
EXPECT_EQ(width, 1280u);
|
||||
EXPECT_EQ(height, 720u);
|
||||
|
||||
ResolveSceneViewportOverlayFrameViewportSize(
|
||||
0u,
|
||||
0u,
|
||||
960u,
|
||||
540u,
|
||||
width,
|
||||
height);
|
||||
|
||||
EXPECT_EQ(width, 960u);
|
||||
EXPECT_EQ(height, 540u);
|
||||
}
|
||||
|
||||
TEST(SceneViewportOverlayFrameCacheTest, OverlayDataComparisonUsesEpsilonTolerance) {
|
||||
const SceneViewportOverlayData lhs = CreateValidOverlay();
|
||||
SceneViewportOverlayData rhs = lhs;
|
||||
rhs.cameraPosition.x += 5e-5f;
|
||||
rhs.orbitDistance += 5e-5f;
|
||||
|
||||
EXPECT_TRUE(AreEqualSceneViewportOverlayData(lhs, rhs));
|
||||
|
||||
rhs.cameraPosition.x += 1e-3f;
|
||||
EXPECT_FALSE(AreEqualSceneViewportOverlayData(lhs, rhs));
|
||||
}
|
||||
|
||||
TEST(SceneViewportOverlayFrameCacheTest, RebuildDecisionTracksCacheMetadataAndDirtyState) {
|
||||
SceneViewportOverlayFrameCacheState cacheState = {};
|
||||
const SceneViewportOverlayData overlay = CreateValidOverlay();
|
||||
const std::vector<uint64_t> selectedObjectIds = { 3u, 7u };
|
||||
const uint64_t contentSignature = 19u;
|
||||
|
||||
EXPECT_TRUE(ShouldRebuildSceneViewportOverlayFrameCache(
|
||||
cacheState,
|
||||
nullptr,
|
||||
overlay,
|
||||
1280u,
|
||||
720u,
|
||||
selectedObjectIds,
|
||||
contentSignature,
|
||||
false));
|
||||
|
||||
SceneViewportOverlayFrameData frameData = {};
|
||||
frameData.overlay = overlay;
|
||||
UpdateSceneViewportOverlayFrameCacheState(
|
||||
cacheState,
|
||||
nullptr,
|
||||
1280u,
|
||||
720u,
|
||||
selectedObjectIds,
|
||||
contentSignature,
|
||||
frameData);
|
||||
|
||||
EXPECT_TRUE(cacheState.cached);
|
||||
EXPECT_EQ(cacheState.viewportWidth, 1280u);
|
||||
EXPECT_EQ(cacheState.viewportHeight, 720u);
|
||||
EXPECT_EQ(cacheState.selectedObjectIds, selectedObjectIds);
|
||||
EXPECT_FALSE(ShouldRebuildSceneViewportOverlayFrameCache(
|
||||
cacheState,
|
||||
nullptr,
|
||||
overlay,
|
||||
1280u,
|
||||
720u,
|
||||
selectedObjectIds,
|
||||
contentSignature,
|
||||
false));
|
||||
EXPECT_TRUE(ShouldRebuildSceneViewportOverlayFrameCache(
|
||||
cacheState,
|
||||
nullptr,
|
||||
overlay,
|
||||
1280u,
|
||||
720u,
|
||||
selectedObjectIds,
|
||||
contentSignature,
|
||||
true));
|
||||
EXPECT_TRUE(ShouldRebuildSceneViewportOverlayFrameCache(
|
||||
cacheState,
|
||||
nullptr,
|
||||
overlay,
|
||||
1920u,
|
||||
1080u,
|
||||
selectedObjectIds,
|
||||
contentSignature,
|
||||
false));
|
||||
}
|
||||
|
||||
TEST(SceneViewportOverlayFrameCacheTest, ContentSignatureTracksSceneCameraAndLightState) {
|
||||
EditorContext context;
|
||||
context.GetSceneManager().NewScene("Overlay Frame Cache");
|
||||
|
||||
auto* cameraEntity = context.GetSceneManager().CreateEntity("SceneCamera");
|
||||
ASSERT_NE(cameraEntity, nullptr);
|
||||
auto* camera = cameraEntity->AddComponent<Components::CameraComponent>();
|
||||
ASSERT_NE(camera, nullptr);
|
||||
camera->SetNearClipPlane(0.3f);
|
||||
cameraEntity->GetTransform()->SetPosition(Math::Vector3(0.0f, 1.0f, 5.0f));
|
||||
|
||||
auto* lightEntity = context.GetSceneManager().CreateEntity("DirectionalLight");
|
||||
ASSERT_NE(lightEntity, nullptr);
|
||||
auto* light = lightEntity->AddComponent<Components::LightComponent>();
|
||||
ASSERT_NE(light, nullptr);
|
||||
light->SetLightType(Components::LightType::Directional);
|
||||
|
||||
const std::vector<uint64_t> selectedObjectIds = { cameraEntity->GetID() };
|
||||
const Components::Scene* scene = context.GetSceneManager().GetScene();
|
||||
ASSERT_NE(scene, nullptr);
|
||||
|
||||
const uint64_t initialSignature =
|
||||
BuildSceneViewportOverlayContentSignature(scene, selectedObjectIds);
|
||||
|
||||
light->SetLightType(Components::LightType::Point);
|
||||
const uint64_t changedLightSignature =
|
||||
BuildSceneViewportOverlayContentSignature(scene, selectedObjectIds);
|
||||
EXPECT_NE(initialSignature, changedLightSignature);
|
||||
|
||||
light->SetLightType(Components::LightType::Directional);
|
||||
cameraEntity->GetTransform()->SetPosition(Math::Vector3(2.0f, 1.0f, 5.0f));
|
||||
const uint64_t movedCameraSignature =
|
||||
BuildSceneViewportOverlayContentSignature(scene, selectedObjectIds);
|
||||
EXPECT_NE(initialSignature, movedCameraSignature);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace XCEngine::Editor
|
||||
Reference in New Issue
Block a user