Skip to content

Commit

Permalink
Replaced some glm usage with fastgltf built-ins.
Browse files Browse the repository at this point in the history
  • Loading branch information
stripe2933 authored and LEE KYOUNGHEON committed Nov 26, 2024
1 parent fe2dba3 commit 4e0122e
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 98 deletions.
31 changes: 17 additions & 14 deletions impl/MainApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,12 +254,7 @@ void vk_gltf_viewer::MainApp::run() {
imguiTaskCollector.inputControl(appState.camera, appState.automaticNearFarPlaneAdjustment, appState.useFrustumCulling, appState.hoveringNodeOutline, appState.selectedNodeOutline);
imguiTaskCollector.imguizmo(appState.camera, appState.gltfAsset.and_then([this](auto &x) {
return value_if(x.selectedNodeIndices.size() == 1, [&]() {
return std::tuple<fastgltf::Asset&, std::span<const glm::mat4>, std::uint16_t, ImGuizmo::OPERATION> {
x.asset,
gltf->sceneHierarchy.nodeWorldTransforms,
*x.selectedNodeIndices.begin(),
appState.imGuizmoOperation,
};
return std::tie(x.asset, gltf->sceneHierarchy.nodeWorldTransforms, *x.selectedNodeIndices.begin(), appState.imGuizmoOperation);
});
}));
}
Expand Down Expand Up @@ -322,7 +317,7 @@ void vk_gltf_viewer::MainApp::run() {
// Adjust the camera based on the scene enclosing sphere.
const auto &[center, radius] = gltf->sceneMiniball;
const float distance = radius / std::sin(appState.camera.fov / 2.f);
appState.camera.position = center - glm::dvec3 { distance * normalize(appState.camera.direction) };
appState.camera.position = glm::make_vec3(center.data()) - glm::dvec3 { distance * normalize(appState.camera.direction) };
appState.camera.zMin = distance - radius;
appState.camera.zMax = distance + radius;
appState.camera.targetDistance = distance;
Expand Down Expand Up @@ -363,7 +358,7 @@ void vk_gltf_viewer::MainApp::run() {
// Adjust the camera based on the scene enclosing sphere.
const auto &[center, radius] = gltf->sceneMiniball;
const float distance = radius / std::sin(appState.camera.fov / 2.f);
appState.camera.position = center - glm::dvec3 { distance * normalize(appState.camera.direction) };
appState.camera.position = glm::make_vec3(center.data()) - glm::dvec3 { distance * normalize(appState.camera.direction) };
appState.camera.zMin = distance - radius;
appState.camera.zMax = distance + radius;
appState.camera.targetDistance = distance;
Expand Down Expand Up @@ -413,21 +408,25 @@ void vk_gltf_viewer::MainApp::run() {
// Scene enclosing sphere would be changed. Adjust the camera's near/far plane if necessary.
if (appState.automaticNearFarPlaneAdjustment) {
const auto &[center, radius]
= (gltf->sceneMiniball = gltf::algorithm::getMiniball(gltf->asset, gltf->scene, LIFT(gltf->sceneGpuBuffers.getMeshNodeWorldTransform)));
appState.camera.tightenNearFar(center, radius);
= gltf->sceneMiniball
= gltf::algorithm::getMiniball(
gltf->asset, gltf->scene, [this](std::size_t nodeIndex, std::size_t instanceIndex) {
return cast<double>(gltf->sceneGpuBuffers.getMeshNodeWorldTransform(nodeIndex, instanceIndex));
});
appState.camera.tightenNearFar(glm::make_vec3(center.data()), radius);
}
},
[this](control::task::TightenNearFarPlane) {
if (gltf) {
const auto &[center, radius] = gltf->sceneMiniball;
appState.camera.tightenNearFar(center, radius);
appState.camera.tightenNearFar(glm::make_vec3(center.data()), radius);
}
},
[this](control::task::ChangeCameraView) {
if (appState.automaticNearFarPlaneAdjustment && gltf) {
// Tighten near/far plane based on the scene enclosing sphere.
const auto &[center, radius] = gltf->sceneMiniball;
appState.camera.tightenNearFar(center, radius);
appState.camera.tightenNearFar(glm::make_vec3(center.data()), radius);
}
},
[&](control::task::InvalidateDrawCommandSeparation) {
Expand Down Expand Up @@ -556,13 +555,17 @@ vk_gltf_viewer::MainApp::Gltf::Gltf(
assetGpuBuffers { asset, gpu, threadPool, assetExternalBuffers },
assetGpuTextures { asset, directory, gpu, threadPool, assetExternalBuffers },
sceneGpuBuffers { asset, scene, sceneHierarchy, gpu, assetExternalBuffers },
sceneMiniball{ gltf::algorithm::getMiniball(asset, scene, LIFT(sceneGpuBuffers.getMeshNodeWorldTransform)) } { }
sceneMiniball { gltf::algorithm::getMiniball(asset, scene, [this](std::size_t nodeIndex, std::size_t instanceIndex) {
return cast<double>(sceneGpuBuffers.getMeshNodeWorldTransform(nodeIndex, instanceIndex));
}) } { }

void vk_gltf_viewer::MainApp::Gltf::setScene(std::size_t sceneIndex) {
scene = asset.scenes[sceneIndex];
sceneHierarchy = { asset, scene };
sceneGpuBuffers = { asset, scene, sceneHierarchy, gpu, assetExternalBuffers };
sceneMiniball = gltf::algorithm::getMiniball(asset, scene, LIFT(sceneGpuBuffers.getMeshNodeWorldTransform));
sceneMiniball = gltf::algorithm::getMiniball(asset, scene, [this](std::size_t nodeIndex, std::size_t instanceIndex) {
return cast<double>(sceneGpuBuffers.getMeshNodeWorldTransform(nodeIndex, instanceIndex));
});
}

auto vk_gltf_viewer::MainApp::createInstance() const -> vk::raii::Instance {
Expand Down
20 changes: 8 additions & 12 deletions impl/control/ImGuiTaskCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -837,8 +837,7 @@ void vk_gltf_viewer::control::ImGuiTaskCollector::nodeInspector(
}
if (ImGui::Selectable("Transform Matrix", !isTrs) && isTrs) {
const auto &trs = get<fastgltf::TRS>(node.transform);
constexpr fastgltf::math::fmat4x4 identity { 1.f };
node.transform.emplace<fastgltf::math::fmat4x4>(translate(identity, trs.translation) * rotate(identity, trs.rotation) * scale(identity, trs.scale));
node.transform.emplace<fastgltf::math::fmat4x4>(toMatrix(trs));
}
ImGui::EndCombo();
}
Expand Down Expand Up @@ -1067,28 +1066,25 @@ void vk_gltf_viewer::control::ImGuiTaskCollector::inputControl(

void vk_gltf_viewer::control::ImGuiTaskCollector::imguizmo(
Camera &camera,
const std::optional<std::tuple<fastgltf::Asset&, std::span<const glm::mat4>, std::uint16_t, ImGuizmo::OPERATION>> &assetAndNodeWorldTransformsAndSelectedNodeIndexAndImGuizmoOperation
const std::optional<std::tuple<fastgltf::Asset&, std::span<const fastgltf::math::fmat4x4>, std::uint16_t, ImGuizmo::OPERATION>> &assetAndNodeWorldTransformsAndSelectedNodeIndexAndImGuizmoOperation
) {
// Set ImGuizmo rect.
ImGuizmo::BeginFrame();
ImGuizmo::SetRect(centerNodeRect.Min.x, centerNodeRect.Min.y, centerNodeRect.GetWidth(), centerNodeRect.GetHeight());

if (assetAndNodeWorldTransformsAndSelectedNodeIndexAndImGuizmoOperation) {
auto &[asset, nodeWorldTransforms, selectedNodeIndex, operation] = *assetAndNodeWorldTransformsAndSelectedNodeIndexAndImGuizmoOperation;
if (glm::mat4 worldTransform = nodeWorldTransforms[selectedNodeIndex];
Manipulate(value_ptr(camera.getViewMatrix()), value_ptr(camera.getProjectionMatrixForwardZ()), operation, ImGuizmo::MODE::WORLD, value_ptr(worldTransform))) {
fastgltf::math::fmat4x4 deltaMatrix;
if (fastgltf::math::fmat4x4 worldTransform = nodeWorldTransforms[selectedNodeIndex];
Manipulate(value_ptr(camera.getViewMatrix()), value_ptr(camera.getProjectionMatrixForwardZ()), operation, ImGuizmo::MODE::WORLD, worldTransform.data(), deltaMatrix.data())) {

const glm::mat4 deltaMatrix = worldTransform * inverse(nodeWorldTransforms[selectedNodeIndex]);
visit(fastgltf::visitor {
[&](fastgltf::math::fmat4x4 &transformMatrix) {
const glm::mat4 newTransform = deltaMatrix * fastgltf::toMatrix(transformMatrix);
std::copy_n(value_ptr(newTransform), 16, transformMatrix.data());
transformMatrix = deltaMatrix * transformMatrix;
},
[&](fastgltf::TRS &trs) {
const glm::mat4 newTransform = deltaMatrix * toMatrix(trs);
fastgltf::math::fmat4x4 newTransformMatrix;
std::copy_n(value_ptr(newTransform), 16, newTransformMatrix.data());
fastgltf::math::decomposeTransformMatrix(newTransformMatrix, trs.scale, trs.rotation, trs.translation);
const fastgltf::math::fmat4x4 newTransform = deltaMatrix * toMatrix(trs);
decomposeTransformMatrix(newTransform, trs.scale, trs.rotation, trs.translation);
},
}, asset.nodes[selectedNodeIndex].transform);
tasks.emplace_back(std::in_place_type<task::ChangeNodeLocalTransform>, selectedNodeIndex);
Expand Down
6 changes: 3 additions & 3 deletions impl/gltf/AssetSceneGpuBuffers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import :helpers.ranges;
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)
#define LIFT(...) [&](auto &&...xs) { return (__VA_ARGS__)(FWD(xs)...); }

const glm::mat4 &vk_gltf_viewer::gltf::AssetSceneGpuBuffers::getMeshNodeWorldTransform(std::uint16_t nodeIndex, std::uint32_t instanceIndex) const noexcept {
return meshNodeWorldTransformBuffer.asRange<const glm::mat4>()[instanceOffsets[nodeIndex] + instanceIndex];
const fastgltf::math::fmat4x4 &vk_gltf_viewer::gltf::AssetSceneGpuBuffers::getMeshNodeWorldTransform(std::uint16_t nodeIndex, std::uint32_t instanceIndex) const noexcept {
return meshNodeWorldTransformBuffer.asRange<const fastgltf::math::fmat4x4>()[instanceOffsets[nodeIndex] + instanceIndex];
}

std::vector<std::uint32_t> vk_gltf_viewer::gltf::AssetSceneGpuBuffers::createInstanceCounts(const fastgltf::Scene &scene) const {
Expand Down Expand Up @@ -50,7 +50,7 @@ vku::AllocatedBuffer vk_gltf_viewer::gltf::AssetSceneGpuBuffers::createNodeBuffe
vku::AllocatedBuffer stagingBuffer = vku::MappedBuffer {
gpu.allocator,
std::from_range, instanceOffsets | std::views::transform([=](std::uint32_t offset) {
return nodeTransformBufferStartAddress + sizeof(glm::mat4) * offset;
return nodeTransformBufferStartAddress + sizeof(fastgltf::math::fmat4x4) * offset;
}),
gpu.isUmaDevice ? vk::BufferUsageFlagBits::eStorageBuffer : vk::BufferUsageFlagBits::eTransferSrc,
}.unmap();
Expand Down
2 changes: 1 addition & 1 deletion impl/vulkan/Frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ auto vk_gltf_viewer::vulkan::Frame::update(const ExecutionTask &task) -> UpdateR

const gltf::AssetPrimitiveInfo &primitiveInfo = task.gltf->assetGpuBuffers.primitiveInfos.at(&primitive);

const glm::mat4 &nodeWorldTransform = task.gltf->sceneHierarchy.nodeWorldTransforms[nodeIndex];
const glm::mat4 nodeWorldTransform = glm::make_mat4(task.gltf->sceneHierarchy.nodeWorldTransforms[nodeIndex].data());
const glm::vec3 transformedMin { nodeWorldTransform * glm::vec4 { primitiveInfo.min, 1.f } };
const glm::vec3 transformedMax { nodeWorldTransform * glm::vec4 { primitiveInfo.max, 1.f } };

Expand Down
2 changes: 1 addition & 1 deletion interface/MainApp.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ namespace vk_gltf_viewer {
*
* The first of the pair is the center, and the second is the radius of the miniball.
*/
std::pair<glm::dvec3, double> sceneMiniball;
std::pair<fastgltf::math::dvec3, double> sceneMiniball;

Gltf(
fastgltf::Parser &parser,
Expand Down
2 changes: 1 addition & 1 deletion interface/control/ImGuiTaskCollector.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace vk_gltf_viewer::control {
void background(bool canSelectSkyboxBackground, full_optional<glm::vec3> &solidBackground);
void imageBasedLighting(const AppState::ImageBasedLighting &info, vk::DescriptorSet eqmapTextureImGuiDescriptorSet);
void inputControl(Camera &camera, bool& automaticNearFarPlaneAdjustment, bool &useFrustumCulling, full_optional<AppState::Outline> &hoveringNodeOutline, full_optional<AppState::Outline> &selectedNodeOutline);
void imguizmo(Camera &camera, const std::optional<std::tuple<fastgltf::Asset&, std::span<const glm::mat4>, std::uint16_t, ImGuizmo::OPERATION>> &assetAndNodeWorldTransformsAndSelectedNodeIndexAndImGuizmoOperation);
void imguizmo(Camera &camera, const std::optional<std::tuple<fastgltf::Asset&, std::span<const fastgltf::math::fmat4x4>, std::uint16_t, ImGuizmo::OPERATION>> &assetAndNodeWorldTransformsAndSelectedNodeIndexAndImGuizmoOperation);

private:
std::vector<Task> &tasks;
Expand Down
14 changes: 7 additions & 7 deletions interface/gltf/AssetSceneGpuBuffers.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace vk_gltf_viewer::gltf {
/**
* @brief Buffer that stores the mesh nodes' transform matrices, with flattened instance matrices.
*
* The term "mesh node" means a node that has a mesh. This buffer only contains transform matrices of mesh nodes. In other words, <tt>meshNodeWorldTransformBuffer.asRange<const glm::mat4>()[nodeIndex]</tt> may NOT represent the world transformation matrix of the <tt>nodeIndex</tt>-th node, because maybe there were nodes with no mesh prior to the <tt>nodeIndex</tt>-th node.
* The term "mesh node" means a node that has a mesh. This buffer only contains transform matrices of mesh nodes. In other words, <tt>meshNodeWorldTransformBuffer.asRange<const fastgltf::math::fmat4x4>()[nodeIndex]</tt> may NOT represent the world transformation matrix of the <tt>nodeIndex</tt>-th node, because maybe there were nodes with no mesh prior to the <tt>nodeIndex</tt>-th node.
*
* For example, a scene has 4 nodes (denoted as A B C D) and A has 2 instances (<tt>M1</tt>, <tt>M2</tt>), B has 3 instances (<tt>M3</tt>, <tt>M4</tt>, <tt>M5</tt>), C is meshless, and D has 1 instance (<tt>M6</tt>), then the flattened matrices will be laid out as:
* @code
Expand Down Expand Up @@ -67,7 +67,7 @@ namespace vk_gltf_viewer::gltf {
* @warning \p nodeIndex-th node MUST have a mesh. No exception thrown for constraint violation.
* @warning \p instanceIndex-th instance MUST be less than the instance count of the node. No exception thrown for constraint violation.
*/
[[nodiscard]] const glm::mat4 &getMeshNodeWorldTransform(std::uint16_t nodeIndex, std::uint32_t instanceIndex = 0) const noexcept;
[[nodiscard]] const fastgltf::math::fmat4x4 &getMeshNodeWorldTransform(std::uint16_t nodeIndex, std::uint32_t instanceIndex = 0) const noexcept;

/**
* @brief Update the mesh node world transforms from given \p nodeIndex, to its descendants.
Expand All @@ -78,7 +78,7 @@ namespace vk_gltf_viewer::gltf {
*/
template <typename BufferDataAdapter = fastgltf::DefaultBufferDataAdapter>
void updateMeshNodeTransformsFrom(std::uint16_t nodeIndex, const AssetSceneHierarchy &sceneHierarchy, const BufferDataAdapter &adapter = {}) {
const std::span<glm::mat4> meshNodeWorldTransforms = meshNodeWorldTransformBuffer.asRange<glm::mat4>();
const std::span<fastgltf::math::fmat4x4> meshNodeWorldTransforms = meshNodeWorldTransformBuffer.asRange<fastgltf::math::fmat4x4>();
algorithm::traverseNode(*pAsset, nodeIndex, [&](std::size_t nodeIndex) {
const fastgltf::Node &node = pAsset->nodes[nodeIndex];
if (!node.meshIndex) {
Expand All @@ -91,7 +91,7 @@ namespace vk_gltf_viewer::gltf {
else {
for (std::uint32_t instanceIndex : ranges::views::upto(instanceCounts[nodeIndex])) {
meshNodeWorldTransforms[instanceOffsets[nodeIndex] + instanceIndex]
= sceneHierarchy.nodeWorldTransforms[nodeIndex] * fastgltf::toMatrix(instanceTransforms[instanceIndex]);
= sceneHierarchy.nodeWorldTransforms[nodeIndex] * instanceTransforms[instanceIndex];
}
}
});
Expand Down Expand Up @@ -196,7 +196,7 @@ namespace vk_gltf_viewer::gltf {
vma::Allocator allocator,
const BufferDataAdapter &adapter
) const {
std::vector<glm::mat4> meshNodeWorldTransforms(instanceOffsets.back() + instanceCounts.back());
std::vector<fastgltf::math::fmat4x4> meshNodeWorldTransforms(instanceOffsets.back() + instanceCounts.back());
algorithm::traverseScene(*pAsset, scene, [&](std::size_t nodeIndex) {
const fastgltf::Node &node = pAsset->nodes[nodeIndex];
if (!node.meshIndex) {
Expand All @@ -209,14 +209,14 @@ namespace vk_gltf_viewer::gltf {
else {
for (std::uint32_t instanceIndex : ranges::views::upto(instanceCounts[nodeIndex])) {
meshNodeWorldTransforms[instanceOffsets[nodeIndex] + instanceIndex]
= sceneHierarchy.nodeWorldTransforms[nodeIndex] * fastgltf::toMatrix(instanceTransforms[instanceIndex]);
= sceneHierarchy.nodeWorldTransforms[nodeIndex] * instanceTransforms[instanceIndex];
}
}
});

return vku::MappedBuffer {
allocator,
std::from_range, meshNodeWorldTransforms,
std::from_range, as_bytes(std::span { meshNodeWorldTransforms }),
vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eShaderDeviceAddress,
};
}
Expand Down
Loading

0 comments on commit 4e0122e

Please sign in to comment.