平面投影中的立方体。适合顶部

时间:2014-08-15 13:54:03

标签: wpf windows-phone-8 windows-runtime affinetransform viewport3d

我正忙于将WPF解决方案迁移到Windows应用商店应用。该解决方案使用了App中没有的ViewPort3D 开发所以我试图使用PlaneProjection转换它。

目标是实现一个可以使用故事板围绕一个轴旋转的立方体。我对立方体的两侧没有任何问题 但顶部的矩形让我很头疼。

我制作了一个测试集来可视化我的问题。如果您创建一个新的blanc Windows应用商店应用(不是电话)并将其命名为PlaneTest,那么将XAML粘贴到 您的整个MainPage.xaml并将C#类放在MainPage.xaml.cs

XAML:

<Page
    x:Class="PlaneTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PlaneTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="500"/>
            <ColumnDefinition Width="700"/>
        </Grid.ColumnDefinitions>   
        <Grid.Resources>
            <Style TargetType="Slider">
                <Setter Property="Width" Value="400"/>
                <Setter Property="Height" Value="23"/>
            </Style>
            <Style TargetType="TextBlock">
                <Setter Property="Margin" Value="0,5,0,0"/>
            </Style>
        </Grid.Resources>
        <StackPanel Orientation="Vertical" Width="450" Grid.Column="0">
            <TextBlock Text="CUBE SLIDERS" Margin="25"></TextBlock>
            <TextBlock Text="Rotation X = 23. CUBE ROTATES AROUND THIS AXIS."></TextBlock>
            <Slider Name="RotateX" Minimum="-90" Maximum="90" Value="23"></Slider>
            <TextBlock Text="Rotation Y = -25"></TextBlock>
            <Slider Name="RotateY" Minimum="-90" Maximum="90" Value="-25"></Slider>
            <TextBlock Text="Rotation Z = -90"></TextBlock>
            <Slider Name="RotateZ" Minimum="-90" Maximum="90" Value="-90"></Slider>

            <TextBlock Text="TOP RECTANGLE" Margin="25,50,0,0"></TextBlock>
            <TextBlock Text="Rotation X"></TextBlock>
            <Slider Name="TopRotateX" Minimum="-180" Maximum="180"></Slider>
            <TextBlock Text="Rotation Y"></TextBlock>
            <Slider Name="TopRotateY" Minimum="-180" Maximum="180"></Slider>
            <TextBlock Text="Rotation Z"></TextBlock>
            <Slider Name="TopRotateZ" Minimum="-180" Maximum="180"></Slider>

            <TextBlock Text="Center Of Rotation X" Margin="0,40,0,0"></TextBlock>
            <Slider Name="CenterOfXRotation" Value="0.5" Minimum="0" Maximum="1" StepFrequency="0.1"></Slider>
            <TextBlock Text="Center Of Rotation Y"></TextBlock>
            <Slider Name="CenterOfYRotation" Value="0.5" Minimum="0" Maximum="1" StepFrequency="0.1"></Slider>
            <TextBlock Text="Center Of Rotation Z"></TextBlock>
            <Slider Name="CenterOfZRotation" Value="200" Minimum="-200" Maximum="200"></Slider>

            <TextBlock Text="GlobalOffSet X" Margin="0,40,0,0"></TextBlock>
            <Slider Name="GlobalXOffSet"  Minimum="-200" Maximum="200" ></Slider>
            <TextBlock Text="GlobalOffSet Y"></TextBlock>
            <Slider Name="GlobalYOffSet" Width="400" Height="23" Minimum="-200" Maximum="200"></Slider>
            <TextBlock Text="GlobalOffSet Z"></TextBlock>
            <Slider Name="GlobalZOffSet" Minimum="-200" Maximum="200"></Slider>
         </StackPanel>     

        <Grid x:Name="LayoutRoot"  Grid.Column="1">
            <Grid.Resources>
                <Style TargetType="Rectangle">
                    <Setter Property="Height" Value="400"/>
                    <Setter Property="Width" Value="400"/>
                </Style>
                <local:RotationXOffset x:Key="rotationXOffset"/>
            </Grid.Resources>

            <Rectangle Fill="#a0FF0000" Name="Side1">
               <Rectangle.Projection>
                   <PlaneProjection CenterOfRotationZ="200" 
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='-90'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ,Path=Value}"/>
                    </Rectangle.Projection>
            </Rectangle>

            <Rectangle Fill="#a00000FF" Name="Side2">
                <Rectangle.Projection>
                    <PlaneProjection CenterOfRotationZ="200"
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='-0'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ, Path=Value}"/>
                </Rectangle.Projection>
            </Rectangle>

            <Rectangle Fill="#a0EFFF30" Name="Side3">
                <Rectangle.Projection>
                    <PlaneProjection CenterOfRotationZ="200"                          
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='90'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ, Path=Value}"/>
                </Rectangle.Projection>
            </Rectangle>

            <Rectangle Fill="#af00FF00" Name="Side4">
                <Rectangle.Projection>
                    <PlaneProjection CenterOfRotationZ="200"
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='180'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ, Path=Value}"/>
                </Rectangle.Projection>
            </Rectangle>

            <Rectangle Fill="Orange"  Name="Top">
                <Rectangle.Projection>
                    <PlaneProjection
                               CenterOfRotationX="{Binding ElementName=CenterOfXRotation, Path=Value}"
                               CenterOfRotationY="{Binding ElementName=CenterOfYRotation, Path=Value}"
                               CenterOfRotationZ="{Binding ElementName=CenterOfZRotation, Path=Value}"
                               GlobalOffsetX="{Binding ElementName=GlobalXOffSet, Path=Value}"
                               GlobalOffsetY="{Binding ElementName=GlobalYOffSet, Path=Value}"
                               GlobalOffsetZ="{Binding ElementName=GlobalZOffSet, Path=Value}"
                               RotationX="{Binding ElementName=TopRotateX, Path=Value}" 
                               RotationY="{Binding ElementName=TopRotateY, Path=Value}" 
                               RotationZ="{Binding ElementName=TopRotateZ, Path=Value}" />
                </Rectangle.Projection>
            </Rectangle>
        </Grid>  
    </Grid>
