MetaCore/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp

752 lines
30 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "MetaCoreRender/MetaCoreFilamentSceneBridge.h"
#include "MetaCorePlatform/MetaCoreWindow.h"
#include "MetaCoreScene/MetaCoreScene.h"
#include "MetaCoreScene/MetaCoreComponents.h"
#include "MetaCoreRender/MetaCoreRenderTypes.h"
#include "MetaCoreRender/MetaCoreImGuiHelper.h"
#include <imgui.h>
#include "MetaCoreFoundation/MetaCoreAssetRegistry.h"
#include <filament/Engine.h>
#include <filament/Scene.h>
#include <filament/View.h>
#include <filament/Camera.h>
#include <filament/SwapChain.h>
#include <filament/Renderer.h>
#include <filament/Viewport.h>
#include <filament/TransformManager.h>
#include <filament/Texture.h>
#include <filament/RenderTarget.h>
#include <filament/LightManager.h>
#include <gltfio/AssetLoader.h>
#include <gltfio/FilamentAsset.h>
#include <gltfio/ResourceLoader.h>
#include <gltfio/MaterialProvider.h>
#include <utils/Entity.h>
#include <utils/EntityManager.h>
#include <utils/NameComponentManager.h>
#include "MetaCoreScene/MetaCoreTransformUtils.h"
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/matrix_decompose.hpp>
#include <glm/gtc/quaternion.hpp>
#include <iostream>
#include <fstream>
#include <unordered_map>
#include <map>
#include <vector>
// 引入 Windows 和 OpenGL 头文件以创建纹理
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <GL/gl.h>
namespace MetaCore {
class MetaCoreFilamentSceneBridge::MetaCoreFilamentSceneBridgeImpl {
public:
MetaCoreFilamentSceneBridgeImpl() = default;
~MetaCoreFilamentSceneBridgeImpl() {
Shutdown();
}
bool Initialize(MetaCoreWindow& window) {
std::cout << "FilamentSceneBridge: Initializing..." << std::endl;
// 创建 Filament Engine (不共享上下文,避免闪退)
Engine_ = filament::Engine::create();
if (!Engine_) {
std::cerr << "Failed to create Filament Engine with shared context!" << std::endl;
return false;
}
// 创建绑定真实窗口的交换链
SwapChain_ = Engine_->createSwapChain((void*)window.GetNativeWindowHandle());
if (!SwapChain_) {
std::cerr << "Failed to create Filament SwapChain with window handle!" << std::endl;
return false;
}
// 创建渲染器
Renderer_ = Engine_->createRenderer();
// 创建场景
Scene_ = Engine_->createScene();
// 创建默认灯光
Light_ = utils::EntityManager::get().create();
filament::LightManager::Builder(filament::LightManager::Type::DIRECTIONAL)
.color(filament::Color::toLinear<filament::ACCURATE>({ 1.0f, 1.0f, 1.0f }))
.intensity(100000.0f)
.direction({ 0.5f, 0.5f, -1.0f }) // Z-up 下 Z 向下
.castShadows(true)
.build(*Engine_, Light_);
Scene_->addEntity(Light_);
// 创建相机
utils::Entity cameraEntity = utils::EntityManager::get().create();
Camera_ = Engine_->createCamera(cameraEntity);
// 创建视图
View_ = Engine_->createView();
View_->setScene(Scene_);
View_->setCamera(Camera_);
// 创建 UI 视图
UIView_ = Engine_->createView();
// 创建 ImGuiHelper
ImGuiHelper_ = new MetaCoreImGuiHelper(Engine_, UIView_, "", ImGui::GetCurrentContext());
// 初始化离屏渲染纹理
auto [width, height] = window.GetFramebufferSize();
// 1. 创建 Filament 颜色纹理
FilamentTexture_ = filament::Texture::Builder()
.width(static_cast<uint32_t>(width))
.height(static_cast<uint32_t>(height))
.usage(filament::Texture::Usage::COLOR_ATTACHMENT | filament::Texture::Usage::SAMPLEABLE)
.format(filament::Texture::InternalFormat::RGBA8)
.build(*Engine_);
// 2. 创建深度纹理
DepthTexture_ = filament::Texture::Builder()
.width(static_cast<uint32_t>(width))
.height(static_cast<uint32_t>(height))
.usage(filament::Texture::Usage::DEPTH_ATTACHMENT)
.format(filament::Texture::InternalFormat::DEPTH24)
.build(*Engine_);
// 3. 创建 RenderTarget 并绑定
RenderTarget_ = filament::RenderTarget::Builder()
.texture(filament::RenderTarget::AttachmentPoint::COLOR, FilamentTexture_)
.texture(filament::RenderTarget::AttachmentPoint::DEPTH, DepthTexture_)
.build(*Engine_);
// 4. 设置到 View
View_->setRenderTarget(RenderTarget_);
View_->setViewport({0, 0, static_cast<uint32_t>(width), static_cast<uint32_t>(height)});
// 确保开启后处理为了HDR
View_->setPostProcessingEnabled(true);
// 初始化 gltfio
MaterialProvider_ = filament::gltfio::createJitShaderProvider(Engine_);
NameManager_ = new utils::NameComponentManager(utils::EntityManager::get());
AssetLoader_ = filament::gltfio::AssetLoader::create({ Engine_, MaterialProvider_, NameManager_ });
std::cout << "FilamentSceneBridge: Initialized with Offscreen Texture ID: " << GLTextureId_ << std::endl;
return true;
}
void Shutdown() {
if (Engine_) {
std::cout << "FilamentSceneBridge: Shutting down..." << std::endl;
// 销毁所有加载的资产
for (auto& [id, asset] : LoadedAssets_) {
AssetLoader_->destroyAsset(asset);
}
LoadedAssets_.clear();
// 销毁 gltfio 资源
if (AssetLoader_) {
filament::gltfio::AssetLoader::destroy(&AssetLoader_);
AssetLoader_ = nullptr;
}
if (MaterialProvider_) {
MaterialProvider_->destroyMaterials();
delete MaterialProvider_;
MaterialProvider_ = nullptr;
}
// 销毁离屏渲染资源
if (RenderTarget_) {
Engine_->destroy(RenderTarget_);
RenderTarget_ = nullptr;
}
if (FilamentTexture_) {
Engine_->destroy(FilamentTexture_);
FilamentTexture_ = nullptr;
}
if (DepthTexture_) {
Engine_->destroy(DepthTexture_);
DepthTexture_ = nullptr;
}
if (GLTextureId_) {
glDeleteTextures(1, &GLTextureId_);
GLTextureId_ = 0;
}
// 销毁 View
Engine_->destroy(View_);
// 销毁相机组件和实体
if (Camera_) {
utils::Entity cameraEntity = Camera_->getEntity();
Engine_->destroyCameraComponent(cameraEntity);
utils::EntityManager::get().destroy(cameraEntity);
}
// 销毁其他资源
Engine_->destroy(Scene_);
Engine_->destroy(Renderer_);
Engine_->destroy(SwapChain_);
delete NameManager_;
NameManager_ = nullptr;
// 最后销毁 Engine
filament::Engine::destroy(&Engine_);
Engine_ = nullptr;
}
}
void SetProjectRootPath(const std::filesystem::path& projectRootPath) {
ProjectRootPath_ = projectRootPath;
}
void ParseModelHierarchyToEcs(MetaCoreScene& scene, MetaCoreGameObject& parentObject, filament::gltfio::FilamentAsset* asset) {
if (!asset) return;
const utils::Entity* entities = asset->getEntities();
size_t entityCount = asset->getEntityCount();
auto& tm = Engine_->getTransformManager();
// 建立 Filament Entity 到 MetaCore GameObject 的映射
std::map<utils::Entity, MetaCoreGameObject> entityToObj;
entityToObj[asset->getRoot()] = parentObject;
// 【超级核心】:绑定顶级父 GameObject 标识到 Filament Asset 根 Entity彻底打通顶级 Gizmo 的同步!
ObjectToFilamentEntity_[parentObject.GetId()] = { asset, asset->getRoot() };
// 预先收集并缓存 parentObject 子树下的所有已有 GameObject用于高精度的三步复用匹配
std::vector<MetaCoreGameObject> subtreeObjects;
std::vector<MetaCoreId> subtreeIds = scene.GetSubtreeObjectIds(parentObject.GetId());
for (MetaCoreId subId : subtreeIds) {
auto subObj = scene.FindGameObject(subId);
if (subObj && subObj.GetId() != parentObject.GetId()) {
subtreeObjects.push_back(subObj);
}
}
// 第一遍:创建或复用所有对象
for (size_t i = 0; i < entityCount; i++) {
utils::Entity entity = entities[i];
if (entity == asset->getRoot()) continue;
const char* nodeName = asset->getName(entity);
std::string name = nodeName ? nodeName : ("Node_" + std::to_string(i));
MetaCoreGameObject childObj;
bool isExisting = false;
// 1. 优先通过 ModelNodeIndex 进行精确匹配(针对带有网格的节点)
for (auto& sceneObj : subtreeObjects) {
if (sceneObj.HasComponent<MetaCoreMeshRendererComponent>()) {
auto& mesh = sceneObj.GetComponent<MetaCoreMeshRendererComponent>();
if (mesh.ModelNodeIndex == static_cast<std::int32_t>(i)) {
childObj = sceneObj;
isExisting = true;
break;
}
}
}
// 2. 如果没找到(针对没有网格的空节点),通过名字进行匹配复用
if (!isExisting) {
for (auto& sceneObj : subtreeObjects) {
if (sceneObj.GetName() == name) {
// 且该节点不能已经被其他实体映射占用
bool alreadyMapped = false;
for (auto& [ent, obj] : entityToObj) {
if (obj.GetId() == sceneObj.GetId()) {
alreadyMapped = true;
break;
}
}
if (!alreadyMapped) {
childObj = sceneObj;
isExisting = true;
break;
}
}
}
}
// 3. 实在没有找到,才进行动态创建(仅作为降级兜底)
if (!isExisting) {
childObj = scene.CreateGameObject(name, parentObject.GetId());
auto& meshRenderer = childObj.AddComponent<MetaCoreMeshRendererComponent>();
meshRenderer.MeshSource = MetaCoreMeshSourceKind::Asset;
meshRenderer.ModelNodeIndex = static_cast<std::int32_t>(i);
}
entityToObj[entity] = childObj;
ObjectToFilamentEntity_[childObj.GetId()] = { asset, entity };
// 获取并设置 Transform
auto instance = tm.getInstance(entity);
if (instance) {
filament::math::mat4f localTransform = tm.getTransform(instance);
glm::mat4 filamentMatrix;
std::memcpy(glm::value_ptr(filamentMatrix), &localTransform[0][0], sizeof(float) * 16);
glm::mat4 R_minus90X = glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), {1, 0, 0});
glm::mat4 R_plus90X = glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), {1, 0, 0});
glm::mat4 matrix = R_minus90X * filamentMatrix * R_plus90X;
// 拆解矩阵
glm::vec3 scale;
glm::quat rotation;
glm::vec3 translation;
glm::vec3 skew;
glm::vec4 perspective;
glm::decompose(matrix, scale, rotation, translation, skew, perspective);
auto& transform = childObj.GetComponent<MetaCoreTransformComponent>();
transform.Position = translation;
transform.RotationEulerDegrees = glm::degrees(glm::eulerAngles(rotation));
transform.Scale = scale;
}
}
// 第二遍:修正父子关系
for (size_t i = 0; i < entityCount; i++) {
utils::Entity entity = entities[i];
if (entity == asset->getRoot()) continue;
auto instance = tm.getInstance(entity);
if (instance) {
utils::Entity parentEntity = tm.getParent(instance);
if (parentEntity && entityToObj.count(parentEntity)) {
MetaCoreGameObject currentObj = entityToObj[entity];
MetaCoreGameObject parentObj = entityToObj[parentEntity];
currentObj.SetParentId(parentObj.GetId());
}
}
}
}
static std::string NormalizePath(std::string path) {
std::replace(path.begin(), path.end(), '\\', '/');
return path;
}
void SyncScene(MetaCoreScene& scene, bool compatibilityMeshOnly) {
if (!AssetLoader_) return;
// 预处理:构建子树模型网格节点计数表,以支撑在没有 Tag 时的极速、完美 Fallback 回溯
std::unordered_map<MetaCoreId, std::unordered_map<std::string, int>> subtreeModelCounts;
for (const auto& obj : scene.GetGameObjects()) {
if (obj.HasComponent<MetaCoreMeshRendererComponent>()) {
auto& mesh = obj.GetComponent<MetaCoreMeshRendererComponent>();
if (mesh.ModelNodeIndex >= 0 && !mesh.SourceModelPath.empty()) {
std::string normPath = NormalizePath(mesh.SourceModelPath);
MetaCoreId currentId = obj.GetId();
while (currentId != 0) {
auto currentObj = scene.FindGameObject(currentId);
if (!currentObj) break;
subtreeModelCounts[currentId][normPath]++;
currentId = currentObj.GetParentId();
}
}
}
}
for (const auto& gameObject : scene.GetGameObjects()) {
if (!gameObject.HasComponent<MetaCoreMeshRendererComponent>()) {
continue;
}
const auto& meshRenderer = gameObject.GetComponent<MetaCoreMeshRendererComponent>();
if (meshRenderer.MeshSource != MetaCoreMeshSourceKind::Asset &&
meshRenderer.MeshSource != MetaCoreMeshSourceKind::Builtin) {
continue;
}
std::string modelPath;
if (meshRenderer.SourceModelAssetGuid.IsValid()) {
modelPath = MetaCoreAssetRegistry::Get().ResolveGuidToPath(meshRenderer.SourceModelAssetGuid).generic_string();
}
if (modelPath.empty() && !meshRenderer.SourceModelPath.empty()) {
modelPath = meshRenderer.SourceModelPath;
}
if (modelPath.empty() && meshRenderer.MeshSource == MetaCoreMeshSourceKind::Builtin && meshRenderer.BuiltinMesh == MetaCoreBuiltinMeshType::Cube) {
modelPath = "Assets/Models/box1.glb";
}
if (modelPath.empty()) {
continue;
}
std::filesystem::path absolutePath = ProjectRootPath_ / modelPath;
// 【黄金算法】:溯源确定唯一的模型根加载主体
MetaCoreGameObject hostRoot = gameObject;
if (meshRenderer.ModelNodeIndex >= 0) {
const std::string& currentModelPath = meshRenderer.SourceModelPath;
std::string normCurrentPath = NormalizePath(currentModelPath);
MetaCoreGameObject current = gameObject;
MetaCoreGameObject foundRoot = {};
// 1. 优先通过运行时 MetaCoreModelRootTag 快速寻找顶级根
while (current.GetParentId() != 0) {
auto parentObj = scene.FindGameObject(current.GetParentId());
if (!parentObj) break;
if (parentObj.HasComponent<MetaCoreModelRootTag>()) {
auto& tag = parentObj.GetComponent<MetaCoreModelRootTag>();
if (NormalizePath(tag.SourceModelPath) == normCurrentPath) {
foundRoot = parentObj;
break;
}
}
current = parentObj;
}
if (foundRoot) {
hostRoot = foundRoot;
} else {
// 2. Fallback若无明确 Tag例如反序列化后使用转折点判定算法匹配包含模型网格数最大的、最深的祖先
current = gameObject;
MetaCoreGameObject bestCandidate = gameObject;
int maxCount = subtreeModelCounts[gameObject.GetId()][normCurrentPath];
while (current) {
int count = subtreeModelCounts[current.GetId()][normCurrentPath];
if (count > maxCount) {
maxCount = count;
bestCandidate = current;
}
if (current.GetParentId() == 0) break;
current = scene.FindGameObject(current.GetParentId());
}
hostRoot = bestCandidate;
}
}
// 如果该模型的顶级根宿主已经被加载过,我们只需更新当前游戏对象的位置即可
if (LoadedAssets_.contains(hostRoot.GetId())) {
UpdateTransform(gameObject);
continue;
}
// 加载新模型,以顶级根宿主 hostRoot 的 ID 进行注册存储
std::cout << "FilamentSceneBridge: Loading GLTF: " << absolutePath << " (Host: " << hostRoot.GetName() << ")" << std::endl;
std::ifstream file(absolutePath, std::ios::binary);
if (!file.is_open()) {
std::cerr << "Failed to open file: " << absolutePath << std::endl;
continue;
}
std::vector<char> buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
filament::gltfio::FilamentAsset* asset = AssetLoader_->createAsset(
reinterpret_cast<const uint8_t*>(buffer.data()),
static_cast<uint32_t>(buffer.size())
);
if (!asset) {
std::cerr << "Failed to create asset!" << std::endl;
continue;
}
// 加载贴图等资源
filament::gltfio::ResourceLoader resourceLoader({ Engine_ });
resourceLoader.loadResources(asset);
// 添加到场景
Scene_->addEntities(asset->getEntities(), asset->getEntityCount());
LoadedAssets_[hostRoot.GetId()] = asset;
// 同步层级结构到场景树并自动进行展开子节点的复用映射
MetaCoreGameObject nonConstHostRoot = hostRoot;
// 现场补挂 Tag确保后续帧和拖拽时 100% 命中 Tag 快速通道,绝不走 Fallback
if (!nonConstHostRoot.HasComponent<MetaCoreModelRootTag>()) {
nonConstHostRoot.AddComponent<MetaCoreModelRootTag>(MetaCoreModelRootTag{ modelPath });
}
// 如果名字是默认的 "Cube",自动改为模型文件名
if (nonConstHostRoot.GetName() == "Cube") {
std::string filename = std::filesystem::path(modelPath).filename().string();
nonConstHostRoot.GetName() = filename;
}
ParseModelHierarchyToEcs(scene, nonConstHostRoot, asset);
// 创建中间 Pivot 实体用于坐标系转换 (glTF Y-up -> MetaCore Z-up)
utils::Entity pivotEntity = utils::EntityManager::get().create();
auto& tm = Engine_->getTransformManager();
tm.create(pivotEntity);
// 将资产根节点挂载到 Pivot 下
utils::Entity assetRoot = asset->getRoot();
tm.setParent(tm.getInstance(assetRoot), tm.getInstance(pivotEntity));
// 获取原始局部变换并叠加旋转补偿
filament::math::mat4f originalLocalTransform = tm.getTransform(tm.getInstance(assetRoot));
glm::mat4 originalMatrix;
std::memcpy(glm::value_ptr(originalMatrix), &originalLocalTransform[0][0], sizeof(float) * 16);
glm::mat4 compensationMatrix = glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), {1, 0, 0});
glm::mat4 finalRootMatrix = compensationMatrix * originalMatrix;
tm.setTransform(tm.getInstance(assetRoot), *reinterpret_cast<const filament::math::mat4f*>(glm::value_ptr(finalRootMatrix)));
// 【关键一步】:注册 hostRoot顶级根宿主的 ID 与 pivotEntity彻底打通顶级宿主的 Gizmo 坐标变换!
ObjectToFilamentEntity_[hostRoot.GetId()] = { asset, pivotEntity };
Scene_->addEntity(pivotEntity);
// 更新初始位置
UpdateTransform(gameObject);
}
// 全量同步所有已映射对象的 Transform
for (const auto& gameObject : scene.GetGameObjects()) {
if (ObjectToFilamentEntity_.count(gameObject.GetId())) {
UpdateTransform(gameObject);
}
}
}
void ApplySceneView(const MetaCoreSceneView& sceneView) {
if (!Camera_ || !View_) return;
// 1. 视图矩阵同步
const glm::mat4 viewMatrix = glm::lookAt(sceneView.CameraPosition, sceneView.CameraTarget, sceneView.CameraUp);
const glm::mat4 cameraModelMatrix = glm::inverse(viewMatrix);
Camera_->setModelMatrix(*reinterpret_cast<const filament::math::mat4f*>(glm::value_ptr(cameraModelMatrix)));
// 2. 投影矩阵:回归 Filament 原生设置
const auto& viewport = View_->getViewport();
float aspect = (viewport.height > 0) ? (static_cast<float>(viewport.width) / static_cast<float>(viewport.height)) : 1.0f;
Camera_->setProjection(
sceneView.VerticalFieldOfViewDegrees,
aspect,
0.1,
1000.0,
filament::Camera::Fov::VERTICAL
);
}
void RenderAll() {
if (!Renderer_ || !SwapChain_ || !View_ || !UIView_ || !ImGuiHelper_) {
return;
}
if (Renderer_->beginFrame(SwapChain_)) {
// 1. 渲染 3D 离屏视口 (输出到 RenderTarget)
filament::Renderer::ClearOptions options;
options.clearColor = { 0.11f, 0.12f, 0.14f, 1.0f }; // 深灰色
options.clear = true;
Renderer_->setClearOptions(options);
Renderer_->render(View_);
// 2. 准备并渲染 UI 视口 (输出到 SwapChain)
ImGuiIO& io = ImGui::GetIO();
ImGuiHelper_->setDisplaySize(io.DisplaySize.x, io.DisplaySize.y);
UIView_->setViewport({0, 0, static_cast<uint32_t>(io.DisplaySize.x), static_cast<uint32_t>(io.DisplaySize.y)});
options.clearColor = { 0.11f, 0.12f, 0.14f, 1.0f }; // 灰色
options.clear = true;
Renderer_->setClearOptions(options);
ImGuiHelper_->processImGuiCommands(ImGui::GetDrawData(), io);
Renderer_->render(UIView_);
Renderer_->endFrame();
// 在帧结束、指令提交后,安全地销毁上一帧遗留的旧纹理
for (auto* tex : OldTextures_) {
Engine_->destroy(tex);
}
OldTextures_.clear();
}
}
uint32_t GetGLTextureId() const {
return GLTextureId_;
}
void Resize(int width, int height) {
if (width <= 0 || height <= 0) return;
// 【关键修复】:如果大小没有改变,不要重新创建纹理!
// 否则会导致上一帧传给 ImGui 的纹理指针在这一帧被提前销毁,引发 Use-after-free 崩溃。
if (FilamentTexture_ &&
FilamentTexture_->getWidth() == static_cast<uint32_t>(width) &&
FilamentTexture_->getHeight() == static_cast<uint32_t>(height)) {
return;
}
if (RenderTarget_) Engine_->destroy(RenderTarget_);
if (DepthTexture_) Engine_->destroy(DepthTexture_);
// 【关键修复】:推迟销毁旧纹理,避免当前帧 ImGui 的 DrawList 还在引用它导致崩溃。
if (FilamentTexture_) {
OldTextures_.push_back(FilamentTexture_);
}
FilamentTexture_ = filament::Texture::Builder()
.width(static_cast<uint32_t>(width))
.height(static_cast<uint32_t>(height))
.usage(filament::Texture::Usage::COLOR_ATTACHMENT | filament::Texture::Usage::SAMPLEABLE)
.format(filament::Texture::InternalFormat::RGBA8)
.build(*Engine_);
DepthTexture_ = filament::Texture::Builder()
.width(static_cast<uint32_t>(width))
.height(static_cast<uint32_t>(height))
.usage(filament::Texture::Usage::DEPTH_ATTACHMENT)
.format(filament::Texture::InternalFormat::DEPTH24)
.build(*Engine_);
RenderTarget_ = filament::RenderTarget::Builder()
.texture(filament::RenderTarget::AttachmentPoint::COLOR, FilamentTexture_)
.texture(filament::RenderTarget::AttachmentPoint::DEPTH, DepthTexture_)
.build(*Engine_);
View_->setRenderTarget(RenderTarget_);
View_->setViewport({0, 0, static_cast<uint32_t>(width), static_cast<uint32_t>(height)});
}
void* GetFilamentTexturePointer() const {
return FilamentTexture_;
}
bool TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const {
return false;
}
bool HasRuntimeSyncFailure() const { return false; }
const std::string& GetLastRuntimeSyncFailure() const { return EmptyString_; }
private:
void UpdateTransform(const MetaCoreGameObject& gameObject) {
auto it = ObjectToFilamentEntity_.find(gameObject.GetId());
if (it == ObjectToFilamentEntity_.end()) return;
filament::gltfio::FilamentAsset* asset = it->second.first;
utils::Entity entity = it->second.second;
auto& tm = Engine_->getTransformManager();
auto instance = tm.getInstance(entity);
if (instance) {
if (!gameObject.HasComponent<MetaCoreTransformComponent>()) return;
const auto& transform = gameObject.GetComponent<MetaCoreTransformComponent>();
glm::mat4 matrix = MetaCoreBuildTransformMatrix(transform);
// 【关键修复】:如果当前 entity 是子节点(即不是顶级映射的 pivotEntity
// 由于它的父级assetRoot带有了 -90X 旋转,我们必须对子节点应用基变换来抵消这个旋转。
// 公式L_filament = R(90X) * L_ecs * R(-90X)
if (LoadedAssets_.count(gameObject.GetId()) == 0) {
glm::mat4 R_plus90X = glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), {1, 0, 0});
glm::mat4 R_minus90X = glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), {1, 0, 0});
matrix = R_plus90X * matrix * R_minus90X;
}
tm.setTransform(instance, *reinterpret_cast<const filament::math::mat4f*>(glm::value_ptr(matrix)));
}
}
filament::Engine* Engine_ = nullptr;
filament::SwapChain* SwapChain_ = nullptr;
filament::Renderer* Renderer_ = nullptr;
filament::Scene* Scene_ = nullptr;
filament::Camera* Camera_ = nullptr;
filament::View* View_ = nullptr;
filament::gltfio::AssetLoader* AssetLoader_ = nullptr;
filament::gltfio::MaterialProvider* MaterialProvider_ = nullptr;
utils::NameComponentManager* NameManager_ = nullptr;
std::unordered_map<MetaCoreId, std::pair<filament::gltfio::FilamentAsset*, utils::Entity>> ObjectToFilamentEntity_;
std::unordered_map<MetaCoreId, filament::gltfio::FilamentAsset*> LoadedAssets_;
filament::View* UIView_ = nullptr;
MetaCoreImGuiHelper* ImGuiHelper_ = nullptr;
GLuint GLTextureId_ = 0;
filament::Texture* FilamentTexture_ = nullptr;
filament::Texture* DepthTexture_ = nullptr;
filament::RenderTarget* RenderTarget_ = nullptr;
std::vector<filament::Texture*> OldTextures_;
utils::Entity Light_;
std::filesystem::path ProjectRootPath_{};
std::string EmptyString_{};
};
MetaCoreFilamentSceneBridge::MetaCoreFilamentSceneBridge()
: Impl_(std::make_unique<MetaCoreFilamentSceneBridgeImpl>()) {}
MetaCoreFilamentSceneBridge::~MetaCoreFilamentSceneBridge() = default;
bool MetaCoreFilamentSceneBridge::Initialize(MetaCoreWindow& window) {
return Impl_->Initialize(window);
}
void MetaCoreFilamentSceneBridge::Shutdown() {
Impl_->Shutdown();
}
void MetaCoreFilamentSceneBridge::SetProjectRootPath(const std::filesystem::path& projectRootPath) {
Impl_->SetProjectRootPath(projectRootPath);
}
void MetaCoreFilamentSceneBridge::SyncScene(MetaCoreScene& scene, bool compatibilityMeshOnly) {
Impl_->SyncScene(scene, compatibilityMeshOnly);
}
void MetaCoreFilamentSceneBridge::ApplySceneView(const MetaCoreSceneView& sceneView) {
Impl_->ApplySceneView(sceneView);
}
void MetaCoreFilamentSceneBridge::RenderAll() {
Impl_->RenderAll();
}
uint32_t MetaCoreFilamentSceneBridge::GetGLTextureId() const {
return Impl_->GetGLTextureId();
}
void MetaCoreFilamentSceneBridge::Resize(int width, int height) {
Impl_->Resize(width, height);
}
void* MetaCoreFilamentSceneBridge::GetFilamentTexturePointer() const {
return Impl_->GetFilamentTexturePointer();
}
bool MetaCoreFilamentSceneBridge::TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const {
return Impl_->TryGetObjectWorldMatrix(objectId, worldMatrix);
}
bool MetaCoreFilamentSceneBridge::HasRuntimeSyncFailure() const {
return Impl_->HasRuntimeSyncFailure();
}
const std::string& MetaCoreFilamentSceneBridge::GetLastRuntimeSyncFailure() const {
return Impl_->GetLastRuntimeSyncFailure();
}
} // namespace MetaCore