Welcome to Pete Brown's 10rem.net

First time here? If you are a developer or are interested in Microsoft tools and technology, please consider subscribing to the latest posts.

You may also be interested in my blog archives, the articles section, or some of my lab projects such as the C64 emulator written in Silverlight.

(hide this)

Silverlight 3 – Perspective 3d Transforms – PlaneProjection

Pete Brown - 18 March 2009

One of the most commonly requested features for Silverlight is some sort of 3d support. Within that, what many folks have expressed real interest in is the ability to do a perspective / non-affine transform of objects in space. Well, the Silverlight team delivered on that one for sure. Not only do we have the perspective transform (which could have been accomplished using shaders or the new bitmap API) but the controls in 3d space are still active and usable. Sweet!

Anyone who has messed with “real” 3d can tell you that just the setup required to get something usable can be a bit much. The perspective transform couldn’t be simpler, though. Here’s a simple form, with buttons, and some sliders for manipulating how the object floats in space. The three sliders control X, Y and Z rotation. You could use an image or any other element, but I wanted to show that controls are still live in 3d space.

What makes this possible is the new Projection attribute:

<Border.Projection>
    <PlaneProjection x:Name="Projection"
                     CenterOfRotationX="0.5"
                     CenterOfRotationY="0.5"
                     CenterOfRotationZ="0.5" />
</Border.Projection>

Projection lets you define the center of rotation, global/local offsets and of course the rotation angles

No transform

image

Example X, Y, Z rotation

image

Reversed rotation

image

Look, I can still type in the field

image

Since I used the new Element to Element binding, there’s zero code in this demo; it’s all in the xaml. Here’s the xaml you can paste into your own control. Note I’m using three new features of Silverlight 3:

  • Element to Element binding
  • Based-On Styles
  • Perspective Transform (Projection)
<Grid x:Name="LayoutRoot">
    <Grid.Background>
        <LinearGradientBrush StartPoint="0,0"
                             EndPoint="0,1">
            <GradientStop Offset="0.0"
                          Color="Black" />
            <GradientStop Offset="0.55"
                          Color="#FF001133" />
            <GradientStop Offset="0.58"
                          Color="#FF000000" />
            <GradientStop Offset="1.0"
                          Color="#FF050505" />
        </LinearGradientBrush>
    </Grid.Background>
    
    <Border CornerRadius="5"
            BorderBrush="DarkGray"
            BorderThickness="2"
            Background="White"
            HorizontalAlignment="Center"
            VerticalAlignment="Center">


        <Grid Margin="10">
            <Grid.Resources>
                <Style x:Key="ElementInGrid"
                       TargetType="FrameworkElement">
                    <Setter Property="VerticalAlignment"
                            Value="Center" />
                    <Setter Property="HorizontalAlignment"
                            Value="Stretch" />
                    <Setter Property="Margin"
                            Value="2 2 2 2" />
                </Style>

                <Style x:Key="FieldLabelStyle"
                       TargetType="TextBlock"
                       BasedOn="{StaticResource ElementInGrid}">
                    <Setter Property="TextAlignment"
                            Value="Right" />
                    <Setter Property="Margin"
                            Value="2 2 8 2" />
                </Style>
            </Grid.Resources>

            
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="80" />
                <ColumnDefinition Width="200" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="28" />
                <RowDefinition Height="28" />
                <RowDefinition Height="28" />
                <RowDefinition Height="38" />
            </Grid.RowDefinitions>

            <TextBlock Grid.Row="0"
                       Grid.Column="0"
                       Style="{StaticResource FieldLabelStyle}"
                       Text="First Name" />
            <TextBox Grid.Row="0"
                     Grid.Column="1"
                     Style="{StaticResource ElementInGrid}"
                     Text="Pete" />

            <TextBlock Grid.Row="1"
                       Grid.Column="0"
                       Style="{StaticResource FieldLabelStyle}"
                       Text="Last Name" />
            <TextBox Grid.Row="1"
                     Grid.Column="1"
                     Style="{StaticResource ElementInGrid}"
                     Text="Brown" />

            <TextBlock Grid.Row="2"
                       Grid.Column="0"
                       Style="{StaticResource FieldLabelStyle}"
                       Text="Url" />
            <TextBox Grid.Row="2"
                     Grid.Column="1"
                     Style="{StaticResource ElementInGrid}"
                     Text="http://www.irritatedVowel.com/Blog" />

            <Button Grid.Row="3"
                    Grid.Column="1"
                    Margin="5"
                    Style="{StaticResource ElementInGrid}"
                    Content="Save" />
        </Grid>


        <!-- this is the new projection attribute -->
        <Border.Projection>
            <PlaneProjection x:Name="Projection"
                             CenterOfRotationX="0.5"
                             CenterOfRotationY="0.5"
                             CenterOfRotationZ="0.5" />
        </Border.Projection>
    </Border>

    <!-- Knobs for changing the X/Y/Z rotation. note the use
    of element binding here to eliminate code from this sample -->
    <StackPanel Width="150">
        <Slider x:Name="XSlider"
                Minimum="-360"
                Maximum="360"
                Margin="5"
                Value="{Binding RotationX, Mode=TwoWay, ElementName=Projection}"
                SmallChange="1" />
        <Slider x:Name="YSlider"
                Minimum="-360"
                Maximum="360"
                Margin="5"
                Value="{Binding RotationY, Mode=TwoWay, ElementName=Projection}"
                SmallChange="1" />
        <Slider x:Name="ZSlider"
                Minimum="-360"
                Maximum="360"
                Margin="5"
                Value="{Binding RotationZ, Mode=TwoWay, ElementName=Projection}"
                SmallChange="1" />
    </StackPanel>

</Grid>

 

 

 

That’s all there is to it :)

     
posted by Pete Brown on Wednesday, March 18, 2009
filed under:      

6 comments for “Silverlight 3 – Perspective 3d Transforms – PlaneProjection”

  1. Pete Brownsays:
    @Martin, sorry, I really need to fix this template so that doesn't happen. If you copy the text it will all come through:

    Value="{Binding RotationX, Mode=TwoWay, ElementName=Projection}"

    @G I haven't seen any announcements about a full 3d stack. truthfully, 95% of the people who will actually do something with 3d will be well served by the projection, the other 5% will need to look at add-on libraries for now.

    @thomas good question! I'll ask around

Comment on this Post

Remember me

7 trackbacks for “Silverlight 3 – Perspective 3d Transforms – PlaneProjection”

  1. DotNetShoutoutsays:
    Thank you for submitting this cool story - Trackback from DotNetShoutout
  2. VBandi's blogsays:
    In early May, I gave a talk about the new features in Silverlight 3. As I’ve started to gather material