透视相机的updirection,是具有三个参数的的属性(X,Y,Z),不过Z属性是没有作用的。
那么X,Y是什么呢?
是用来确定角度的。
注意H边,
我们知道单位圆上的一点都是可以用XY表示,用Y/X,即tan函数就可以求出圆心角的弧度,然后转角度就可以了。
比如说UpDirection我们设置为 1 1 0,Y/X=1,tan等于1弧度,等于57.29度。
但是这么做只能先设置计算好XY的比值才能确定角度,不方便。
********************************************************************************************
所以我们使用极坐标,这样我们就可以先设置角度又程序计算XY的值。
所谓极坐标即直角坐标系内使用角度和长度作为表示方式,比如 直角坐标系内的某点是(x,y)在极坐标内就是(p,θ)注意这里面的θ是弧度。p是长度。
程序的UpDirection是用直角坐标系,所以我们给定好角度和长度后需要从极坐标转到直角坐标系,使得我们的角度换算成直角坐标系内的表达方式,好在是,我们使用单位圆的默认长度即可也就是1;
极坐标换算直角坐标系方式为
x=p*cosθ
y=p*sinθ;
直角坐标系换算极坐标
p=根号下X的平凡+Y的平方
θ=Arctan(Y/X);
假设,XY坐标系内画一个直径为1的圆(圆心[0,0])
确定好圆上的点连接圆心之后和Y轴之间的夹角之后再用反三角函数求出角度即可
比如说我用tan函数
当确定X,Y值后,点连接圆心,长度为1,圆心角的对边长度为X坐标,斜边长度为1(不知道为什么直接写1不好使,必须用勾股定理求一下斜边),之后再Arctan函数转角度就好了。
上代码:
<Window.Resources>
<local:AngleConverter x:Key="Angle"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Viewport3D>
<Viewport3D.Camera>
<PerspectiveCamera LookDirection="0 0 -1"
FieldOfView="90"
UpDirection="{Binding ElementName=AngleSlider, Path=Value, Converter={StaticResource Angle}, Mode=TwoWay}"
Position="0 0 400"/>
</Viewport3D.Camera>
<Viewport2DVisual3D>
<Viewport2DVisual3D.Material>
<DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True"/>
</Viewport2DVisual3D.Material>
<Viewport2DVisual3D.Geometry>
<MeshGeometry3D>
<MeshGeometry3D.Positions>
-100 100 0,
-100 -100 0,
100 -100 0,
100 100 0
</MeshGeometry3D.Positions>
<MeshGeometry3D.TextureCoordinates>
0 0,
0 1,
1 1,
1 0
</MeshGeometry3D.TextureCoordinates>
<MeshGeometry3D.TriangleIndices>
0 ,1 ,2 ,0 ,2 ,3
</MeshGeometry3D.TriangleIndices>
</MeshGeometry3D>
</Viewport2DVisual3D.Geometry>
<Viewport2DVisual3D.Visual>
<Button Content="旋转" Height="150" Width="150"/>
</Viewport2DVisual3D.Visual>
</Viewport2DVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="White"/>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
<StackPanel Grid.Row="1">
<Slider Minimum="-360" Maximum="360" Value="0" x:Name="AngleSlider"/>
<TextBlock Text="{Binding ElementName=AngleSlider, Path=Value, Mode=OneWay}" />
</StackPanel>
</Grid>
后台
namespace 向上镜头
{
class AngleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double angle , x,y;
//转换为弧度
angle = Math.PI / 180*System.Convert.ToDouble(value);
//极坐标转为直角坐标系
x = Math.Cos(angle);
y = Math.Sin(angle);
return new Vector3D(x, y, 0);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var point = (Vector3D)value;
return Math.Atan2(point.X, point.Y) / Math.PI * 180;
}
}
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
看看效果