Flutter 颤振-将三维点转换为二维点

Flutter 颤振-将三维点转换为二维点,flutter,dart,3d,flutter-layout,Flutter,Dart,3d,Flutter Layout,我有一个obj的3d点,我想能够选择一个点,比如说v-0.822220 0.216242-0.025730,然后用一个容器覆盖它并保存该点。(我有一个车辆3d obj,我想能够选择,比如说驾驶员车门并保存所选点,可能是一个车门把手) 样本点: v0.822220.216242-0.025730-0.822220.216242-0.025730-0.811726 0.220845 0.029668-0.811726 0.220845 0.029668-0.777874 0.214472 0.075

我有一个obj的3d点,我想能够选择一个点,比如说v-0.822220 0.216242-0.025730,然后用一个容器覆盖它并保存该点。(我有一个车辆3d obj,我想能够选择,比如说驾驶员车门并保存所选点,可能是一个车门把手)

样本点:

v0.822220.216242-0.025730-0.822220.216242-0.025730-0.811726 0.220845 0.029668-0.811726 0.220845 0.029668-0.777874 0.214472 0.075458-0.777874 0.214472 0.075458-0.724172 0.189587 0.073470-0.724172 0.189587 0.073470-0.704111 0.180226

我所取得的成就

    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;
    });
  }
返回新的手势检测器(
onTapDown:(tappdownDetails)=>onTapDown(上下文,细节),
子项:新堆栈(拟合:StackFit.expand,子项:[
Object3D(…),
新定位(
子容器:新容器(颜色:Colors.red),
左:posx,
上图:波西,
)
]),
);
void onTapDown(BuildContext上下文,tappdownDetails){
打印(“${details.globalPosition}”);
final RenderBox=context.findenderObject();
最终偏移量localOffset=box.globalToLocal(details.globalPosition);
设置状态(){
posx=localOffset.dx;
posy=localOffset.dy;
});
}
。我得到一个建议,将点转换为二维点,并使用二维点覆盖容器。如何将三维点转换为二维点

有更好的方法吗

我正在使用这个软件包(免责声明:Dart/FLATTER中的3D图形是非常实验性的。FLATTER不提供任何3D渲染上下文来绘制3D对象,任何3D渲染软件包(如FLATTER_3D_obj)都是A)基于软件的,因此速度非常慢,B)功能集非常有限[即缺少照明、着色、法线、纹理等]。因此,不建议尝试直接在颤振中绘制3D对象。建议使用类似于使用2D动画复制3D效果的工具,或使用类似于软件包的工具在非颤振画布上绘制3D图形。)


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

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

投影变换通常有两种类型:透视变换和正交变换

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

import'package:vector_math/vector_math.dart';
Vector2 transformPointOrtho(Vector3输入){
最终正交=矩阵x4(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
);
返回(正交*输入).xy;
}
透视图更为复杂,因为它还考虑了透视图(也称为视野角度)。因此,创建变换矩阵时有一些参数:

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

  • fov=视野(fov)角度,单位为度
    • (要使用弧度,请省略“*(π/180)”部分)
import'dart:math';
导入“package:vector_math/vector_math.dart”;
Vector2 transformPointPersp(Vector3输入,双fovDeg,双近夹,双远夹){
最终s=1/(tan((fovDeg/2)*(pi/180));
最终fdfn=-farClip/(farClip-nearClip);
最终fndfn=-(farClip*nearClip)/(farClip-nearClip);
最终人员=矩阵4(
s、 0,0,0,
0,s,0,0,
0,0,fdfn,-1,
0,0,fndfn,0,
);
返回(输入*persp).xy;
}

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