【问题标题】:flutter convert 3d points to 2d points颤振将3d点转换为2d点
【发布时间】:2020-01-13 18:13:53
【问题描述】:

我有来自 obj 的 3d 点,我希望能够选择一个点,比如 v -0.822220 0.216242 -0.025730 并用容器覆盖它并保存该点。(我有一个车辆 3d obj,我希望能够选择说出司机的车门并保存选择的点(可能是门把手)。

样本点:

v 0.822220 0.216242 -0.025730 v -0.822220 0.216242 -0.025730 v 0.811726 0.220845 0.029668 v -0.811726 0.220845 0.029668 v 0.777874 0.214472 0.075458 v -0.777874 0.214472 0.075458 v 0.724172 0.189587 0.073470 v -0.724172 0.189587 0.073470 v 0.704111 0.180226 0.027508

我的成就

    return new GestureDetector(
      onTapDown: (TapDownDetails details) => onTapDown(context, details),
      child: new Stack(fit: StackFit.expand, children: <Widget>[
         Object3D(...),
        new Positioned(
          child: new Container(color:Colors.red),
          left: posx,
          top: posy,
        )
      ]),
    );

void onTapDown(BuildContext context, TapDownDetails details) {
    print('${details.globalPosition}');
    final RenderBox box = context.findRenderObject();
    final Offset localOffset = box.globalToLocal(details.globalPosition);
    setState(() {
      posx = localOffset.dx;
      posy = localOffset.dy;
    });
  }

。我建议将点转换为 2d 并使用 2d 点覆盖容器。如何将 3d 点转换为 2d 点?

有更好的方法吗?

我正在使用这个包flutter_3d_obj

【问题讨论】:

    标签: flutter dart 3d flutter-layout


    【解决方案1】:

    (免责声明:Dart/Flutter 中的 3D 图形非常具有实验性。Flutter 不提供任何 3D 渲染上下文来绘制 3D 对象,并且任何 3D 渲染包(例如 flutter_3d_obj)都是基于软件的,因此非常慢,并且 B) 功能集极其有限 [即缺乏光照、阴影、法线、纹理等]。因此,不建议尝试直接在 Flutter 中绘制 3D 对象。建议是使用类似 flare 使用2D动画复制3D效果或使用类似 Unity3D Widget 包在非-Flutter 画布。)


    从 3D 空间中的点到 2D 平面的转换称为Projection Transformation。这种转变是 3D 软件中所有“相机”的基础,从简单的游戏到 3D 动画好莱坞电影。关于投影变换的工作原理有很多优秀的文章(谷歌搜索会找到this one),但下面是过于简化的解释。

    (与任何其他转换一样,这需要线性代数和矩阵乘法。幸运的是,Dart 在vector_math 中有一个矩阵数学包。)

    投影变换有两种一般类型:透视和正交。

    正交是最容易概念化和实现的,因为它只是从 3D 空间中的一个点到平面上最接近该点的位置的平面转换。它实际上只是从 3D 点中剥离 Z 坐标,并使用 X 和 Y 坐标作为新的 2D 点:

                                                            

    import 'package:vector_math/vector_math.dart';
    
    Vector2 transformPointOrtho(Vector3 input) {
      final ortho = Matrix4(
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 0, 0,
        0, 0, 0, 0,
      );
      return (ortho * input).xy;
    }
    

    透视更复杂,因为它还考虑了透视(也称为视野角度)。因此,有一些参数会用于创建转换矩阵:

                                                     

    • n = 近剪裁平面
    • f = 远剪裁平面
    • S = 垂直视角的表示,由以下公式得出:

                                                                

    • fov = 视场角 (FOV) 度数
      • (要使用弧度,请省略“* (π/180)”部分)
    import 'dart:math';
    
    import 'package:vector_math/vector_math.dart';
    
    Vector2 transformPointPersp(Vector3 input, double fovDeg, double nearClip, double farClip) {
      final s = 1 / (tan((fovDeg / 2) * (pi / 180)));
      final fdfn = -farClip / (farClip - nearClip);
      final fndfn = -(farClip * nearClip) / (farClip - nearClip);
      final persp = Matrix4(
        s, 0, 0, 0,
        0, s, 0, 0,
        0, 0, fdfn, -1,
        0, 0, fndfn, 0,
      );
      return (input * persp).xy;
    }
    

    显然,这是一种过于简单化的解释,并未考虑相机位置/旋转等因素。这也是形成变换矩阵的最简单方法,但不一定是最好的。为了进一步阅读,我强烈建议您查看各种线性代数和低级 3D 渲染教程(例如上面链接的教程)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-11
      相关资源
      最近更新 更多