134 lines
4.6 KiB
C++
134 lines
4.6 KiB
C++
#include "MetaCoreRender/MetaCoreSceneRenderSync.h"
|
|
|
|
#include "MetaCoreRender/MetaCoreRenderTypes.h"
|
|
#include "MetaCoreScene/MetaCoreScene.h"
|
|
#include "MetaCoreScene/MetaCoreTransformUtils.h"
|
|
|
|
#include <glm/geometric.hpp>
|
|
|
|
#include <cmath>
|
|
|
|
namespace MetaCore {
|
|
|
|
namespace {
|
|
|
|
[[nodiscard]] bool MetaCoreIsUsableDirection(const glm::vec3& value) {
|
|
return std::isfinite(value.x) &&
|
|
std::isfinite(value.y) &&
|
|
std::isfinite(value.z) &&
|
|
glm::length(value) > 0.0001F;
|
|
}
|
|
|
|
[[nodiscard]] glm::vec3 MetaCoreExtractTranslation(const glm::mat4& matrix) {
|
|
return glm::vec3(matrix[3]);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
MetaCoreSceneRenderSyncSnapshot MetaCoreSceneRenderSync::BuildSnapshot(const MetaCoreScene& scene) const {
|
|
MetaCoreSceneRenderSyncSnapshot snapshot;
|
|
|
|
for (MetaCoreId objectId : scene.BuildHierarchyPreorder()) {
|
|
const MetaCoreGameObject gameObject = scene.FindGameObject(objectId);
|
|
if (!gameObject) {
|
|
continue;
|
|
}
|
|
|
|
glm::mat4 localMatrix{1.0F};
|
|
if (gameObject.HasComponent<MetaCoreTransformComponent>()) {
|
|
localMatrix = MetaCoreBuildTransformMatrix(gameObject.GetComponent<MetaCoreTransformComponent>());
|
|
}
|
|
|
|
glm::mat4 worldMatrix = localMatrix;
|
|
const MetaCoreId parentId = gameObject.GetParentId();
|
|
if (parentId != 0) {
|
|
const auto parentWorldIt = snapshot.WorldMatrices.find(parentId);
|
|
if (parentWorldIt != snapshot.WorldMatrices.end()) {
|
|
worldMatrix = parentWorldIt->second * localMatrix;
|
|
}
|
|
}
|
|
snapshot.WorldMatrices[objectId] = worldMatrix;
|
|
|
|
if (gameObject.HasComponent<MetaCoreMeshRendererComponent>()) {
|
|
const auto& meshRenderer = gameObject.GetComponent<MetaCoreMeshRendererComponent>();
|
|
snapshot.Renderables.push_back(MetaCoreRenderSyncRenderable{
|
|
objectId,
|
|
parentId,
|
|
gameObject.GetName(),
|
|
localMatrix,
|
|
worldMatrix,
|
|
meshRenderer.Visible,
|
|
meshRenderer.MeshSource,
|
|
meshRenderer.BuiltinMesh,
|
|
meshRenderer.MeshAssetGuid,
|
|
meshRenderer.SourceModelAssetGuid,
|
|
meshRenderer.SourceModelPath,
|
|
meshRenderer.ModelNodeIndex
|
|
});
|
|
}
|
|
|
|
if (gameObject.HasComponent<MetaCoreCameraComponent>()) {
|
|
const auto& camera = gameObject.GetComponent<MetaCoreCameraComponent>();
|
|
MetaCoreRenderSyncCamera syncCamera{
|
|
objectId,
|
|
camera.IsPrimary,
|
|
camera.FieldOfViewDegrees,
|
|
camera.NearClip,
|
|
camera.FarClip,
|
|
worldMatrix
|
|
};
|
|
snapshot.Cameras.push_back(syncCamera);
|
|
if (syncCamera.IsPrimary && !snapshot.PrimaryCamera.has_value()) {
|
|
snapshot.PrimaryCamera = syncCamera;
|
|
}
|
|
}
|
|
|
|
if (gameObject.HasComponent<MetaCoreLightComponent>()) {
|
|
const auto& light = gameObject.GetComponent<MetaCoreLightComponent>();
|
|
snapshot.Lights.push_back(MetaCoreRenderSyncLight{
|
|
objectId,
|
|
light.Color,
|
|
light.Intensity,
|
|
worldMatrix
|
|
});
|
|
}
|
|
}
|
|
|
|
if (!snapshot.PrimaryCamera.has_value() && !snapshot.Cameras.empty()) {
|
|
snapshot.PrimaryCamera = snapshot.Cameras.front();
|
|
}
|
|
|
|
return snapshot;
|
|
}
|
|
|
|
bool MetaCoreSceneRenderSync::TryBuildSceneViewFromPrimaryCamera(
|
|
const MetaCoreSceneRenderSyncSnapshot& snapshot,
|
|
MetaCoreSceneView& sceneView
|
|
) {
|
|
if (!snapshot.PrimaryCamera.has_value()) {
|
|
return false;
|
|
}
|
|
|
|
const MetaCoreRenderSyncCamera& camera = *snapshot.PrimaryCamera;
|
|
const glm::vec3 cameraPosition = MetaCoreExtractTranslation(camera.WorldMatrix);
|
|
glm::vec3 cameraForward = glm::vec3(camera.WorldMatrix * glm::vec4(0.0F, 0.0F, -1.0F, 0.0F));
|
|
glm::vec3 cameraUp = glm::vec3(camera.WorldMatrix * glm::vec4(0.0F, 1.0F, 0.0F, 0.0F));
|
|
|
|
if (!MetaCoreIsUsableDirection(cameraForward)) {
|
|
cameraForward = glm::vec3(0.0F, 0.0F, -1.0F);
|
|
}
|
|
if (!MetaCoreIsUsableDirection(cameraUp)) {
|
|
cameraUp = glm::vec3(0.0F, 1.0F, 0.0F);
|
|
}
|
|
|
|
sceneView.CameraPosition = cameraPosition;
|
|
sceneView.CameraTarget = cameraPosition + glm::normalize(cameraForward);
|
|
sceneView.CameraUp = glm::normalize(cameraUp);
|
|
sceneView.VerticalFieldOfViewDegrees = camera.FieldOfViewDegrees;
|
|
sceneView.NearClip = camera.NearClip;
|
|
sceneView.FarClip = camera.FarClip;
|
|
return true;
|
|
}
|
|
|
|
} // namespace MetaCore
|