ADD: object movement system
This commit is contained in:
@@ -6,10 +6,10 @@ Work-In-Progress Vulkan render engine
|
|||||||
Current structure:
|
Current structure:
|
||||||
- Flexible render graph system with multiple render passes, Hot reloading
|
- Flexible render graph system with multiple render passes, Hot reloading
|
||||||
- Deferred rendering
|
- Deferred rendering
|
||||||
- PBR (IBL is WIP), cascaded shadows, normal mapping (MikkTSpace tangents optional)
|
- PBR, cascaded shadows, normal mapping (MikkTSpace tangents optional)
|
||||||
- GLTF loading and rendering, primitive creation and rendering.
|
- GLTF loading and rendering, primitive creation and rendering.
|
||||||
- Supports texture compression(BCn, non glTF standard), LRU reload
|
- Supports texture compression(BCn, non glTF standard), LRU reload
|
||||||
- IBL
|
- Object clicking, generation.
|
||||||
|
|
||||||
Work-In-Progress
|
Work-In-Progress
|
||||||
- [ ] TAA
|
- [ ] TAA
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "render/vk_renderpass_tonemap.h"
|
#include "render/vk_renderpass_tonemap.h"
|
||||||
#include "render/vk_renderpass_background.h"
|
#include "render/vk_renderpass_background.h"
|
||||||
#include <glm/gtx/euler_angles.hpp>
|
#include <glm/gtx/euler_angles.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include "render/rg_graph.h"
|
#include "render/rg_graph.h"
|
||||||
#include "core/vk_pipeline_manager.h"
|
#include "core/vk_pipeline_manager.h"
|
||||||
#include "core/texture_cache.h"
|
#include "core/texture_cache.h"
|
||||||
@@ -755,7 +756,23 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
SceneManager *sceneMgr = eng->_sceneManager.get();
|
SceneManager *sceneMgr = eng->_sceneManager.get();
|
||||||
const GPUSceneData &sceneData = sceneMgr->getSceneData();
|
|
||||||
|
// Choose a pick to edit: prefer last pick, then hover.
|
||||||
|
VulkanEngine::PickInfo *pick = nullptr;
|
||||||
|
if (eng->_lastPick.valid)
|
||||||
|
{
|
||||||
|
pick = &eng->_lastPick;
|
||||||
|
}
|
||||||
|
else if (eng->_hoverPick.valid)
|
||||||
|
{
|
||||||
|
pick = &eng->_hoverPick;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pick || pick->ownerName.empty())
|
||||||
|
{
|
||||||
|
ImGui::TextUnformatted("No selection for gizmo (pick or hover an instance).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static ImGuizmo::OPERATION op = ImGuizmo::TRANSLATE;
|
static ImGuizmo::OPERATION op = ImGuizmo::TRANSLATE;
|
||||||
static ImGuizmo::MODE mode = ImGuizmo::LOCAL;
|
static ImGuizmo::MODE mode = ImGuizmo::LOCAL;
|
||||||
@@ -778,24 +795,106 @@ namespace
|
|||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
MeshInstance,
|
MeshInstance,
|
||||||
GLTFInstance,
|
GLTFInstance
|
||||||
Node
|
|
||||||
};
|
};
|
||||||
GizmoTarget target = GizmoTarget::None;
|
GizmoTarget target = GizmoTarget::None;
|
||||||
|
|
||||||
|
if (pick->ownerType == RenderObject::OwnerType::MeshInstance)
|
||||||
|
{
|
||||||
|
if (sceneMgr->getMeshInstanceTransform(pick->ownerName, targetTransform))
|
||||||
|
{
|
||||||
|
target = GizmoTarget::MeshInstance;
|
||||||
|
ImGui::Text("Editing mesh instance: %s", pick->ownerName.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pick->ownerType == RenderObject::OwnerType::GLTFInstance)
|
||||||
|
{
|
||||||
|
if (sceneMgr->getGLTFInstanceTransform(pick->ownerName, targetTransform))
|
||||||
|
{
|
||||||
|
target = GizmoTarget::GLTFInstance;
|
||||||
|
ImGui::Text("Editing glTF instance: %s", pick->ownerName.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target == GizmoTarget::None)
|
||||||
|
{
|
||||||
|
ImGui::TextUnformatted("Gizmo only supports dynamic mesh/glTF instances.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ImGuiIO &io = ImGui::GetIO();
|
ImGuiIO &io = ImGui::GetIO();
|
||||||
ImGuizmo::SetOrthographic(false);
|
ImGuizmo::SetOrthographic(false);
|
||||||
ImGuizmo::SetDrawlist();
|
ImGuizmo::SetDrawlist();
|
||||||
ImGuizmo::SetRect(0.0f, 0.0f, io.DisplaySize.x, io.DisplaySize.y);
|
ImGuizmo::SetRect(0.0f, 0.0f, io.DisplaySize.x, io.DisplaySize.y);
|
||||||
|
|
||||||
glm::mat4 view = sceneData.view;
|
// Build a distance-based perspective projection for ImGuizmo instead of
|
||||||
glm::mat4 proj = sceneData.proj;
|
// using the engine's reversed-Z Vulkan projection.
|
||||||
|
Camera &cam = sceneMgr->getMainCamera();
|
||||||
|
float fovRad = glm::radians(cam.fovDegrees);
|
||||||
|
VkExtent2D extent = eng->_swapchainManager
|
||||||
|
? eng->_swapchainManager->swapchainExtent()
|
||||||
|
: VkExtent2D{1, 1};
|
||||||
|
float aspect = extent.height > 0
|
||||||
|
? static_cast<float>(extent.width) / static_cast<float>(extent.height)
|
||||||
|
: 1.0f;
|
||||||
|
|
||||||
proj[1][1] *= -1.0f;
|
// Distance from camera to object; clamp to avoid degenerate planes.
|
||||||
|
glm::vec3 camPos = cam.position;
|
||||||
|
glm::vec3 objPos = pick->worldPos;
|
||||||
|
float dist = glm::length(objPos - camPos);
|
||||||
|
if (!std::isfinite(dist) || dist <= 0.0f)
|
||||||
|
{
|
||||||
|
dist = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Near/far based on distance: keep ratio reasonable for precision.
|
||||||
|
float nearPlane = glm::max(0.05f, dist * 0.05f);
|
||||||
|
float farPlane = glm::max(nearPlane * 50.0f, dist * 2.0f);
|
||||||
|
|
||||||
|
glm::mat4 view = cam.getViewMatrix();
|
||||||
|
glm::mat4 proj = glm::perspective(fovRad, aspect, nearPlane, farPlane);
|
||||||
|
|
||||||
|
glm::mat4 before = targetTransform;
|
||||||
|
|
||||||
|
ImDrawList* dl = ImGui::GetForegroundDrawList();
|
||||||
|
ImGuizmo::SetDrawlist(dl);
|
||||||
|
|
||||||
|
ImGuizmo::SetRect(0.0f, 0.0f, io.DisplaySize.x, io.DisplaySize.y);
|
||||||
ImGuizmo::Manipulate(&view[0][0], &proj[0][0],
|
ImGuizmo::Manipulate(&view[0][0], &proj[0][0],
|
||||||
op, mode,
|
op, mode,
|
||||||
&targetTransform[0][0]);
|
&targetTransform[0][0]);
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
for (int c = 0; c < 4 && !changed; ++c)
|
||||||
|
{
|
||||||
|
for (int r = 0; r < 4; ++r)
|
||||||
|
{
|
||||||
|
if (before[c][r] != targetTransform[c][r])
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
{
|
||||||
|
switch (target)
|
||||||
|
{
|
||||||
|
case GizmoTarget::MeshInstance:
|
||||||
|
sceneMgr->setMeshInstanceTransform(pick->ownerName, targetTransform);
|
||||||
|
break;
|
||||||
|
case GizmoTarget::GLTFInstance:
|
||||||
|
sceneMgr->setGLTFInstanceTransform(pick->ownerName, targetTransform);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep pick debug info roughly in sync.
|
||||||
|
pick->worldTransform = targetTransform;
|
||||||
|
pick->worldPos = glm::vec3(targetTransform[3]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|||||||
@@ -344,6 +344,28 @@ void SceneManager::addMeshInstance(const std::string &name, std::shared_ptr<Mesh
|
|||||||
dynamicMeshInstances[name] = std::move(inst);
|
dynamicMeshInstances[name] = std::move(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SceneManager::getMeshInstanceTransform(const std::string &name, glm::mat4 &outTransform)
|
||||||
|
{
|
||||||
|
auto it = dynamicMeshInstances.find(name);
|
||||||
|
if (it == dynamicMeshInstances.end())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
outTransform = it->second.transform;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SceneManager::setMeshInstanceTransform(const std::string &name, const glm::mat4 &transform)
|
||||||
|
{
|
||||||
|
auto it = dynamicMeshInstances.find(name);
|
||||||
|
if (it == dynamicMeshInstances.end())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
it->second.transform = transform;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool SceneManager::removeMeshInstance(const std::string &name)
|
bool SceneManager::removeMeshInstance(const std::string &name)
|
||||||
{
|
{
|
||||||
return dynamicMeshInstances.erase(name) > 0;
|
return dynamicMeshInstances.erase(name) > 0;
|
||||||
@@ -391,6 +413,17 @@ bool SceneManager::removeGLTFInstance(const std::string &name)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SceneManager::getGLTFInstanceTransform(const std::string &name, glm::mat4 &outTransform)
|
||||||
|
{
|
||||||
|
auto it = dynamicGLTFInstances.find(name);
|
||||||
|
if (it == dynamicGLTFInstances.end())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
outTransform = it->second.transform;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool SceneManager::setGLTFInstanceTransform(const std::string &name, const glm::mat4 &transform)
|
bool SceneManager::setGLTFInstanceTransform(const std::string &name, const glm::mat4 &transform)
|
||||||
{
|
{
|
||||||
auto it = dynamicGLTFInstances.find(name);
|
auto it = dynamicGLTFInstances.find(name);
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ public:
|
|||||||
void addMeshInstance(const std::string &name, std::shared_ptr<MeshAsset> mesh,
|
void addMeshInstance(const std::string &name, std::shared_ptr<MeshAsset> mesh,
|
||||||
const glm::mat4 &transform = glm::mat4(1.f),
|
const glm::mat4 &transform = glm::mat4(1.f),
|
||||||
std::optional<BoundsType> boundsType = {});
|
std::optional<BoundsType> boundsType = {});
|
||||||
|
bool getMeshInstanceTransform(const std::string &name, glm::mat4 &outTransform);
|
||||||
|
bool setMeshInstanceTransform(const std::string &name, const glm::mat4 &transform);
|
||||||
bool removeMeshInstance(const std::string &name);
|
bool removeMeshInstance(const std::string &name);
|
||||||
void clearMeshInstances();
|
void clearMeshInstances();
|
||||||
|
|
||||||
@@ -108,6 +110,7 @@ public:
|
|||||||
void addGLTFInstance(const std::string &name, std::shared_ptr<LoadedGLTF> scene,
|
void addGLTFInstance(const std::string &name, std::shared_ptr<LoadedGLTF> scene,
|
||||||
const glm::mat4 &transform = glm::mat4(1.f));
|
const glm::mat4 &transform = glm::mat4(1.f));
|
||||||
bool removeGLTFInstance(const std::string &name);
|
bool removeGLTFInstance(const std::string &name);
|
||||||
|
bool getGLTFInstanceTransform(const std::string &name, glm::mat4 &outTransform);
|
||||||
bool setGLTFInstanceTransform(const std::string &name, const glm::mat4 &transform);
|
bool setGLTFInstanceTransform(const std::string &name, const glm::mat4 &transform);
|
||||||
void clearGLTFInstances();
|
void clearGLTFInstances();
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ def parse_gltf_roles(gltf_path: Path):
|
|||||||
def mark(uri, role):
|
def mark(uri, role):
|
||||||
if not uri:
|
if not uri:
|
||||||
return
|
return
|
||||||
# normal > albedo > mr 우선
|
|
||||||
prio = {"normal": 3, "albedo": 2, "mr": 1}
|
prio = {"normal": 3, "albedo": 2, "mr": 1}
|
||||||
old = roles.get(uri)
|
old = roles.get(uri)
|
||||||
if old is None or prio[role] > prio.get(old, 0):
|
if old is None or prio[role] > prio.get(old, 0):
|
||||||
|
|||||||
Reference in New Issue
Block a user