ADD: object movement system
This commit is contained in:
@@ -6,10 +6,10 @@ Work-In-Progress Vulkan render engine
|
||||
Current structure:
|
||||
- Flexible render graph system with multiple render passes, Hot reloading
|
||||
- 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.
|
||||
- Supports texture compression(BCn, non glTF standard), LRU reload
|
||||
- IBL
|
||||
- Object clicking, generation.
|
||||
|
||||
Work-In-Progress
|
||||
- [ ] TAA
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "render/vk_renderpass_tonemap.h"
|
||||
#include "render/vk_renderpass_background.h"
|
||||
#include <glm/gtx/euler_angles.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include "render/rg_graph.h"
|
||||
#include "core/vk_pipeline_manager.h"
|
||||
#include "core/texture_cache.h"
|
||||
@@ -755,7 +756,23 @@ namespace
|
||||
}
|
||||
|
||||
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::MODE mode = ImGuizmo::LOCAL;
|
||||
@@ -778,24 +795,106 @@ namespace
|
||||
{
|
||||
None,
|
||||
MeshInstance,
|
||||
GLTFInstance,
|
||||
Node
|
||||
GLTFInstance
|
||||
};
|
||||
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();
|
||||
ImGuizmo::SetOrthographic(false);
|
||||
ImGuizmo::SetDrawlist();
|
||||
ImGuizmo::SetRect(0.0f, 0.0f, io.DisplaySize.x, io.DisplaySize.y);
|
||||
|
||||
glm::mat4 view = sceneData.view;
|
||||
glm::mat4 proj = sceneData.proj;
|
||||
// Build a distance-based perspective projection for ImGuizmo instead of
|
||||
// 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],
|
||||
op, mode,
|
||||
&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
|
||||
|
||||
|
||||
@@ -344,6 +344,28 @@ void SceneManager::addMeshInstance(const std::string &name, std::shared_ptr<Mesh
|
||||
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)
|
||||
{
|
||||
return dynamicMeshInstances.erase(name) > 0;
|
||||
@@ -391,6 +413,17 @@ bool SceneManager::removeGLTFInstance(const std::string &name)
|
||||
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)
|
||||
{
|
||||
auto it = dynamicGLTFInstances.find(name);
|
||||
|
||||
@@ -95,6 +95,8 @@ public:
|
||||
void addMeshInstance(const std::string &name, std::shared_ptr<MeshAsset> mesh,
|
||||
const glm::mat4 &transform = glm::mat4(1.f),
|
||||
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);
|
||||
void clearMeshInstances();
|
||||
|
||||
@@ -108,6 +110,7 @@ public:
|
||||
void addGLTFInstance(const std::string &name, std::shared_ptr<LoadedGLTF> scene,
|
||||
const glm::mat4 &transform = glm::mat4(1.f));
|
||||
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);
|
||||
void clearGLTFInstances();
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ def parse_gltf_roles(gltf_path: Path):
|
||||
def mark(uri, role):
|
||||
if not uri:
|
||||
return
|
||||
# normal > albedo > mr 우선
|
||||
|
||||
prio = {"normal": 3, "albedo": 2, "mr": 1}
|
||||
old = roles.get(uri)
|
||||
if old is None or prio[role] > prio.get(old, 0):
|
||||
|
||||
Reference in New Issue
Block a user