</Page>

C#

 class RotationXOffset : IValueConverter
    {
        object IValueConverter.Convert(object value, Type targetType, object parameter, string language)
        {
            return (double)value + Convert.ToDouble(parameter);
        }

        object IValueConverter.ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }

如果您没有触及3个顶部滑块,请尝试使用其他滑块将橙色顶部矩形放在立方体顶部。 我不能。

当我将旋转X最顶部滑块移动到0或90时,我可以适合顶部,但不能与任何其他值一起移动。 我究竟做错了什么?甚至可以使用PlaneProjection吗? 我是否遇到了仿射转换限制? http://www.charlespetzold.com/blog/2009/01/Non-Affine-Transforms-in-Silverlight.html

1 个答案:

答案 0 :(得分:0)

与此同时,我正在研究另一个项目,现在回到这个解决方案,我又看了一遍。

使用这个XAML和问题的值转换器,它可以正常工作。

<Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="500"/>
            <ColumnDefinition Width="700"/>
        </Grid.ColumnDefinitions>   
        <Grid.Resources>
            <Style TargetType="Slider">
                <Setter Property="Width" Value="400"/>
                <Setter Property="Height" Value="23"/>
            </Style>
            <Style TargetType="TextBlock">
                <Setter Property="Margin" Value="0,5,0,0"/>
            </Style>
        </Grid.Resources>
        <StackPanel Orientation="Vertical" Width="450" Grid.Column="0">
            <TextBlock Text="CUBE SLIDERS" Margin="25"></TextBlock>
            <TextBlock Text="Rotation X = 23. CUBE ROTATES AROUND THIS AXIS."></TextBlock>
            <Slider Name="RotateX" Minimum="-90" Maximum="90" Value="23"></Slider>
            <TextBlock Text="Rotation Y = -25"></TextBlock>
            <Slider Name="RotateY" Minimum="-90" Maximum="90" Value="-25"></Slider>
            <TextBlock Text="Rotation Z = -90"></TextBlock>
            <Slider Name="RotateZ" Minimum="-90" Maximum="90" Value="-90"></Slider>
        </StackPanel>     

        <Grid x:Name="LayoutRoot"  Grid.Column="1">
            <Grid.Resources>
                <Style TargetType="Rectangle">
                    <Setter Property="Height" Value="400"/>
                    <Setter Property="Width" Value="400"/>
                </Style>
                <local:RotationXOffset x:Key="rotationXOffset"/>
            </Grid.Resources>

            <Rectangle Fill="#a0FF0000" Name="Side1">
               <Rectangle.Projection>
                   <PlaneProjection CenterOfRotationZ="200" 
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='-90'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ,Path=Value}"/>
                    </Rectangle.Projection>
            </Rectangle>

            <Rectangle Fill="#a00000FF" Name="Side2">
                <Rectangle.Projection>
                    <PlaneProjection CenterOfRotationZ="200"
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='-0'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ, Path=Value}"/>
                </Rectangle.Projection>
            </Rectangle>

            <Rectangle Fill="#a0EFFF30" Name="Side3">
                <Rectangle.Projection>
                    <PlaneProjection CenterOfRotationZ="200"                          
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='90'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ, Path=Value}"/>
                </Rectangle.Projection>
            </Rectangle>

            <Rectangle Fill="#af00FF00" Name="Side4">
                <Rectangle.Projection>
                    <PlaneProjection CenterOfRotationZ="200"
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='180'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ, Path=Value}"/>
                </Rectangle.Projection>
            </Rectangle>

        </Grid>  
        <Grid Grid.Column="1">
            <Grid.Projection>
                <PlaneProjection RotationX="115" CenterOfRotationZ="200"/>
            </Grid.Projection>
            <Rectangle Fill="Orange"  Name="Top" Height="400" Width="400" >
                <Rectangle.Projection>
                    <PlaneProjection RotationZ="{Binding ElementName=RotateX, Path=Value}"/>
                </Rectangle.Projection>
            </Rectangle>
        </Grid>
    </Grid>