Our first project
You're still here, good. Lets get some code done.
Before we start, the form designer in WPF is XML based, and as such follows all of the rules of XML. However the code behind works the same as in any application. When you see code in the XML format it is code for the designer, and when you see VB it is in the code behind.
Start a new WPF application project, and open the Window1 XAML object. Copy and paste this code in the editor. (between the Grid tags) This code contains everything needed in XML format to create and render four coloured cubes.
<Viewport3D Name="Viewport3D1" Margin="12,55,12,12">
<Viewport3D.Camera>
<PerspectiveCamera Position="-40,40,40" LookDirection="40,-40,-40 "
UpDirection="0,0,1" />
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<DirectionalLight Color="White" Direction="-10,-10,-10" />
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions="0,0,0 10,0,0 10,10,0 0,10,0 0,0,10 10,0,10 10,10,10 0,10,10"
TriangleIndices="0,1,3 1,2,3 0,4,3 4,7,3 4,6,7 4,5,6 0,4,1 1,4,5 1,2,6 6,5,1 2,3,7 7,6,2"/>
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial Brush="red" AmbientColor="Yellow" Color="Yellow" />
</GeometryModel3D.Material>
</GeometryModel3D>
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions="0,-10,-10 10,-10,-10 10,0,-10 0,0,-10 0,-10,0 10,-10,0 10,0,0 0,0,0"
TriangleIndices="0,1,3 1,2,3 0,4,3 4,7,3 4,6,7 4,5,6 0,4,1 1,4,5 1,2,6 6,5,1 2,3,7 7,6,2"/>
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial Brush="yellow" AmbientColor="Yellow" Color="Yellow" />
</GeometryModel3D.Material>
</GeometryModel3D>
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions="-10,-10,0 0,-10,0 0,0,0 -10,0,0 -10,-10,10 0,-10,10 0,0,10 -10,0,10"
TriangleIndices="0,1,3 1,2,3 0,4,3 4,7,3 4,6,7 4,5,6 0,4,1 1,4,5 1,2,6 6,5,1 2,3,7 7,6,2"/>
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial Brush="green" AmbientColor="white" Color="white" />
</GeometryModel3D.Material>
</GeometryModel3D>
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions="-10,0,-10 0,0,-10 0,10,-10 -10,10,-10 -10,0,0 0,0,0 0,10,0 -10,10,0"
TriangleIndices="0,1,3 1,2,3 0,4,3 4,7,3 4,6,7 4,5,6 0,4,1 1,4,5 1,2,6 6,5,1 2,3,7 7,6,2"/>
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial Brush="blue" AmbientColor="white" Color="white" />
</GeometryModel3D.Material>
</GeometryModel3D>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
Now compile and run the application. You should get a view like the one below. Now here's something to try while the application is running: resize the form and make note of how the objects react. The image should resize with the form.
[WPF1.jpg]
Figure 7: Compile and run the application
But what have we done. In simple terms, we have created a 3D viewing portal (the canvas) and placed a few Geometric models into it (the cubes). For each cube, we start off by listing each of the coordinates for all of the corners (8) in our cube, in X(0),Y(0),Z(0) X(1),Y(1),Z(1) etc,etc. Note: The list can be comma or space separated. Thereafter, we have to build each of our triangles from these points in sets of 3. As we are building a simple cube each face is built from two triangles. ie the first face is triangle 0,1,3 and 1,2,3 (Note: The list can be comma or space separated.) What is very important here is that the points are listed in a Clockwise direction, returning to our plane image.
[Plane.gif][Plane2.gif]
The points are listed in a Clockwise direction
In order for the skining of face ABC to be visible when looking at the object, on the plane MNOP the coordinates have to be listed in clockwise order A,B,C. If they are listed in reverse order, i.e., A,C,B the face will only be visible when viewing the pyramid from the back side, in which case the other faces will be rendered over it.
Great we got cubes! But this is boring, there's nothing happening. Before we get this object to move around, let's look a little closer at a few things. First we are going to look at the Viewports camera object.
In the above code there's this line :
PerspectiveCamera Position="-40,40,40" LookDirection="40,-40,-40 " UpDirection="0,0,1"
This code defines our views camera and the vector needed to place it.
The vector or position is a coordinate in the format of X,Y,Z and the direction ,also a coordinate, relative to the current camera position. So let's play with this a little and see what we can do. First we are going to add a slider to the project, place the slider control code below into the designer, just after the viewport, and add the VB code to the project.
<Slider Height="22" Margin="12,12,12,0" Name="Slider1" VerticalAlignment="Top" Minimum="-40" Maximum="40" SmallChange="1" />
Private X As Double = -40
Private newpcam As New Media3D.PerspectiveCamera()
Private Pos1 As New Media3D.Point3D(-40, 40, 40)
Private Dir1 As New Media3D.Point3D(40, -40, -40)
Private Sub Window1_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
Viewport3D1.Camera = newpcam
newpcam.Position = Pos1
newpcam.LookDirection = Dir1
End Sub
Private Sub SetX(ByVal X As Double)
Pos1.X = X
Dir1.X = -X
newpcam.Position = Pos1
newpcam.LookDirection = Dir1
End Sub
Private Sub Slider1_ValueChanged(ByVal sender As System.Object, ByVal e As System.Windows.RoutedPropertyChangedEventArgs(Of System.Double))
SetX(Slider1.Value)
End Sub
After adding the code, run the project again, and move the slider left and right. We now have a little animation action happening. Well, all we are really doing is moving the camera left and right in a straight line, while turning it to look at our cubes. A working project file is available in the download section, with a few additions.
Our Second Project
What we've done up to now has been relatively simple. Let's see how to animate the individual cubes. We are going to use the same XAML layout, but we are going to add to the VB code to accomplish this.
Copy and paste this code into our previous project.
Imports System.Windows.Media.Media3D
Imports System.Windows.Media.Animation
Private Sub Window1_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
Viewport3D1.Camera = newpcam
newpcam.Position = Pos1
newpcam.LookDirection = Dir1
Dim Cube_ani As New DoubleAnimation()
Cube_ani.Duration = TimeSpan.FromSeconds(3)
Cube_ani.From = 0
Cube_ani.To = 359
Cube_ani.RepeatBehavior = RepeatBehavior.Forever
Dim Cube_rot As New AxisAngleRotation3D()
Cube_rot.Axis = New Vector3D(0, 1, 0)
Viewport3D1.Children.Item(0).Transform = New RotateTransform3D(Cube_rot, 5, 5, 5)
Viewport3D1.Children.Item(1).Transform = New RotateTransform3D(Cube_rot, 5, -5, -5)
Viewport3D1.Children.Item(2).Transform = New RotateTransform3D(Cube_rot, -5, -5, 5)
Viewport3D1.Children.Item(3).Transform = New RotateTransform3D(Cube_rot, -5, 5, -5)
Cube_rot.BeginAnimation(AxisAngleRotation3D.AngleProperty, Cube_ani)
End Sub
When you run this project, you should see the four cubes rotating in place. Cool! Now we getting somewhere. What we've now done is created a animation storyboard, DoubleAnimation. Our storyboard will create a double typed variable according to the start(From), end(To) and time(Duration) values that we give it. In this case we looking for an angle that will cause our object to rotate a full 360 degrees, so we give it a Start and End value of 0 and 359.
Something interesting about the storyboard is you only have to tell it how long you want the animation to last, in this case we set it to three seconds, i.e., the storyboard will step from 0 to 359 in three seconds. It will calculate the steps between depending on the elapsed time from the first frame, giving a smooth constant rotation regardless on the performance of the system.
Next we define our animation type, AxisAngleRotation. Here we set the animation to rotate around the Y axis, with a factor of 1. You can set any combination of axis you want with any factor to produce any effect you like. Just remember that setting the axis to (0,0,0) will result in no rotation at all.
The next step is applying our Animation Type to the Object we want to animate. At this time we also have to assign the center of the object that the animation will use to rotate around. What we've used here are the exact middles of the cubes so that they will appear to be spinning much like a wheel. We can assign different centers for different objects or even the same for several objects.
Last on the list we start the animation and assign it a storyboard. The animation will now start and because we set the storyboard to repeat forever: for as long at the application is running the cubes will spin on their axis. We could also place triggers in the code to specifically start and stop the animation at any time, or set it to step through it a limited number of times.
The second project file is available in the download section, with a few additional tweeks.
Realtime 3D rendering in Visual Basic was limited to what you could do with massive amounts of API's and Cross referencing lookup tables pre built into memory to help speed up calculations and rendering times, but as you can see, WPF has made it exceptionally easy to apply full 3D functionality into any VB application with a minimal amount of effort.
In the next article we going to build a small 3D world and see if we can move around in it.
Till then Happy 3D coding...
Comments
There are no comments yet. Be the first to comment!