Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Making 3D Application with WPF

0.00/5 (No votes)
19 Oct 2009 4  
WPF_3D_Application

Introduction

This is a very simple 3D app, which is written in WPF. This is fully 3D application which also has zooming control on mouse wheel, and manual horizontal rotation on keyboard arrows.
The reason why I published this article is to show other people and developers the possibilities of the WPF framework!

Background

Possibilities of this app are unlimited. The only question is "Can your hardware take that?!"

Using the Code

This app is entirely straightforward. From the developers point of view, it has a few textboxes, buttons, one MediaElement (for those who have not worked with WPF, MediaElement is a control which can be used for media files playing), listview... as I already said, pretty straightforward, but this app has a few exceptions in regard to normal desktop application. For those who have done work with 3D programming, most of this would be familiar.

I mentioned 3D programming because this app was made in that way. Here, I have ViewPort3D control, Camera control, Lights control and 3D Model without which all of this wouldn't make any sense! Let's see how all of this looks like in XAML code (I show how this looks like in XAML because it's much easier to make a 3D scene from here):

<Grid>
   <Viewport3D x:Name="view" ClipToBounds="False" RenderOptions.EdgeMode="Aliased">
   <!--3D Scene-->
   <Viewport3D.Camera>
       <PerspectiveCamera x:Name="camera" FieldOfView="59" 
		Position="0.5,0.5,2" LookDirection="0,0,-1">
           <PerspectiveCamera.Transform>
               <RotateTransform3D x:Name="rot" CenterY="0.5" CenterX="0.5" CenterZ="-0.5">
                   <RotateTransform3D.Rotation>
                       <!-- rotation -->
                       <AxisAngleRotation3D x:Name="camRotation" Axis="0,1,0" Angle="0"/>
                   </RotateTransform3D.Rotation>
               </RotateTransform3D>
           </PerspectiveCamera.Transform>
       </PerspectiveCamera>    
   </Viewport3D.Camera>
   <!--Light-->
   <ModelVisual3D>
       <ModelVisual3D.Content>
           <AmbientLight Color="White" />
       </ModelVisual3D.Content>
   </ModelVisual3D>
</Grid>

This was a simple example of how you can make a 3D scene in WPF and XAML. Now when we have our 3D scene, we need to make a 3D model which needs to be rendered. Many of you now think, that can't be easy, but it is!

The only thing that you need for this is your brain and a little math, but also you can use some extern softwares to make more complicated 3D models. (3D Studio Max, Blender, Maya....)

Before I proceed, I want to say for those who can and want to make 3D Models, that Blender is a great tool for 3D animations, and can also export models directly to XAML, but also in *.x, and many others extensions. Also, what is most important is that it's FREE ;)

Blender can be downloaded from here.

Let's now look at how we can make one side of the cube and add something to it:

<!-- cube front side -->
        <!--
        This is element which get controls and put them in 3D
        (make all scaling and transforming cordinates for you that looks like it is in 3D)
        -->
        <Viewport2DVisual3D Material="{StaticResource CubeSideMaterial}">
            <!--this is part where all drawing are done for this part-->
            <Viewport2DVisual3D.Geometry>
                <!--
                meshgeometry3d give you possibility to put bunch of points 
	       and to locate them in 3D and to connect them in what way 
	       you like (for connecting points we use 
                TriangleIndices-because all 3d graphic rendering are done with triangles)
                -->
                <MeshGeometry3D Positions="0,1,0 0,0,0 1,0,0 1,1,0"
                                TextureCoordinates="0,0 0,1 1,1 1,0"
                                TriangleIndices="0 1 2  0 2 3"/>
            </Viewport2DVisual3D.Geometry>
            <!--
            when we are finished our drawing we can put everything what we want in our
            Viewport2DVisual3D control,and it will be rendered like normal desktop app
            -->
            <Grid x:Name="FrontPanel" Background="
            	{StaticResource BlackBackground}" ShowGridLines="False" 
            	IsHitTestVisible="True" Margin="0">
                <Grid.BitmapEffect>
                    <OuterGlowBitmapEffect GlowSize="2" />
                </Grid.BitmapEffect>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition Height="15"/>
                    <RowDefinition Height="15" MaxHeight="15" />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <Button Style="{DynamicResource SimpleButton}" 
                	Grid.Row="3" Grid.Column="0" 
                	Grid.ColumnSpan="2" Content="Ok" 
                	Foreground="White" Click="Button_Click" 
                	FlowDirection="LeftToRight" FontSize="3" 
                	VerticalContentAlignment="Top"
                        Width="40"
                        Height="5"
                        Margin="0,2,0,2"
                        />
                <TextBox Grid.Row="1" Grid.Column="1" 
                	Height="5" Width="45" Margin="1,1,2,1" 
                	x:Name="textBox1" BorderThickness="0" 
                	ClipToBounds="False" FontSize="3.5" 
                	Padding="0,0.3,0,0"/>
                <PasswordBox Grid.Row="2" Grid.Column="1" 
                	Height="5" Width="45" 
                	Margin="1,-9.5,2,1" x:Name="passwordBox1" 
                	VerticalAlignment="Center" BorderThickness="0" 
                	Padding="0,0.3,0,0" FontSize="3.5" />
                <Label Grid.Row="1" Grid.Column="0" 
                	x:Name="label1" Foreground="White" 
                	FontSize="4" HorizontalAlignment="Left" 
                	MinWidth="0" Padding="3,5,3,3" 
                	Content="Username:"/>
                <Label Grid.Row="2" Grid.Column="0" 
                	FontSize="4" Foreground="White" 
                	x:Name="label2" Margin="0,-3,0,0" 
                	Padding="3" Content="Password:"/>
                <Label FontSize="5" Foreground="White" 
                	Grid.Row="0" Grid.Column="0" 
                	Grid.ColumnSpan="2" x:Name="label3" 
                	FontStyle="Oblique" FontWeight="Bold" Content="LogIn"/> 
            </Grid>
        </Viewport2DVisual3D> 

Here we can see how 3D Mesh can be made. This is a very simple mesh and it has only four points, but it is also a good example. One important thing about TriangleIndices is that connection of points in one triangle must be in counterclockwise direction, and that triangles need to face each other like this:

Positions="0,1,0 0,0,0 1,0,0 1,1,0"
TriangleIndices="0 1 2  0 2 3" 

But you can experiment with that and you will see what happens! ;)

