MetaCore/Source/MetaCoreRender/Private/MetaCoreRenderDevice.cpp

171 lines
5.7 KiB
C++

#include "MetaCoreRender/MetaCoreRenderDevice.h"
#include "MetaCorePlatform/MetaCoreWindow.h"
#include "camera.h"
#include "displayRegion.h"
#include "graphicsEngine.h"
#include "graphicsWindow.h"
#include "pandaFramework.h"
#include "pandaNode.h"
#include "perspectiveLens.h"
#include "windowFramework.h"
#include <algorithm>
#include <memory>
namespace MetaCore {
class MetaCoreRenderDevice::MetaCoreRenderDeviceImpl {
public:
MetaCoreWindow* Window = nullptr;
PandaFramework* Framework = nullptr;
WindowFramework* WindowFrameworkHandle = nullptr;
GraphicsWindow* GraphicsWindowHandle = nullptr;
GraphicsEngine* GraphicsEngineHandle = nullptr;
DisplayRegion* SceneDisplayRegion = nullptr;
NodePath SceneRoot{};
NodePath EditorCamera{};
bool Initialized = false;
};
MetaCoreRenderDevice::MetaCoreRenderDevice()
: Impl_(std::make_unique<MetaCoreRenderDeviceImpl>()) {
}
MetaCoreRenderDevice::~MetaCoreRenderDevice() {
Shutdown();
}
bool MetaCoreRenderDevice::Initialize(MetaCoreWindow& window) {
if (Impl_->Initialized) {
return true;
}
auto* frameworkHandle = static_cast<PandaFramework*>(window.GetNativeFrameworkHandle());
auto* windowFrameworkHandle = static_cast<WindowFramework*>(window.GetNativeWindowFrameworkHandle());
auto* graphicsWindowHandle = static_cast<GraphicsWindow*>(window.GetNativeGraphicsWindowHandle());
if (frameworkHandle == nullptr || windowFrameworkHandle == nullptr || graphicsWindowHandle == nullptr) {
return false;
}
Impl_->Window = &window;
Impl_->Framework = frameworkHandle;
Impl_->WindowFrameworkHandle = windowFrameworkHandle;
Impl_->GraphicsWindowHandle = graphicsWindowHandle;
Impl_->GraphicsEngineHandle = frameworkHandle->get_graphics_engine();
if (Impl_->GraphicsEngineHandle == nullptr) {
return false;
}
Impl_->GraphicsEngineHandle->set_auto_flip(false);
Impl_->GraphicsEngineHandle->open_windows();
if (Impl_->WindowFrameworkHandle->get_display_region_2d() != nullptr) {
Impl_->WindowFrameworkHandle->get_display_region_2d()->set_active(false);
}
Impl_->SceneDisplayRegion = Impl_->WindowFrameworkHandle->get_display_region_3d();
if (Impl_->SceneDisplayRegion == nullptr) {
return false;
}
Impl_->GraphicsWindowHandle->set_clear_color_active(true);
Impl_->GraphicsWindowHandle->set_clear_color(LColor(0.38F, 0.48F, 0.62F, 1.0F));
PT(PandaNode) sceneRootNode = new PandaNode("MetaCoreSceneRoot");
Impl_->SceneRoot = Impl_->WindowFrameworkHandle->get_render().attach_new_node(sceneRootNode);
Impl_->SceneRoot.set_shader_auto();
Impl_->EditorCamera = Impl_->WindowFrameworkHandle->make_camera();
Impl_->SceneDisplayRegion->set_camera(Impl_->EditorCamera);
Impl_->SceneDisplayRegion->set_sort(0);
Impl_->SceneDisplayRegion->set_scissor_enabled(true);
Impl_->SceneDisplayRegion->set_clear_color_active(false);
if (auto* cameraNode = DCAST(Camera, Impl_->EditorCamera.node()); cameraNode != nullptr) {
PT(PerspectiveLens) lens = new PerspectiveLens();
lens->set_fov(60.0F);
lens->set_near_far(0.05F, 500.0F);
cameraNode->set_lens(lens);
}
Impl_->Initialized = true;
return true;
}
void MetaCoreRenderDevice::Shutdown() {
if (!Impl_->Initialized) {
return;
}
if (!Impl_->EditorCamera.is_empty()) {
Impl_->EditorCamera.remove_node();
Impl_->EditorCamera = NodePath();
}
if (!Impl_->SceneRoot.is_empty()) {
Impl_->SceneRoot.remove_node();
Impl_->SceneRoot = NodePath();
}
Impl_->SceneDisplayRegion = nullptr;
Impl_->GraphicsEngineHandle = nullptr;
Impl_->GraphicsWindowHandle = nullptr;
Impl_->WindowFrameworkHandle = nullptr;
Impl_->Framework = nullptr;
Impl_->Window = nullptr;
Impl_->Initialized = false;
}
void MetaCoreRenderDevice::RenderFrame() const {
if (Impl_->GraphicsEngineHandle != nullptr) {
Impl_->GraphicsEngineHandle->render_frame();
}
}
void MetaCoreRenderDevice::PresentFrame() const {
if (Impl_->GraphicsEngineHandle != nullptr) {
Impl_->GraphicsEngineHandle->flip_frame();
}
}
void MetaCoreRenderDevice::SetSceneViewportRect(const MetaCoreViewportRect& viewportRect) {
if (Impl_->SceneDisplayRegion == nullptr || Impl_->Window == nullptr) {
return;
}
const auto [framebufferWidth, framebufferHeight] = Impl_->Window->GetFramebufferSize();
if (framebufferWidth <= 0 || framebufferHeight <= 0 || viewportRect.Width <= 1.0F || viewportRect.Height <= 1.0F) {
Impl_->SceneDisplayRegion->set_active(false);
return;
}
const float clampedLeft = std::clamp(viewportRect.Left / static_cast<float>(framebufferWidth), 0.0F, 1.0F);
const float clampedRight = std::clamp((viewportRect.Left + viewportRect.Width) / static_cast<float>(framebufferWidth), 0.0F, 1.0F);
const float clampedTop = std::clamp(viewportRect.Top / static_cast<float>(framebufferHeight), 0.0F, 1.0F);
const float clampedBottom = std::clamp((viewportRect.Top + viewportRect.Height) / static_cast<float>(framebufferHeight), 0.0F, 1.0F);
Impl_->SceneDisplayRegion->set_active(true);
Impl_->SceneDisplayRegion->set_dimensions(
clampedLeft,
clampedRight,
1.0F - clampedBottom,
1.0F - clampedTop
);
}
void* MetaCoreRenderDevice::GetNativeWindowFrameworkHandle() const {
return Impl_->WindowFrameworkHandle;
}
void* MetaCoreRenderDevice::GetNativeSceneRootHandle() const {
return Impl_->SceneRoot.is_empty() ? nullptr : static_cast<void*>(&Impl_->SceneRoot);
}
void* MetaCoreRenderDevice::GetNativeEditorCameraHandle() const {
return Impl_->EditorCamera.is_empty() ? nullptr : static_cast<void*>(&Impl_->EditorCamera);
}
} // namespace MetaCore