第 7 次大作业进展报告
4/11/25About 3 min
问题
请编写带有图形界面的普通三阶魔方模拟程序.
要求:
- 实现平移、放大、缩小和自适应大小的魔方展示功能.
- 请自定义编码表示魔方的各种可能操作, 每种编码表示其中 1 种操作.
- 实现打开文本文件的功能, 该文本文件由一系列编码组成, 对应魔方操作.
- 实现魔方操作功能: 可以交互实现每个操作, 也可以通过动画自动播放魔方的系列操作.
- 在操作或转动魔方时, 必须以动画的形式展示, 从而方便看清如何操作或转动.
- 可以保存魔方操作, 保存结果是由一系列编码组成文本文件.
- 编写文档详细介绍模拟算法与图形界面等内容.
参考:
- 雍俊海. 清华教授的小课堂魔方真好玩. 北京: 清华大学出版社.
1. 魔方分割方法
1.1 三维网格划分体系
本系统采用 3 x 3 x 3 的立体网格对魔方进行空间划分, 将魔方解构为 26 个可见小立方体 (排除中心不可见单元). 每个网格单元使用三维坐标 (x, y, z) 唯一标识, 坐标取值范围为 {0, 1, 2}.
1.2 分组命名规则
通过 group_name(...) 函数实现坐标到分组名的映射:
auto group_name(int x, int y, int z) -> std::string {
return fmt::format("{}{}{}", x, y, z);
}示例: 坐标 (0, 2, 1) 对应分组 “021”
1.3 面片归属判定
// 几何中心计算: 对每个面片计算包围盒中心坐标
glm::vec3 center = (shape_bound_max + shape_bound_min) / 2.0f;
// 网格映射: 将中心坐标映射到 3×3×3 网格
glm::ivec3 grid = glm::floor((center - scene_bound_min) / cube_length);
// 动态分组: 根据计算结果将面片加入对应分组
polyscope::getSurfaceMesh(shape.name)->addToGroup(name);1.4 面层选择算法
通过 select_meshes(...) 函数实现面层选择:
case 'f': // 选择前面 (z = 2 平面)
if(z == 2) groups.push_back(group_name(x, y, z));
break;各面层对应条件:
- (F)ront:
z == 2 - (B)ack:
z == 0 - (U)p:
y == 2 - (D)own:
y == 0 - (L)eft:
x == 0 - ®ight:
x == 2
2. 魔方动画实现
2.1 核心动画算法
旋转轴选择策略:
- F/B 面: 绕 Z 轴
- U/D 面: 绕 Y 轴
- L/R 面: 绕 X 轴
void callback() {
rotation += 0.01f; // 每帧增加旋转角度
mesh->setTransform(glm::rotate(rotation, axis));
}2.2 动画控制逻辑 (TODO)
- 状态管理
- 动画队列机制
- 帧间插值计算
2.3 操作指令映射 (TODO)
定义操作编码规范:
| 编码 | 含义 | 旋转角度 |
|---|---|---|
| F | 前面顺时针 | 90° |
| F’ | 前面逆时针 | -90° |
| U2 | 上面 180° | 180° |
3. 实现效果展示
4. 后续工作计划
- 完善操作指令解析模块
- 实现文件操作序列的导入/导出
- 添加碰撞检测优化动画效果
- 开发用户交互控制面板