Dandelion
2.0.0
A light-weight 3D builder for educational usage
Toggle main menu visibility
载入中...
搜索中...
未找到
scene.h
浏览该文件的文档.
1
#ifndef DANDELION_SCENE_SCENE_H
2
#define DANDELION_SCENE_SCENE_H
3
4
#include <memory>
5
#include <string>
6
#include <vector>
7
#include <list>
8
#include <chrono>
9
#include <string_view>
10
11
#include <spdlog/spdlog.h>
12
13
#include "
group.h
"
14
#include "
camera.h
"
15
#include "
light.h
"
16
#include "selection_helper.h"
17
#include "
../geometry/mesh.hpp
"
18
#include "
../geometry/halfedge.h
"
19
20
/*!
21
* \file scene/scene.h
22
* \ingroup rendering
23
* \ingroup simulation
24
* \~chinese
25
* \brief 包含场景的类。
26
*/
27
28
/*! \~chinese 约束 `F` 必须是对单个物体进行的读写操作。 */
29
template
<
typename
F>
30
concept
ObjectOp
= std::invocable<F, Object&> && std::is_void_v<std::invoke_result_t<F, Object&>>;
31
32
/*! \~chinese 约束 `F` 必须是对单个物体进行的只读操作。 */
33
template
<
typename
F>
34
concept
ObjectReadOp
=
35
std::invocable<F, const Object&> && std::is_void_v<std::invoke_result_t<F, const Object&>>;
36
37
/*!
38
* \ingroup rendering
39
* \ingroup simulation
40
* \~chinese
41
* \brief 表示一个包含相机、光源、物体等对象的完整场景。
42
*
43
* `Scene` 是一个对象语义的类,它既包含完成图形设计和渲染所需的全部数据,
44
* 也具有渲染自身预览效果的功能。当前的设计是:控制器 (Controller) 在 OpenGL
45
* 上下文被创建后即创建场景实例,该实例在程序的整个生命周期中都是唯一的。因此,
46
* 复制或移动 `Scene` 实例都是错误的行为,因为这有可能导致场景数据不一致。
47
* 未来加入修改历史记录时,此设计思路有可能被改变。
48
*
49
* 场景可以是空的,如果它非空,则可以包含若干个物体组 (Group);
50
* 每个组也可以为空或包含若干物体 (Object),物体是场景中的最小单元,不能再分了。
51
* 各种数据遵循“尽可能存储到更小单元中”的原则,因此 `Scene` 类中只存储相机、
52
* 光源这些与任何物体都无关的数据,而材质、mesh 等数据则存储到物体中。
53
* 所有物体都由 `Scene` 对象创建并持有,当 `Scene` 对象析构时,所有的组、
54
* 物体都会自行析构。
55
*/
56
class
Scene
57
{
58
public
:
59
60
Scene();
61
///@{
62
/*! \~chinese 禁止复制场景。 */
63
Scene
(Scene& other) =
delete
;
64
Scene
(
const
Scene& other) =
delete
;
65
///@}
66
/*! \~chinese 禁止移动场景。 */
67
Scene
(Scene&& other) =
delete
;
68
~Scene() =
default
;
69
/*!
70
* \~chinese
71
* \brief 从指定路径导入模型文件到这个场景中。
72
*
73
* 这个函数只会根据文件名创建一个物体组,然后调用物体组的 `load_models` 方法加载文件。
74
*
75
* \param file_path 要导入的模型文件路径
76
* \returns 加载是否成功
77
*/
78
bool
import_model
(
const
std::string& file_path);
79
/*!
80
* \~chinese
81
* \brief 保存所有场景数据到指定的目录中。
82
*
83
* 保存场景时涉及两类数据:
84
* - 模型数据(包括几何数据和材质数据),会被保存为通用模型文件格式
85
* - 元数据,Dandelion 特有的组、物体信息等,会被保存为 metadata.json 文件
86
*
87
* \param directory 场景文件夹路径
88
* \returns 是否保存成功
89
*/
90
bool
save
(
const
std::string_view directory);
91
/*!
92
* \~chinese
93
* \brief 从指定目录中加载保存的场景数据。
94
*
95
* 与 `save` 方法相对应,`load` 会从保存的数据中恢复模型、物体、组、相机、
96
* 光源等全部信息。
97
* \param directory 要加载的场景文件夹路径
98
* \returns 是否加载成功
99
*/
100
bool
load
(
const
std::string_view directory);
101
/*!
102
* \~chinese
103
* \brief 清除场景中所有元素
104
*/
105
void
clear
();
106
/*! \~chinese 备份物体当前状态并开始模拟,此后每一帧都会调用所有物体的 `update` 方法。 */
107
void
start_simulation
();
108
/*! \~chinese 停止模拟,此后不再调用物体的 `update` 方法。 */
109
void
stop_simulation
();
110
/*! \~chinese 恢复物体在动画开始前的状态。 */
111
void
reset_simulation
();
112
/*! \~chinese 查询当前是否正在进行物理模拟。 */
113
bool
check_during_simulation
();
114
/*!
115
* \~chinese
116
* \brief 计算场景中所有物体下一帧要渲染的运动状态。
117
*
118
* 这个函数按照固定的时间步长模拟物体运动。
119
*
120
* 每一帧的渲染过程可以概括为更新数据(几何、运动等等)和渲染图像两步。
121
* 约定当前屏幕上显示的是上一帧的图像,正在计算的是当前帧的数据。
122
* 更新运动状态时首先用当前时间减去 `last_update` 得到上一帧和之前帧剩余时长之和;
123
* 再循环模拟物体运动。每循环一次走过一个长度为 `time_step` 的时间步、
124
* 剩余时长减去 `time_step` ;当剩余时长不足一个 `time_step` 时停止模拟,
125
* 并将这一帧模拟走过的总时长累加到 `last_update` 上。
126
*/
127
void
simulation_update
();
128
129
/*!
130
* \~chinese
131
* 对每个物体执行同样的操作,允许读写物体数据。
132
* \param op 要执行的操作,其函数签名必须满足 `ObjectOp` 的要求。
133
*/
134
template
<ObjectOp F>
135
void
for_each_object
(F&& op)
136
{
137
for
(std::unique_ptr<Group>& group: this->
groups
)
138
for
(std::unique_ptr<Object>&
object
: group->objects) op(*
object
);
139
}
140
141
/*!
142
* \~chinese
143
* 对每个物体执行同样的操作,只能读取物体数据。
144
* \param op 要执行的操作,其函数签名必须满足 `ObjectReadOp` 的要求。
145
*/
146
template
<ObjectReadOp F>
147
void
for_each_object
(F&& op)
const
148
{
149
for
(
const
std::unique_ptr<Group>& group: this->
groups
)
150
for
(
const
std::unique_ptr<Object>&
object
: group->objects) op(*
object
);
151
}
152
153
/*! \~chinese 场景中所有的物体组。 */
154
std::vector<std::unique_ptr<Group>>
groups
;
155
/*!
156
* \~chinese
157
* \brief 当前被选中的物体。
158
*
159
* 在布局模式和物理模拟模式下,它决定当前被高亮的物体;在建模模式下,仅有这个物体被绘制。
160
*/
161
Object
*
selected_object
;
162
/*!
163
* \~chinese
164
* \brief 当前被选中的元素。
165
*
166
* 根据当前所处的模式,物体、各类几何基本元素、光源都可能被选中,详见 `SelectableType`
167
* 的类型说明。当 `selected_element` 持有 `std::monostate` 类型时,
168
* 当前的选择状态为空(没有任何元素被选中)。
169
*/
170
SelectableType
selected_element
;
171
/*! \~chinese 用于预览场景的观察相机(主相机)。 */
172
Camera
main_camera
;
173
/*! \~chinese 用于 **离线渲染** 的相机,和用于预览场景的观察相机(主相机)无关。 */
174
Camera
camera
;
175
/*! \~chinese 用于 **离线渲染** 的光源,和预览时照亮物体的光源无关。 */
176
std::list<Light>
lights
;
177
/*! \~chinese 用于建模模式的半边网格。 */
178
std::unique_ptr<HalfedgeMesh>
halfedge_mesh
;
179
/*! \~chinese 用于在物理模拟模式下显示速度向量。 */
180
ArrowSet
arrows
;
181
/*! \~chinese 用于显示地面网格。 */
182
LineSet
ground_grid
;
183
/*! \~chinese 用于显示 x 轴。 */
184
LineSet
x_axis
;
185
/*! \~chinese 用于显示 y 轴。 */
186
LineSet
y_axis
;
187
/*! \~chinese 用于显示 z 轴。 */
188
LineSet
z_axis
;
189
/*! \~chinese 用于显示离线渲染相机。 */
190
LineSet
camera_wireframe
;
191
/*! \~chinese 被选中元素类型为顶点、边、面片或光源时使用的绘制对象。 */
192
Mesh
highlighted_element
;
193
/*! \~chinese 被选中元素类型为半边时使用的绘制对象。 */
194
ArrowSet
highlighted_halfedge
;
195
/*! \~chinese 显示拾取射线用的绘制对象,对应 `DebugOptions::show_picking_ray` 。 */
196
LineSet
picking_ray
;
197
/*! \~chinese 显示光源。这个 Mesh 中只包含一个光源示意图的几何数据,渲染时需要多次绘制。 */
198
Mesh
light_indicator
;
199
200
private
:
201
202
/*!
203
* \~chinese
204
* 主相机的初始位置。
205
*/
206
static
Eigen::Vector3f
initial_camera_pos
;
207
/*!
208
* \~chinese
209
* 主相机的初始观察目标点(看向的位置)。
210
*/
211
static
Eigen::Vector3f
initial_camera_target
;
212
/*!
213
* \~chinese
214
* 保存场景元数据的文件名。
215
*/
216
static
constexpr
std::string_view
metadata_filename
=
"metadata.json"
;
217
/*! \~chinese 状态变量,表示当前是否正在进行物理模拟。 */
218
bool
during_animation
;
219
/*! \~chinese 上一次将模拟状态同步到渲染的时间点。 */
220
std::chrono::time_point<std::chrono::steady_clock>
last_update
;
221
/*! \~chinese 碰撞检测时记录所有物体,其他情况下无效。 */
222
std::vector<Object*>
all_objects
;
223
/*! \~chinese 日志记录器。 */
224
std::shared_ptr<spdlog::logger>
logger
;
225
};
226
227
#endif
// DANDELION_SCENE_SCENE_H
camera.h
包含相机的类,用来表示场景中的相机。
Object
表示物体的类。
定义
object.h:39
Scene::z_axis
LineSet z_axis
定义
scene.h:188
Scene::picking_ray
LineSet picking_ray
定义
scene.h:196
Scene::selected_element
SelectableType selected_element
当前被选中的元素。
定义
scene.h:170
Scene::arrows
ArrowSet arrows
定义
scene.h:180
Scene::y_axis
LineSet y_axis
定义
scene.h:186
Scene::during_animation
bool during_animation
定义
scene.h:218
Scene::highlighted_halfedge
ArrowSet highlighted_halfedge
定义
scene.h:194
Scene::reset_simulation
void reset_simulation()
定义
scene.cpp:276
Scene::highlighted_element
Mesh highlighted_element
定义
scene.h:192
Scene::check_during_simulation
bool check_during_simulation()
定义
scene.cpp:287
Scene::Scene
Scene(Scene &other)=delete
Scene::groups
std::vector< std::unique_ptr< Group > > groups
定义
scene.h:154
Scene::load
bool load(const std::string_view directory)
从指定目录中加载保存的场景数据。
定义
scene.cpp:190
Scene::logger
std::shared_ptr< spdlog::logger > logger
定义
scene.h:224
Scene::stop_simulation
void stop_simulation()
定义
scene.cpp:271
Scene::initial_camera_target
static Eigen::Vector3f initial_camera_target
定义
scene.h:211
Scene::import_model
bool import_model(const std::string &file_path)
从指定路径导入模型文件到这个场景中。
定义
scene.cpp:112
Scene::clear
void clear()
清除场景中所有元素
定义
scene.cpp:245
Scene::lights
std::list< Light > lights
定义
scene.h:176
Scene::for_each_object
void for_each_object(F &&op) const
定义
scene.h:147
Scene::initial_camera_pos
static Eigen::Vector3f initial_camera_pos
定义
scene.h:206
Scene::ground_grid
LineSet ground_grid
定义
scene.h:182
Scene::start_simulation
void start_simulation()
定义
scene.cpp:256
Scene::light_indicator
Mesh light_indicator
定义
scene.h:198
Scene::halfedge_mesh
std::unique_ptr< HalfedgeMesh > halfedge_mesh
定义
scene.h:178
Scene::Scene
Scene(const Scene &other)=delete
Scene::for_each_object
void for_each_object(F &&op)
定义
scene.h:135
Scene::main_camera
Camera main_camera
定义
scene.h:172
Scene::x_axis
LineSet x_axis
定义
scene.h:184
Scene::save
bool save(const std::string_view directory)
保存所有场景数据到指定的目录中。
定义
scene.cpp:128
Scene::metadata_filename
static constexpr std::string_view metadata_filename
定义
scene.h:216
Scene::last_update
std::chrono::time_point< std::chrono::steady_clock > last_update
定义
scene.h:220
Scene::all_objects
std::vector< Object * > all_objects
定义
scene.h:222
Scene::camera_wireframe
LineSet camera_wireframe
定义
scene.h:190
Scene::selected_object
Object * selected_object
当前被选中的物体。
定义
scene.h:161
Scene::Scene
Scene(Scene &&other)=delete
Scene::simulation_update
void simulation_update()
计算场景中所有物体下一帧要渲染的运动状态。
定义
scene.cpp:292
Scene::camera
Camera camera
定义
scene.h:174
ObjectOp
定义
scene.h:30
ObjectReadOp
定义
scene.h:34
group.h
包含物体组的类。
SelectableType
std::variant< std::monostate, Object *, const Halfedge *, Vertex *, Edge *, Face *, Light * > SelectableType
场景中可被选择的元素类型。
定义
selection_helper.h:36
halfedge.h
半边网格所需各种类型的公共头文件。
light.h
包含光源的类,目前只有一个点光源。
mesh.hpp
ArrowSet
用于渲染箭头的特殊线条集。
定义
mesh.hpp:125
Camera
表示观察点的相机,既可以用于预览视角,也可以用于渲染视角。
定义
camera.h:24
LineSet
用于同步线条渲染数据的内存对象。
定义
mesh.hpp:72
Mesh
用于同步渲染数据的三角形 Mesh 。
定义
mesh.hpp:28
src
scene
scene.h
制作者
1.18.0