Flutter 伪 3D 绘制#02 | 地平面与透视

上一篇我们实现了三维空间点到二维平面的映射,并且绘制了坐标轴。本文将进一步完善三维空间的视觉表现,如下所示,构建一个地平面网格, 并且具有透视效果:


1. 地平面绘制

在数学的立体几何中,一些辅助线可以更好地帮我们理解三维空间。 这里准备在 X-Y 平面绘制一个网格,体现出地平线,这可以在视觉上让我们更具有归属感:

绘制网格非常简单,主要就是找到坐标,遍历收集线条绘制。如下代码中,遍历 6 次,收集横纵方向上各 6 条线:

dart 复制代码
void _drawGrid(Canvas canvas) {
  List<(Point3D, Point3D)> lines = [];
  for (double i = 0; i <= 5; i++) {
    lines.add((Point3D(i, 0, 0), Point3D(i, 5, 0)));
    lines.add((Point3D(0, i, 0), Point3D(5, i, 0)));
  }
  
  Paint paint = Paint() ..color = Colors.white..strokeWidth = 1;
  for (var line in lines) {
    Offset p0 = project(line.$1);
    Offset p1 = project(line.$2);
    canvas.drawLine(p0, p1, paint);
  }
}

然后可以修改一下遍历的个数,以及线的长度,就可以轻松实现一个 10*10 的网格:

dart 复制代码
List<(Point3D, Point3D)> lines = [];
for (double i = -5; i <= 5; i++) {
  lines.add((Point3D(i, -5, 0), Point3D(i, 5, 0)));
  lines.add((Point3D(-5, i, 0), Point3D(5, i, 0)));
}

2. 透视效果

仔细观察不难看出,目前的地平面每条线都是平行的,这对于近大远小的视觉感来说比较为何,特别是旋转角度后,这种绝对的平行会产生违和感:


那么该如何在当前的效果上施加 透视 的魔法呢?如下效果的对比可以看出,施加透视之后,感官上舒适了很多:

未透视 透视效果

透视效果本质上还是在三维点到二维点映射过程,根据视觉规律进行的转换。如下所示,两行代码即可在转换过程中施加透视效果:

dart 复制代码
// 3D点投影到2D平面
Offset project(Point3D p) {
  double scale = 32.0; // 缩放系数
  double angle = 30 / 180 * pi; // 30度弧度值(π/6)
  // 绕Z轴旋转
  final rx = p.x * cos(rotationZ) - p.y * sin(rotationZ);
  final ry = p.x * sin(rotationZ) + p.y * cos(rotationZ);
  // 等轴测投影
  final xProj = (rx - ry) * cos(angle);
  final yProj = (rx + ry) * sin(angle) - p.z;
  // 增加透视
  double d = 18.0;
  double radio = d / (d - yProj);
  return Offset(xProj * scale * radio, yProj * scale * radio);
}

当动态修改 d 的值,可以调整透视的效果,如下所示。至于为什么这样就可以实现透视,以及 d 的具体作用。不用着急,后续会一点点分析揭秘:


多绘制一些直线,可以更好地表现地平面和透视的效果。如下所示,在旋转过程中,外部延伸的线条可以联想成路面,越往远处路面线的长度越短,符合透视的规律:

dart 复制代码
List<(Point3D, Point3D)> lines = [];
for (double i = -32; i <= 32; i++) {
  lines.add((Point3D(i, -5, 0), Point3D(i, 5, 0)));
  lines.add((Point3D(-5, i, 0), Point3D(5, i, 0)));
}

尾声

本想这一篇介绍一下映射原理的,但是发现增加透视会有更好的感官体验,绘制地平面也可以更好地为之后的分析做铺垫。下一篇我将会详细分析一下投影的映射逻辑,敬请期待 ~

更多文章和视频知识资讯,大家可以关注我的公众号、掘金和 B 站 。

相关推荐
九丝城主23 分钟前
2025使用VM虚拟机安装配置Macos苹果系统下Flutter开发环境保姆级教程--上篇
服务器·flutter·macos·vmware
瓜子三百克5 小时前
七、性能优化
flutter·性能优化
雨白9 小时前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
kk爱闹11 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空13 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭13 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日14 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安14 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑14 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟18 小时前
CTF Web的数组巧用
android