One more thing that I will say is about the media player, and media seeking position. The reason why I mention this is because I had problems with setting this up before I found some article which helped me to solve this. To do media seeking, I put a slider control which is a normal thing :) But when you look at things a little closer and think that the slider will be updated on some time interval, and that on every update will be run slider ValueChanged_Event, you can't make media seeking with slider ValueChanged_Event and you don't make media glitches while playing!

But one interesting thing in WPF is that you can make Events for every part of the control, and that's where it was found that you can make an event handler for slider thumb dragging only (but one important thing is that you need to distinguish Drag and Drop Event Handlers from Thumb Dragging Event).

//slider control and thumb drag event
<Slider x:Name="PositionSlider" Thumb.DragCompleted="PositionSlider_DragCompleted" 
	Style="{DynamicResource SimpleSlider}" />
//and this is code behind
 private void PositionSlider_DragCompleted
	(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
 {
        mediaPlayer.Position = TimeSpan.FromMilliseconds(PositionSlider.Value);
 }

That's all what I did think that is important. If you have additional questions, post a message!

Thanks, Crashandburn.

Points of Interest

I just want to add a few words here about how this is a great and useful thing... just think about how it would be if someone makes a 3D operating system, or how you can make big business applications in a single window?!!!

Running Tutorial

For those who only want to run this app, they will need .NET 3.0 Framework, which you can download here and, I think but I'm not sure - Windows Media Player 10 or later!

Executable is located in \bin\Debug directory, and the login information is:

  • Username: crash
  • Password: burn

History

  • 20th October, 2009: Initial post

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here