Dandelion
2.0.0
A light-weight 3D builder for educational usage
Toggle main menu visibility
载入中...
搜索中...
未找到
controller.h
浏览该文件的文档.
1
#ifndef DANDELION_UI_CONTROLLER_H
2
#define DANDELION_UI_CONTROLLER_H
3
4
/*!
5
* \file ui/controller.h
6
*/
7
8
#include <memory>
9
10
#include <spdlog/spdlog.h>
11
#include <nlohmann/json.hpp>
12
13
#include "
menubar.h
"
14
#include "
toolbar.h
"
15
#include "../scene/selection_helper.h"
16
#include "
../scene/scene.h
"
17
#include "
../render/preview_renderer.h
"
18
19
/*!
20
* \ingroup ui
21
* \~chinese
22
* \brief 控制器管理所有的界面组件,并处理和预览视角操作(例如旋转、缩放或者平移)相关的输入。
23
*
24
* 控制器的生命周期就是整个程序 GUI 的生命周期,因此这是一个单例的类。其唯一一个实例可以通过
25
* `controller()` 这个静态方法访问,访问操作是线程安全的(但访问后的修改不是)。
26
* 控制器创建并持有所有与图形界面相关的资源:
27
*
28
* - 界面元素(菜单栏和工具栏)
29
* - 场景(包含所有物体、坐标轴等)
30
*
31
* 界面元素本身不存储场景,也不保存指向场景的引用等。控制器在每一帧将场景的引用传递给
32
* `Toolbar::render` 或 `Menubar::render` 函数,从而允许这些界面元素访问场景。
33
* 与 `Menubar` 或 `Toolbar` 保存引用相比,这种设计当前并没有额外有点,它只是参考 Scotty3D
34
* 思路的结果,将来有可能为引入全局撤销 (Undo) 和重做 (Redo) 操作提供方便。
35
*/
36
class
Controller
37
{
38
public
:
39
40
/*!
41
* \~chinese
42
* \brief 获取 `Controller` 类的唯一实例。
43
*
44
* 唯一的实例被定义成函数内的静态变量,在 C++ 11 及之后的标准中,这种定义方式是线程安全的。
45
*/
46
static
Controller
&
controller
();
47
///@{
48
/*! \~chinese 禁止复制构造。*/
49
Controller
(
Controller
& other) =
delete
;
50
Controller
&
operator=
(
Controller
& other) =
delete
;
51
///@}
52
~Controller
();
53
/*! \~chinese 清理需要手动释放而不能随析构自动处理的资源。 */
54
void
shutdown
();
55
/*!
56
* \~chinese
57
* \brief 将鼠标拖动转换为旋转视角或平移视角操作。
58
*
59
* 当按下鼠标中键(或 Alt+鼠标左键)拖动时旋转视角,按下 Ctrl+鼠标左键拖动时平移视角。
60
* 同时按下 Alt 和 Ctrl 的效果与只按下 Alt 相同(只旋转不平移)。
61
*
62
* \param initial 为真表示开始拖动时调用,为假表示拖动过程中调用。
63
*/
64
void
on_mouse_dragged
(
bool
initial);
65
/*!
66
* \~chinese
67
* \brief 根据鼠标点击选取场景中的物体。
68
*
69
* 这个函数将鼠标点击的屏幕坐标 (screen space) 转换为观察坐标 (view space),
70
* 然后将观察坐标转换回世界坐标 (world space),从而构造一条从观察相机(主相机)
71
* 发出的射线,按这条射线与场景中物体的相交结果拾取(选中)场景中的可选中对象。
72
* 工作于布局模式和物理模拟模式下时,它调用 `pick_object` 函数,工作于建模模式下时,
73
* 它调用 `pick_element` 函数。
74
*/
75
void
on_picking
();
76
/*!
77
* \~chinese
78
* \brief 将拨动鼠标滚轮的操作转换为视角拉进或远离。
79
*
80
* 缩放视角的操作按指数规律执行:鼠标滚轮每滚动一个单位,观察相机到目标点的距离就乘上一个固定值
81
* `wheel_scroll_factor`,即
82
*
83
* \f[
84
* \mathbf{d}_\text{new}=\text{wheel_scroll_factor}^\text{wheel_delta}\cdot\mathbf{d}
85
* \f]
86
*/
87
void
on_wheel_scrolled
();
88
/*!
89
* \~chinese
90
* \brief 在缩放窗口时调整轨迹球半径、预览视角(相机)Y 方向的 FoV,并更新自身记录的窗口尺寸。
91
*
92
* 虽然名字相同,但这个函数并非 GLFW 的窗口缩放回调函数。在缩放时它会被真正的回调函数
93
* `Platform::on_framebuffer_resized` 调用。
94
* \param width 缩放后的窗口宽度
95
* \param height 缩放后的窗口高度
96
*/
97
void
on_framebuffer_resized
(
float
width,
float
height);
98
/*!
99
* \~chinese
100
* \brief 处理关于场景操作的输入。
101
*
102
* 这个函数判别鼠标操作是否对应于某种场景操作(调整视角、拾取物体等),并调用相应的处理函数
103
* (例如 `on_mouse_clicked` 或 `on_picking`)。与场景操作相对的是控件操作(例如点击按钮),
104
* 控件操作由相应的 ImGui 控件直接处理。
105
*/
106
void
process_input
();
107
/*!
108
* \~chinese
109
* 渲染场景和各个 UI 组件。控制器本身不直接渲染任何内容,而是调用相应类的 `render()` 方法。
110
* \param renderer 预览渲染器实例。
111
*/
112
void
render
(
PreviewRenderer
& renderer);
113
/*!
114
* \~chinese
115
* 在加载场景前重置 UI 的状态,避免加载场景时控制器仍有不当的数据引用。
116
*/
117
void
return_to_safe_state
();
118
/*!
119
* \~english All variables used for layout are float because ImVec2 expects float.
120
* \~chinese 由于 ImGui 使用浮点数表示尺寸,所有和布局相关的变量都是浮点型。
121
*/
122
///@{
123
float
window_width
,
window_height
;
124
float
toolbar_width
;
125
///@}
126
127
private
:
128
129
/*!
130
* \~chinese
131
* \brief 选择一个元素。
132
*
133
* 这个函数修改控制器记录的选择状态。它包括两步动作:
134
* 1. 调用 `unselect` 清除原先的选择状态及其副作用
135
* 2. 修改被选中元素 `selected_element`,调用 `select_[type]` 函数执行具体操作
136
*
137
* \param element 要选择的新元素
138
*/
139
void
select
(
SelectableType
element);
140
/*!
141
* \~chinese
142
* \brief 取消选择。
143
*
144
* 这个函数清楚当前的选择状态,将`selected_element` 重置为 `std::monostate`
145
* 并清空 `highlighted_element` 或 `highlighted_halfedge` 这些高亮元素。
146
* 如果之前的被选中元素设置过 `Scene` 等对象的属性,它也会一并将其重置。
147
*/
148
void
unselect
();
149
/*!
150
* \~chinese
151
* \brief 拾取物体。
152
*
153
* 在布局或物理模拟模式下,根据射线求交的结果选择物体。
154
* \param ray 根据点击位置生成的射线(世界坐标系下)
155
*/
156
void
pick_object
(
Ray
& ray);
157
/*!
158
* \~chinese
159
* \brief 拾取半边、顶点、边或面片。
160
*
161
* 在建模模式下,根据射线求交的结果选择半边网格上的基本元素。
162
* \param ray 根据点击位置生成的射线(世界坐标系下)
163
*/
164
void
pick_element
(
Ray
& ray);
165
/*! \~chinese 选择物体并更新 `Scene::selected_object` 。 */
166
void
select_object
(
Object
*
object
);
167
/*! \~chinese 选择半边并更新 `highlighted_halfedge` 。 */
168
void
select_halfedge
(
const
Halfedge
* halfedge);
169
/*! \~chinese 选择顶点并更新 `highlighted_element` 。 */
170
void
select_vertex
(
Vertex
* vertex);
171
/*! \~chinese 选择边并更新 `highlighted_element` 。 */
172
void
select_edge
(
Edge
* edge);
173
/*! \~chinese 选择面片并更新 `highlighted_element` 。 */
174
void
select_face
(
Face
* face);
175
/*! \~chinese 选择光源并更新 `highlighted_element` 。 */
176
void
select_light
(
Light
* light);
177
/*!
178
* \~chinese
179
* \brief 将鼠标拖动转换为轨迹球 (Trackball) 操作,用于旋转预览视角。
180
*
181
* 轨迹球曲面的推导参考 [Object Mouse
182
* Trackball](https://www.khronos.org/opengl/wiki/Object_Mouse_Trackball)。
183
* \param initial 为真表示开始拖动时调用,为假表示拖动过程中调用。
184
*/
185
void
on_rotating
(
bool
initial);
186
/*!
187
* \~chinese
188
* \brief 将鼠标拖动转换为视角平移。
189
*
190
* 将鼠标拖动时屏幕坐标的变化量换算为观察空间 (view space) 中的坐标变化,
191
* 光标向右移动对应相机向左移动,光标向上移动对应相机向下移动。
192
* 相应的变化量会累加到主相机的 `position` 和 `target` 属性上,因此平移过程中视线方向不会改变。
193
*
194
* 视点到观察点的距离增大(减小)时,相同屏幕坐标变化量对应的观察坐标变化量也增大(减小),
195
* 平移量正比于视角远近,比例系数为 `mouse_translation_factor` 。
196
* \param initial 为真表示开始拖动时调用,为假表示拖动过程中调用。
197
*/
198
void
on_translating
(
bool
initial);
199
/*! \~chinese 缩放视角的控制系数,详见 `on_wheel_scrolled` 方法。 */
200
static
constexpr
float
wheel_scroll_factor
= 0.8f;
201
/*! \~chinese 平移视角时屏幕坐标到观察坐标换算系数的固定部分。 */
202
static
constexpr
float
mouse_translation_factor
= 0.001f;
203
/*! \~chinese 构造函数是私有的。 */
204
Controller
();
205
/*!
206
* \~chinese
207
* \brief 全局工作模式。
208
*
209
* 控制器维护着当前的工作模式,决定各种功能可用或禁用。其他的 GUI 组件持有对该变量的引用。
210
*/
211
WorkingMode
mode
;
212
/*! \~chinese 一些帮助调试的选项,详见 `UI::DebugOptions` 类型说明。 */
213
DebugOptions
debug_options
;
214
/*! \~chinese 菜单栏。 */
215
std::unique_ptr<UI::Menubar>
menubar
;
216
/*! \~chinese 工具栏。 */
217
std::unique_ptr<UI::Toolbar>
toolbar
;
218
/*! \~chinese 包含所有三维数据的场景实例。 */
219
std::unique_ptr<Scene>
scene
;
220
/*! \~chinese 日志记录器。 */
221
std::shared_ptr<spdlog::logger>
logger
;
222
/*! \~chinese 当前的轨迹球半径,决定轨迹球控制曲面上球面和双曲面部分的相切位置。 */
223
float
trackball_radius
;
224
};
225
226
#endif
// DANDELION_UI_CONTROLLER_H
Controller::select_object
void select_object(Object *object)
定义
controller.cpp:388
Controller::select_light
void select_light(Light *light)
定义
controller.cpp:434
Controller::select_halfedge
void select_halfedge(const Halfedge *halfedge)
定义
controller.cpp:394
Controller::on_rotating
void on_rotating(bool initial)
将鼠标拖动转换为轨迹球 (Trackball) 操作,用于旋转预览视角。
定义
controller.cpp:447
Controller::toolbar
std::unique_ptr< UI::Toolbar > toolbar
定义
controller.h:217
Controller::on_framebuffer_resized
void on_framebuffer_resized(float width, float height)
在缩放窗口时调整轨迹球半径、预览视角(相机)Y 方向的 FoV,并更新自身记录的窗口尺寸。
定义
controller.cpp:150
Controller::on_wheel_scrolled
void on_wheel_scrolled()
将拨动鼠标滚轮的操作转换为视角拉进或远离。
定义
controller.cpp:140
Controller::select_vertex
void select_vertex(Vertex *vertex)
定义
controller.cpp:402
Controller::on_translating
void on_translating(bool initial)
将鼠标拖动转换为视角平移。
定义
controller.cpp:504
Controller::mode
WorkingMode mode
全局工作模式。
定义
controller.h:211
Controller::return_to_safe_state
void return_to_safe_state()
定义
controller.cpp:526
Controller::logger
std::shared_ptr< spdlog::logger > logger
定义
controller.h:221
Controller::select_face
void select_face(Face *face)
定义
controller.cpp:420
Controller::pick_element
void pick_element(Ray &ray)
拾取半边、顶点、边或面片。
定义
controller.cpp:323
Controller::mouse_translation_factor
static constexpr float mouse_translation_factor
定义
controller.h:202
Controller::operator=
Controller & operator=(Controller &other)=delete
Controller::controller
static Controller & controller()
获取 Controller 类的唯一实例。
定义
controller.cpp:34
Controller::unselect
void unselect()
取消选择。
定义
controller.cpp:269
Controller::wheel_scroll_factor
static constexpr float wheel_scroll_factor
定义
controller.h:200
Controller::render
void render(PreviewRenderer &renderer)
定义
controller.cpp:241
Controller::shutdown
void shutdown()
定义
controller.cpp:92
Controller::Controller
Controller()
定义
controller.cpp:40
Controller::window_height
float window_height
定义
controller.h:123
Controller::on_mouse_dragged
void on_mouse_dragged(bool initial)
将鼠标拖动转换为旋转视角或平移视角操作。
定义
controller.cpp:99
Controller::on_picking
void on_picking()
根据鼠标点击选取场景中的物体。
定义
controller.cpp:113
Controller::scene
std::unique_ptr< Scene > scene
定义
controller.h:219
Controller::window_width
float window_width
定义
controller.h:123
Controller::toolbar_width
float toolbar_width
定义
controller.h:124
Controller::Controller
Controller(Controller &other)=delete
Controller::select
void select(SelectableType element)
选择一个元素。
定义
controller.cpp:253
Controller::trackball_radius
float trackball_radius
定义
controller.h:223
Controller::pick_object
void pick_object(Ray &ray)
拾取物体。
定义
controller.cpp:299
Controller::debug_options
DebugOptions debug_options
定义
controller.h:213
Controller::select_edge
void select_edge(Edge *edge)
定义
controller.cpp:409
Controller::menubar
std::unique_ptr< UI::Menubar > menubar
定义
controller.h:215
Controller::process_input
void process_input()
处理关于场景操作的输入。
定义
controller.cpp:158
Object
表示物体的类。
定义
object.h:39
PreviewRenderer
用于实时预览的渲染器。
定义
preview_renderer.h:28
SelectableType
std::variant< std::monostate, Object *, const Halfedge *, Vertex *, Edge *, Face *, Light * > SelectableType
场景中可被选择的元素类型。
定义
selection_helper.h:36
menubar.h
preview_renderer.h
用于实时预览的渲染器。
WorkingMode
WorkingMode
定义
rendering.hpp:55
scene.h
包含场景的类。
DebugOptions
辅助调试的 GUI 选项。
定义
rendering.hpp:94
Edge
半边网格中的边。
定义
halfedge.h:115
Face
半边网格中的面片。
定义
halfedge.h:148
Halfedge
半边网格中最关键的几何元素。
定义
halfedge.h:43
Light
表示一个点光源的类。
定义
light.h:19
Ray
定义
ray.h:24
Vertex
半边网格中的顶点。
定义
halfedge.h:83
toolbar.h
src
ui
controller.h
制作者
1.18.0