WPF 透视相机的UpDirection(向上方向)

透视相机的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();
        }
    }
}

 

 看看效果

 

posted @ 2020-03-08 10:44  ARM830  阅读(955)  评论(0编辑  收藏  举报