Skip to content

Commit 6f8a4ca

Browse files
committed
Add button and shortcut to focus the selected object
1 parent bc417d7 commit 6f8a4ca

File tree

7 files changed

+106
-8
lines changed

7 files changed

+106
-8
lines changed

include/core/CameraController.hpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,19 @@ struct CameraController {
2323

2424
float zoom_speed{1.0f};
2525

26-
void update(float delta_time, bool handle_scroll);
26+
void update(float delta_time, bool handle_input, bool handle_scroll);
27+
void animate_to(glm::vec3 position, glm::vec3 target, float duration);
28+
void focus_on(InstancedNode const& node);
2729

2830
private:
31+
struct {
32+
bool active{false};
33+
glm::vec3 position;
34+
glm::vec3 target;
35+
float remaining_time;
36+
} m_animation;
37+
38+
void update_animation(float delta_time);
2939
void update_freecam(float delta_time, bool handle_scroll);
3040
void update_blender(float delta_time, bool handle_scroll);
3141
void update_unity(float delta_time, bool handle_scroll);

include/ui/ObjectDetails.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#pragma once
22

3+
struct CameraController;
4+
35
struct ObjectDetails {
46
ObjectDetails();
5-
void render();
7+
8+
// FIXME: Avoid passing the camera controller to this function
9+
void render(CameraController&);
610
};

include/ui/Viewport.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ struct Viewport {
1717
Viewport();
1818
void render(double delta_time);
1919

20+
CameraController& camera_controller() { return m_camera_controller; }
21+
2022
private:
2123
Framebuffer m_framebuffer;
2224
Framebuffer m_blitted_framebuffer;

src/core/CameraController.cpp

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,17 @@ CameraController::CameraController(Type type, glm::vec3 camera_position)
1010
camera = std::make_unique<Camera>(camera_position, camera_position + direction);
1111
}
1212

13-
void CameraController::update(float delta_time, bool handle_scroll)
13+
void CameraController::update(float delta_time, bool handle_input, bool handle_scroll)
1414
{
15+
if (m_animation.active) {
16+
update_animation(delta_time);
17+
return;
18+
}
19+
20+
if (!handle_input) {
21+
return;
22+
}
23+
1524
switch (type) {
1625
case Type::FREECAM:
1726
update_freecam(delta_time, handle_scroll);
@@ -25,6 +34,71 @@ void CameraController::update(float delta_time, bool handle_scroll)
2534
}
2635
}
2736

37+
void CameraController::animate_to(glm::vec3 position, glm::vec3 target, float duration)
38+
{
39+
m_animation.active = true;
40+
m_animation.position = position;
41+
m_animation.target = target;
42+
m_animation.remaining_time = duration;
43+
}
44+
45+
void CameraController::focus_on(InstancedNode const& node)
46+
{
47+
auto const duration = 0.3f;
48+
49+
auto const world_center = glm::vec3{node.model_matrix * glm::vec4{0.0f, 0.0f, 0.0f, 1.0f}};
50+
auto radius = 0.0f;
51+
node.traverse([&](glm::mat4 model_matrix, Node const& node) {
52+
for (auto const& mesh : node.meshes) {
53+
auto const world_aabb_min = model_matrix * glm::vec4{mesh.aabb.min, 1.0f};
54+
auto const world_aabb_max = model_matrix * glm::vec4{mesh.aabb.max, 1.0f};
55+
radius = std::max(radius, std::abs(world_center.x - world_aabb_min.x));
56+
radius = std::max(radius, std::abs(world_center.y - world_aabb_min.y));
57+
radius = std::max(radius, std::abs(world_center.z - world_aabb_min.z));
58+
radius = std::max(radius, std::abs(world_center.x - world_aabb_max.x));
59+
radius = std::max(radius, std::abs(world_center.y - world_aabb_max.y));
60+
radius = std::max(radius, std::abs(world_center.z - world_aabb_max.z));
61+
}
62+
});
63+
64+
if (radius < 0.1f) {
65+
return;
66+
}
67+
68+
auto const distance = radius * 1.5f;
69+
70+
auto const look_direction = glm::normalize(camera->target - camera->position);
71+
72+
switch (type) {
73+
case Type::FREECAM:
74+
case Type::UNITY: {
75+
auto const target_position = world_center - look_direction * distance;
76+
animate_to(target_position, target_position + look_direction, duration);
77+
break;
78+
}
79+
case Type::BLENDER: {
80+
}
81+
animate_to(world_center - look_direction * distance, world_center, duration);
82+
}
83+
}
84+
85+
void CameraController::update_animation(float delta_time)
86+
{
87+
if (!m_animation.active) {
88+
return;
89+
}
90+
91+
auto factor = delta_time / m_animation.remaining_time;
92+
m_animation.remaining_time -= delta_time;
93+
if (factor >= 1.0f) {
94+
factor = 1.0f;
95+
m_animation.active = false;
96+
}
97+
98+
camera->target = factor * m_animation.target + (1 - factor) * camera->target;
99+
camera->position = factor * m_animation.position + (1 - factor) * camera->position;
100+
}
101+
28102
std::pair<float, float> direction_to_yaw_pitch(glm::vec3 direction)
29103
{
30104
float pitch = std::asin(direction.y);

src/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ int main()
172172

173173
setup_dock_builder(); // create docking layout before components are rendered
174174

175-
object_details_pane.render();
175+
object_details_pane.render(viewport_window.camera_controller());
176176
object_selection_tree.render();
177177
asset_browser.render();
178178
settings_pane.render();

src/ui/ObjectDetails.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "ui/ObjectDetails.hpp"
22
#include "core/Project.hpp"
3+
#include "ui/Viewport.hpp"
34
#include <imgui.h>
45
#include <string>
56

@@ -49,7 +50,7 @@ void reset_instance_transform(InstancedNode* node)
4950

5051
char object_label[128] = {""};
5152

52-
void ObjectDetails::render()
53+
void ObjectDetails::render(CameraController& camera_controller)
5354
{
5455
auto transform_changed = false;
5556
auto project = Project::get_current();
@@ -126,6 +127,11 @@ void ObjectDetails::render()
126127
if (ImGui::Button("Reset")) {
127128
ImGui::OpenPopup("reset_mode");
128129
}
130+
131+
ImGui::SameLine();
132+
if (ImGui::Button("Focus Camera [F]")) {
133+
camera_controller.focus_on(*project->selected_node);
134+
}
129135
}
130136

131137
if (project->scene && transform_changed) {

src/ui/Viewport.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ void Viewport::render(double delta_time)
3535
m_camera_controller.camera->position = config.camera_position;
3636
m_camera_controller.camera->target = config.camera_target;
3737

38-
if (ImGui::IsWindowFocused()) {
39-
m_camera_controller.update(delta_time, ImGui::IsWindowHovered());
40-
}
38+
m_camera_controller.update(delta_time, ImGui::IsWindowFocused(), ImGui::IsWindowHovered());
4139

4240
auto size = ImGui::GetContentRegionAvail();
4341
if (size.x != m_framebuffer.width || size.y != m_framebuffer.height) {
@@ -211,6 +209,10 @@ void Viewport::render(double delta_time)
211209
project->selected_node = nullptr;
212210
}
213211
}
212+
213+
if (ImGui::IsWindowFocused() && project->selected_node && ImGui::IsKeyPressed(ImGuiKey_F, false)) {
214+
m_camera_controller.focus_on(*project->selected_node);
215+
}
214216
}
215217

216218
// Focus Viewport window not only with the left, but also the middle and right mouse button.

0 commit comments

Comments
 (0)