534 lines
19 KiB
C++
534 lines
19 KiB
C++
#include "MetaCoreRender/MetaCorePandaSceneBridge.h"
|
|
|
|
#include "MetaCoreRender/MetaCoreRenderDevice.h"
|
|
#include "MetaCoreRender/MetaCoreRenderTypes.h"
|
|
#include "MetaCoreScene/MetaCoreComponents.h"
|
|
#include "MetaCoreScene/MetaCoreScene.h"
|
|
|
|
#include "ambientLight.h"
|
|
#include "camera.h"
|
|
#include "directionalLight.h"
|
|
#include "geom.h"
|
|
#include "geomNode.h"
|
|
#include "geomLines.h"
|
|
#include "geomTriangles.h"
|
|
#include "geomVertexData.h"
|
|
#include "geomVertexFormat.h"
|
|
#include "geomVertexWriter.h"
|
|
#include "lineSegs.h"
|
|
#include "loader.h"
|
|
#include "nodePath.h"
|
|
#include "perspectiveLens.h"
|
|
#include "pandaNode.h"
|
|
#include "windowFramework.h"
|
|
|
|
#define GLM_ENABLE_EXPERIMENTAL
|
|
#include <glm/ext/matrix_transform.hpp>
|
|
#include <glm/gtx/euler_angles.hpp>
|
|
#include <glm/mat4x4.hpp>
|
|
|
|
#include <chrono>
|
|
#include <cstdio>
|
|
#include <ctime>
|
|
#include <memory>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
|
|
namespace MetaCore {
|
|
|
|
namespace {
|
|
|
|
void MetaCoreTrace(const char* message) {
|
|
if (message == nullptr) {
|
|
return;
|
|
}
|
|
|
|
const auto now = std::chrono::system_clock::now();
|
|
const auto time = std::chrono::system_clock::to_time_t(now);
|
|
struct tm timeInfo {};
|
|
localtime_s(&timeInfo, &time);
|
|
|
|
char timeBuffer[32]{};
|
|
std::strftime(timeBuffer, sizeof(timeBuffer), "[%H:%M:%S] ", &timeInfo);
|
|
|
|
FILE* file = nullptr;
|
|
if (fopen_s(&file, "editor.crash.log", "a") == 0 && file != nullptr) {
|
|
std::fputs(timeBuffer, file);
|
|
std::fputs(message, file);
|
|
std::fputs("\n", file);
|
|
std::fflush(file);
|
|
std::fclose(file);
|
|
}
|
|
|
|
std::printf("%s%s\n", timeBuffer, message);
|
|
}
|
|
|
|
glm::mat4 MetaCoreBuildBasisSwapMatrix() {
|
|
glm::mat4 basis(1.0F);
|
|
basis[0] = glm::vec4(1.0F, 0.0F, 0.0F, 0.0F);
|
|
basis[1] = glm::vec4(0.0F, 0.0F, 1.0F, 0.0F);
|
|
basis[2] = glm::vec4(0.0F, 1.0F, 0.0F, 0.0F);
|
|
basis[3] = glm::vec4(0.0F, 0.0F, 0.0F, 1.0F);
|
|
return basis;
|
|
}
|
|
|
|
LMatrix4f MetaCoreConvertTransformToPanda(const MetaCoreTransformComponent& transform) {
|
|
const glm::mat4 translation = glm::translate(glm::mat4(1.0F), transform.Position);
|
|
const glm::mat4 rotation = glm::yawPitchRoll(
|
|
glm::radians(transform.RotationEulerDegrees.y),
|
|
glm::radians(transform.RotationEulerDegrees.x),
|
|
glm::radians(transform.RotationEulerDegrees.z)
|
|
);
|
|
const glm::mat4 scale = glm::scale(glm::mat4(1.0F), transform.Scale);
|
|
|
|
const glm::mat4 metaCoreMatrix = translation * rotation * scale;
|
|
const glm::mat4 basis = MetaCoreBuildBasisSwapMatrix();
|
|
const glm::mat4 pandaMatrix = basis * metaCoreMatrix * basis;
|
|
|
|
LMatrix4f result;
|
|
for (int row = 0; row < 4; ++row) {
|
|
for (int column = 0; column < 4; ++column) {
|
|
result.set_cell(row, column, pandaMatrix[column][row]);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
LPoint3f MetaCoreToPandaPoint(const glm::vec3& value) {
|
|
return LPoint3f(value.x, -value.z, value.y);
|
|
}
|
|
|
|
LVector3f MetaCoreToPandaVector(const glm::vec3& value) {
|
|
return LVector3f(value.x, -value.z, value.y);
|
|
}
|
|
|
|
LVecBase3f MetaCoreToPandaScale(const glm::vec3& value) {
|
|
return LVecBase3f(value.x, value.z, value.y);
|
|
}
|
|
|
|
void MetaCoreApplyTransformToPandaNode(const MetaCoreTransformComponent& transform, NodePath& nodePath) {
|
|
nodePath.set_pos(MetaCoreToPandaPoint(transform.Position));
|
|
nodePath.set_hpr(
|
|
transform.RotationEulerDegrees.y,
|
|
transform.RotationEulerDegrees.x,
|
|
transform.RotationEulerDegrees.z
|
|
);
|
|
nodePath.set_scale(MetaCoreToPandaScale(transform.Scale));
|
|
}
|
|
|
|
NodePath MetaCoreCreateGridNode(const NodePath& parentNode) {
|
|
MetaCoreTrace("create_grid: begin");
|
|
try {
|
|
MetaCoreTrace("create_grid: create vertex data");
|
|
PT(GeomVertexData) vertexData = new GeomVertexData(
|
|
"MetaCoreGrid",
|
|
GeomVertexFormat::get_v3c4(),
|
|
Geom::UH_static
|
|
);
|
|
|
|
GeomVertexWriter vertexWriter(vertexData, "vertex");
|
|
GeomVertexWriter colorWriter(vertexData, "color");
|
|
|
|
MetaCoreTrace("create_grid: loop start");
|
|
constexpr int gridHalfExtent = 10;
|
|
int vertexCount = 0;
|
|
for (int lineIndex = -gridHalfExtent; lineIndex <= gridHalfExtent; ++lineIndex) {
|
|
const bool isAxisLine = (lineIndex == 0);
|
|
const LColor color(isAxisLine ? 0.42F : 0.30F, isAxisLine ? 0.45F : 0.33F, isAxisLine ? 0.50F : 0.36F, 1.0F);
|
|
|
|
// X-direction lines
|
|
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(static_cast<float>(lineIndex), 0.0F, static_cast<float>(-gridHalfExtent))));
|
|
colorWriter.add_data4(color);
|
|
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(static_cast<float>(lineIndex), 0.0F, static_cast<float>(gridHalfExtent))));
|
|
colorWriter.add_data4(color);
|
|
|
|
// Z-direction lines
|
|
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(static_cast<float>(-gridHalfExtent), 0.0F, static_cast<float>(lineIndex))));
|
|
colorWriter.add_data4(color);
|
|
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(static_cast<float>(gridHalfExtent), 0.0F, static_cast<float>(lineIndex))));
|
|
colorWriter.add_data4(color);
|
|
|
|
vertexCount += 4;
|
|
}
|
|
MetaCoreTrace("create_grid: loop end");
|
|
|
|
MetaCoreTrace("create_grid: create primitive");
|
|
PT(GeomLines) lines = new GeomLines(Geom::UH_static);
|
|
for (int i = 0; i < vertexCount; i += 2) {
|
|
lines->add_vertices(i, i + 1);
|
|
}
|
|
|
|
MetaCoreTrace("create_grid: create geom");
|
|
PT(Geom) geom = new Geom(vertexData);
|
|
geom->add_primitive(lines.p());
|
|
|
|
PT(GeomNode) geomNode = new GeomNode("MetaCoreGridNode");
|
|
geomNode->add_geom(geom);
|
|
|
|
return parentNode.attach_new_node(geomNode);
|
|
} catch (...) {
|
|
return NodePath();
|
|
}
|
|
}
|
|
|
|
NodePath MetaCoreCreateAxisNode(const NodePath& parentNode) {
|
|
MetaCoreTrace("create_axis: begin");
|
|
try {
|
|
PT(GeomVertexData) vertexData = new GeomVertexData(
|
|
"MetaCoreAxis",
|
|
GeomVertexFormat::get_v3c4(),
|
|
Geom::UH_static
|
|
);
|
|
|
|
GeomVertexWriter vertexWriter(vertexData, "vertex");
|
|
GeomVertexWriter colorWriter(vertexData, "color");
|
|
|
|
// X Axis (Red)
|
|
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 0.0F)));
|
|
colorWriter.add_data4(LColor(0.92F, 0.26F, 0.26F, 1.0F));
|
|
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(2.0F, 0.0F, 0.0F)));
|
|
colorWriter.add_data4(LColor(0.92F, 0.26F, 0.26F, 1.0F));
|
|
|
|
// Y Axis (Green)
|
|
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 0.0F)));
|
|
colorWriter.add_data4(LColor(0.28F, 0.86F, 0.36F, 1.0F));
|
|
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(0.0F, 2.0F, 0.0F)));
|
|
colorWriter.add_data4(LColor(0.28F, 0.86F, 0.36F, 1.0F));
|
|
|
|
// Z Axis (Blue)
|
|
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 0.0F)));
|
|
colorWriter.add_data4(LColor(0.32F, 0.56F, 0.96F, 1.0F));
|
|
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 2.0F)));
|
|
colorWriter.add_data4(LColor(0.32F, 0.56F, 0.96F, 1.0F));
|
|
|
|
PT(GeomLines) lines = new GeomLines(Geom::UH_static);
|
|
lines->add_vertices(0, 1);
|
|
lines->add_vertices(2, 3);
|
|
lines->add_vertices(4, 5);
|
|
|
|
PT(Geom) geom = new Geom(vertexData);
|
|
geom->add_primitive(lines.p());
|
|
|
|
PT(GeomNode) geomNode = new GeomNode("MetaCoreAxisNode");
|
|
geomNode->add_geom(geom);
|
|
|
|
return parentNode.attach_new_node(geomNode);
|
|
} catch (...) {
|
|
return NodePath();
|
|
}
|
|
}
|
|
|
|
NodePath MetaCoreCreateUnitCubeNode(const NodePath& parentNode) {
|
|
PT(GeomVertexData) vertexData = new GeomVertexData(
|
|
"MetaCoreUnitCube",
|
|
GeomVertexFormat::get_v3n3(),
|
|
Geom::UH_static
|
|
);
|
|
|
|
GeomVertexWriter vertexWriter(vertexData, "vertex");
|
|
GeomVertexWriter normalWriter(vertexData, "normal");
|
|
|
|
const auto addFace = [&](const glm::vec3& normal, const glm::vec3& a, const glm::vec3& b, const glm::vec3& c, const glm::vec3& d) {
|
|
const glm::vec3 corners[4] = {a, b, c, d};
|
|
for (const glm::vec3& corner : corners) {
|
|
const LPoint3f pandaPoint = MetaCoreToPandaPoint(corner);
|
|
const LVector3f pandaNormal = MetaCoreToPandaVector(normal);
|
|
vertexWriter.add_data3(pandaPoint);
|
|
normalWriter.add_data3(pandaNormal);
|
|
}
|
|
};
|
|
|
|
addFace(glm::vec3(0.0F, 0.0F, 1.0F),
|
|
glm::vec3(-0.5F, -0.5F, 0.5F),
|
|
glm::vec3(0.5F, -0.5F, 0.5F),
|
|
glm::vec3(0.5F, 0.5F, 0.5F),
|
|
glm::vec3(-0.5F, 0.5F, 0.5F));
|
|
addFace(glm::vec3(0.0F, 0.0F, -1.0F),
|
|
glm::vec3(0.5F, -0.5F, -0.5F),
|
|
glm::vec3(-0.5F, -0.5F, -0.5F),
|
|
glm::vec3(-0.5F, 0.5F, -0.5F),
|
|
glm::vec3(0.5F, 0.5F, -0.5F));
|
|
addFace(glm::vec3(-1.0F, 0.0F, 0.0F),
|
|
glm::vec3(-0.5F, -0.5F, -0.5F),
|
|
glm::vec3(-0.5F, -0.5F, 0.5F),
|
|
glm::vec3(-0.5F, 0.5F, 0.5F),
|
|
glm::vec3(-0.5F, 0.5F, -0.5F));
|
|
addFace(glm::vec3(1.0F, 0.0F, 0.0F),
|
|
glm::vec3(0.5F, -0.5F, 0.5F),
|
|
glm::vec3(0.5F, -0.5F, -0.5F),
|
|
glm::vec3(0.5F, 0.5F, -0.5F),
|
|
glm::vec3(0.5F, 0.5F, 0.5F));
|
|
addFace(glm::vec3(0.0F, 1.0F, 0.0F),
|
|
glm::vec3(-0.5F, 0.5F, 0.5F),
|
|
glm::vec3(0.5F, 0.5F, 0.5F),
|
|
glm::vec3(0.5F, 0.5F, -0.5F),
|
|
glm::vec3(-0.5F, 0.5F, -0.5F));
|
|
addFace(glm::vec3(0.0F, -1.0F, 0.0F),
|
|
glm::vec3(-0.5F, -0.5F, -0.5F),
|
|
glm::vec3(0.5F, -0.5F, -0.5F),
|
|
glm::vec3(0.5F, -0.5F, 0.5F),
|
|
glm::vec3(-0.5F, -0.5F, 0.5F));
|
|
|
|
PT(GeomTriangles) triangles = new GeomTriangles(Geom::UH_static);
|
|
for (int faceIndex = 0; faceIndex < 6; ++faceIndex) {
|
|
const int baseVertex = faceIndex * 4;
|
|
triangles->add_vertices(baseVertex + 0, baseVertex + 1, baseVertex + 2);
|
|
triangles->add_vertices(baseVertex + 0, baseVertex + 2, baseVertex + 3);
|
|
}
|
|
|
|
PT(Geom) geom = new Geom(vertexData);
|
|
geom->add_primitive(triangles);
|
|
|
|
PT(GeomNode) geomNode = new GeomNode("MetaCoreUnitCubeNode");
|
|
geomNode->add_geom(geom);
|
|
return parentNode.attach_new_node(geomNode);
|
|
}
|
|
|
|
glm::mat4 MetaCoreConvertPandaMatrixToGlm(const LMatrix4f& matrix) {
|
|
glm::mat4 result(1.0F);
|
|
for (int col = 0; col < 4; ++col) {
|
|
for (int row = 0; row < 4; ++row) {
|
|
result[col][row] = matrix.get_cell(col, row);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
class MetaCorePandaSceneBridge::MetaCorePandaSceneBridgeImpl {
|
|
public:
|
|
struct MetaCorePandaObjectState {
|
|
NodePath RootNode{};
|
|
NodePath MeshNode{};
|
|
NodePath LightNode{};
|
|
};
|
|
|
|
MetaCoreRenderDevice* RenderDevice = nullptr;
|
|
NodePath GridNode{};
|
|
NodePath AxisNode{};
|
|
NodePath AmbientLightNode{};
|
|
MetaCoreId SelectedObjectId = 0;
|
|
std::unordered_map<MetaCoreId, MetaCorePandaObjectState> ObjectStates{};
|
|
};
|
|
|
|
MetaCorePandaSceneBridge::MetaCorePandaSceneBridge()
|
|
: Impl_(std::make_unique<MetaCorePandaSceneBridgeImpl>()) {
|
|
}
|
|
|
|
MetaCorePandaSceneBridge::~MetaCorePandaSceneBridge() {
|
|
Shutdown();
|
|
}
|
|
|
|
bool MetaCorePandaSceneBridge::Initialize(MetaCoreRenderDevice& renderDevice) {
|
|
Shutdown();
|
|
|
|
auto* windowFrameworkHandle = static_cast<WindowFramework*>(renderDevice.GetNativeWindowFrameworkHandle());
|
|
auto* sceneRootHandle = static_cast<NodePath*>(renderDevice.GetNativeSceneRootHandle());
|
|
if (windowFrameworkHandle == nullptr || sceneRootHandle == nullptr || sceneRootHandle->is_empty()) {
|
|
return false;
|
|
}
|
|
|
|
Impl_->RenderDevice = &renderDevice;
|
|
|
|
Impl_->GridNode = MetaCoreCreateGridNode(*sceneRootHandle);
|
|
Impl_->AxisNode = MetaCoreCreateAxisNode(*sceneRootHandle);
|
|
|
|
Impl_->GridNode.set_light_off(1);
|
|
Impl_->AxisNode.set_light_off(1);
|
|
|
|
PT(AmbientLight) ambientLight = new AmbientLight("MetaCoreAmbientLight");
|
|
ambientLight->set_color(LColor(0.85F, 0.85F, 0.85F, 1.0F));
|
|
Impl_->AmbientLightNode = sceneRootHandle->attach_new_node(ambientLight);
|
|
sceneRootHandle->set_light(Impl_->AmbientLightNode);
|
|
|
|
return true;
|
|
}
|
|
|
|
void MetaCorePandaSceneBridge::Shutdown() {
|
|
if (Impl_ == nullptr) {
|
|
return;
|
|
}
|
|
|
|
for (auto& [objectId, objectState] : Impl_->ObjectStates) {
|
|
(void)objectId;
|
|
if (!objectState.RootNode.is_empty()) {
|
|
objectState.RootNode.remove_node();
|
|
}
|
|
}
|
|
Impl_->ObjectStates.clear();
|
|
|
|
if (!Impl_->AmbientLightNode.is_empty()) {
|
|
Impl_->AmbientLightNode.remove_node();
|
|
Impl_->AmbientLightNode = NodePath();
|
|
}
|
|
|
|
if (!Impl_->AxisNode.is_empty()) {
|
|
Impl_->AxisNode.remove_node();
|
|
Impl_->AxisNode = NodePath();
|
|
}
|
|
|
|
if (!Impl_->GridNode.is_empty()) {
|
|
Impl_->GridNode.remove_node();
|
|
Impl_->GridNode = NodePath();
|
|
}
|
|
|
|
Impl_->RenderDevice = nullptr;
|
|
Impl_->SelectedObjectId = 0;
|
|
}
|
|
|
|
void MetaCorePandaSceneBridge::SyncScene(const MetaCoreScene& scene) {
|
|
if (Impl_->RenderDevice == nullptr) {
|
|
return;
|
|
}
|
|
|
|
auto* windowFrameworkHandle = static_cast<WindowFramework*>(Impl_->RenderDevice->GetNativeWindowFrameworkHandle());
|
|
auto* sceneRootHandle = static_cast<NodePath*>(Impl_->RenderDevice->GetNativeSceneRootHandle());
|
|
if (windowFrameworkHandle == nullptr || sceneRootHandle == nullptr || sceneRootHandle->is_empty()) {
|
|
return;
|
|
}
|
|
|
|
std::unordered_set<MetaCoreId> aliveObjectIds;
|
|
|
|
for (const MetaCoreGameObject& gameObject : scene.GetGameObjects()) {
|
|
aliveObjectIds.insert(gameObject.Id);
|
|
auto [iterator, inserted] = Impl_->ObjectStates.try_emplace(gameObject.Id);
|
|
MetaCorePandaSceneBridgeImpl::MetaCorePandaObjectState& objectState = iterator->second;
|
|
|
|
if (inserted || objectState.RootNode.is_empty()) {
|
|
PT(PandaNode) rootNode = new PandaNode(gameObject.Name);
|
|
objectState.RootNode = sceneRootHandle->attach_new_node(rootNode);
|
|
}
|
|
|
|
objectState.RootNode.set_name(gameObject.Name);
|
|
MetaCoreApplyTransformToPandaNode(gameObject.Transform, objectState.RootNode);
|
|
|
|
if (gameObject.ParentId != 0) {
|
|
const auto parentIterator = Impl_->ObjectStates.find(gameObject.ParentId);
|
|
if (parentIterator != Impl_->ObjectStates.end() && !parentIterator->second.RootNode.is_empty()) {
|
|
objectState.RootNode.reparent_to(parentIterator->second.RootNode);
|
|
} else {
|
|
objectState.RootNode.reparent_to(*sceneRootHandle);
|
|
}
|
|
} else {
|
|
objectState.RootNode.reparent_to(*sceneRootHandle);
|
|
}
|
|
|
|
if (gameObject.MeshRenderer.has_value()) {
|
|
if (objectState.MeshNode.is_empty()) {
|
|
objectState.MeshNode = MetaCoreCreateUnitCubeNode(objectState.RootNode);
|
|
}
|
|
|
|
if (!objectState.MeshNode.is_empty()) {
|
|
objectState.MeshNode.set_texture_off(1);
|
|
objectState.MeshNode.set_material_off(1);
|
|
objectState.MeshNode.set_shader_off(1);
|
|
objectState.MeshNode.set_light_off(1);
|
|
objectState.MeshNode.set_two_sided(true);
|
|
objectState.MeshNode.set_color(
|
|
gameObject.MeshRenderer->BaseColor.r,
|
|
gameObject.MeshRenderer->BaseColor.g,
|
|
gameObject.MeshRenderer->BaseColor.b,
|
|
1.0F
|
|
);
|
|
|
|
if (gameObject.MeshRenderer->Visible) {
|
|
objectState.MeshNode.show();
|
|
} else {
|
|
objectState.MeshNode.hide();
|
|
}
|
|
|
|
if (gameObject.Id == Impl_->SelectedObjectId) {
|
|
objectState.MeshNode.set_color_scale(1.18F, 1.02F, 0.72F, 1.0F);
|
|
} else {
|
|
objectState.MeshNode.clear_color_scale();
|
|
}
|
|
}
|
|
} else if (!objectState.MeshNode.is_empty()) {
|
|
objectState.MeshNode.remove_node();
|
|
objectState.MeshNode = NodePath();
|
|
}
|
|
|
|
if (gameObject.Light.has_value()) {
|
|
if (objectState.LightNode.is_empty()) {
|
|
PT(DirectionalLight) directionalLight = new DirectionalLight(gameObject.Name);
|
|
objectState.LightNode = objectState.RootNode.attach_new_node(directionalLight);
|
|
sceneRootHandle->set_light(objectState.LightNode);
|
|
}
|
|
|
|
auto* directionalLight = DCAST(DirectionalLight, objectState.LightNode.node());
|
|
if (directionalLight != nullptr) {
|
|
directionalLight->set_color(LColor(
|
|
gameObject.Light->Color.r * gameObject.Light->Intensity,
|
|
gameObject.Light->Color.g * gameObject.Light->Intensity,
|
|
gameObject.Light->Color.b * gameObject.Light->Intensity,
|
|
1.0F
|
|
));
|
|
}
|
|
} else if (!objectState.LightNode.is_empty()) {
|
|
sceneRootHandle->clear_light(objectState.LightNode);
|
|
objectState.LightNode.remove_node();
|
|
objectState.LightNode = NodePath();
|
|
}
|
|
}
|
|
|
|
for (auto iterator = Impl_->ObjectStates.begin(); iterator != Impl_->ObjectStates.end();) {
|
|
if (!aliveObjectIds.contains(iterator->first)) {
|
|
if (!iterator->second.RootNode.is_empty()) {
|
|
iterator->second.RootNode.remove_node();
|
|
}
|
|
iterator = Impl_->ObjectStates.erase(iterator);
|
|
} else {
|
|
++iterator;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MetaCorePandaSceneBridge::ApplySceneView(const MetaCoreSceneView& sceneView) {
|
|
if (Impl_->RenderDevice == nullptr) {
|
|
return;
|
|
}
|
|
|
|
auto* editorCameraHandle = static_cast<NodePath*>(Impl_->RenderDevice->GetNativeEditorCameraHandle());
|
|
if (editorCameraHandle == nullptr || editorCameraHandle->is_empty()) {
|
|
return;
|
|
}
|
|
|
|
Impl_->SelectedObjectId = sceneView.SelectedObjectId;
|
|
|
|
editorCameraHandle->set_pos(MetaCoreToPandaPoint(sceneView.CameraPosition));
|
|
editorCameraHandle->look_at(MetaCoreToPandaPoint(sceneView.CameraTarget), MetaCoreToPandaVector(sceneView.CameraUp));
|
|
|
|
auto* cameraNode = DCAST(Camera, editorCameraHandle->node());
|
|
if (cameraNode != nullptr) {
|
|
auto* perspectiveLens = DCAST(PerspectiveLens, cameraNode->get_lens());
|
|
if (perspectiveLens != nullptr) {
|
|
const float aspect = std::max(0.001F, perspectiveLens->get_aspect_ratio());
|
|
const float vFovRad = glm::radians(sceneView.VerticalFieldOfViewDegrees);
|
|
const float hFovDeg = glm::degrees(2.0F * std::atan(aspect * std::tan(vFovRad * 0.5F)));
|
|
perspectiveLens->set_fov(LVecBase2f(std::max(0.001F, hFovDeg), std::max(0.001F, sceneView.VerticalFieldOfViewDegrees)));
|
|
}
|
|
}
|
|
}
|
|
|
|
bool MetaCorePandaSceneBridge::TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const {
|
|
if (Impl_ == nullptr || Impl_->RenderDevice == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
auto* sceneRootHandle = static_cast<NodePath*>(Impl_->RenderDevice->GetNativeSceneRootHandle());
|
|
if (sceneRootHandle == nullptr || sceneRootHandle->is_empty()) {
|
|
return false;
|
|
}
|
|
|
|
const auto objectIterator = Impl_->ObjectStates.find(objectId);
|
|
if (objectIterator == Impl_->ObjectStates.end() || objectIterator->second.RootNode.is_empty()) {
|
|
return false;
|
|
}
|
|
|
|
worldMatrix = MetaCoreConvertPandaMatrixToGlm(objectIterator->second.RootNode.get_mat(*sceneRootHandle));
|
|
return true;
|
|
}
|
|
|
|
} // namespace MetaCore
|