C#/WPF/Math 相对于相机定向 3D 模型

C#/WPF/Math Orienting a 3D model relative to the camera

我正在使用 WPF Viewport3d。视点来自一架不断改变位置和方向的飞机(称之为 AC1)。在此视口中,我需要绘制另一架也会改变位置和方向的飞机(称为 Model2)。我得到以下作为输入:

  1. AC1 的 Lat/Lon/Alt、Heading/Pitch/Roll
  2. 模型 2 的 Lat/Lon/Alt、Heading/Pitch/Roll 和 Azimuth/Elevation/Range 相对于 AC1

如果我没有 rotate/reposition 我的透视相机,定位 Model2 并不困难。相机朝 (0,0,-1) 方向看,向上是 (0,1,0)。通过该设置,我可以获得

double X = range * Math.Cos(ConvertDegreesToRadians(elevation)) * Math.Sin(ConvertDegreesToRadians(mSATAzimDeg));
double Y = range * Math.Sin(ConvertDegreesToRadians(elevation));
double Z = range * Math.Cos(ConvertDegreesToRadians(elevation)) * Math.Cos(ConvertDegreesToRadians(azimuth));

然后我可以使用 X/Y/Z 制作 TranslateTransform3D 并将模型移动到该位置。

我 运行 遇到的主要问题是定位模型。我已经尝试将 Lat/Lon/Alts 转换为 ECEF space,然后计算 space 中的方向,但这会弄乱位置和方向。我也试过旋转视点的轴,然后围绕这些新轴旋转 Model2,但这也不起作用。

有没有人有一个简单的算法来适当地定位 Model2?理想情况下,我们不会旋转相机,而是计算 Model2 应该如何相对于视点定向。如果我不想移动相机看起来很奇怪,那是因为 WPF Viewport3d 充当 OpenGL window 之上的叠加层,所以我真的只需要相对于 Model2 定位和定向WPF 视口,根本不需要移动视点(但如果这样更容易,我可以)。

希望这是有道理的。如果没有,我将尝试详细说明。感谢您提供的任何帮助。

所以我最终让它工作了,只是不是我想要的方式......在 xaml 我为相机设置了这个旋转

<Transform3DGroup x:Name="CameraTransformGroup">
  <RotateTransform3D>
    <RotateTransform3D.Rotation>
      <AxisAngleRotation3D Axis="0,0,1" Angle="{Binding AC1Roll, ElementName=UserControl}" />
    </RotateTransform3D.Rotation>
  </RotateTransform3D>
  <RotateTransform3D>
    <RotateTransform3D.Rotation>
      <AxisAngleRotation3D Axis="1,0,0" Angle="{Binding AC1Pitch, ElementName=UserControl}" />
     </RotateTransform3D.Rotation>
   </RotateTransform3D>
   <RotateTransform3D>
     <RotateTransform3D.Rotation>
       <AxisAngleRotation3D Axis="0,-1,0" Angle="{Binding AC1Heading, ElementName=UserControl}" />
     </RotateTransform3D.Rotation>
   </RotateTransform3D>
 </Transform3DGroup>

对于 Model2 我做了这个轮换

<Transform3DGroup>
  <RotateTransform3D>
    <RotateTransform3D.Rotation>
      <AxisAngleRotation3D Axis="0,0,-1" Angle="{Binding Roll, ElementName=UserControl, Converter={StaticResource RadToDegConverter}}" />
    </RotateTransform3D.Rotation>
  </RotateTransform3D>
  <RotateTransform3D>
    <RotateTransform3D.Rotation>
      <AxisAngleRotation3D Axis="1,0,0" Angle="{Binding Pitch, ElementName=UserControl, Converter={StaticResource RadToDegConverter}}" />
    </RotateTransform3D.Rotation>
  </RotateTransform3D>
  <RotateTransform3D>
    <RotateTransform3D.Rotation>
      <AxisAngleRotation3D Axis="0,-1,0" Angle="{Binding Heading, ElementName=UserControl, Converter={StaticResource RadToDegConverter}}" />
    </RotateTransform3D.Rotation>
  </RotateTransform3D>
  <TranslateTransform3D OffsetZ="{Binding RelativeOffsetZ, ElementName=UserControl}" 
                        OffsetX="{Binding RelativeOffsetX, ElementName=UserControl}" 
                        OffsetY="{Binding RelativeOffsetY, ElementName=UserControl}" />
</Transform3DGroup>

然后在后面的代码中RelativeOffsetX/Y/Z是由

计算出来的
double wXOffset = mRng * Math.Cos(mElevation * GeoConstants.DEG2RAD) * Math.Sin(mAzimuth * GeoConstants.DEG2RAD);
double wYOffset = mRng * Math.Sin(mElevation * GeoConstants.DEG2RAD);
double wZOffset = mRng * Math.Cos(mElevation * GeoConstants.DEG2RAD) * Math.Cos(mAzimuth * GeoConstants.DEG2RAD);

Matrix3D wCameraRotation = CameraTransformGroup.Value;

Vector3D wNewXyz = Vector3D.Multiply(new Vector3D(wXOffset, wYOffset, wZOffset, wCameraRotation);
this.RelativeOffsetX = wNewXyz.X;
this.RelativeOffsetY = wNewXyz.Y;
this.RelativeOffsetZ = wNewXyz.Z;

我没有想出如何不旋转相机,而是通过旋转相机和模型然后运行通过旋转矩阵CameraTransformGroup.Value和向量乘法计算出的点您可以计算相对于相机朝向的新偏移量,从而正确定位和定向 Model2。