Click here to Skip to main content
15,868,016 members
Articles / Programming Languages / C#

All New .NET 3.5 3D Elements

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
17 Jun 2009CPOL 16.5K   146   10  
All new .NET 3.5 3D elements

I have started looking at 3D again in WPF. I have in the past blogged about the Viewport2DVisual3D 3D WPF element. Well for what I am working on, I didn’t need to be able to put 2D interactive elements on a 3D surface, but I did want the 3D object to able to respond to Mouse events.  Now in the past, what you would have done is use a MouseDown event on the Viewport3D and do some sort of hit testing. Which was ok….

But now, there is the wonderful new .NET 3.5 element ModelUIElement3D which is a fully fledged element that supports events. Hooray!

And there is also a new container element to host 1 or more ModelUIElement3D elements.

Let's see an example:

XML
<Window x:Class="Shapes.Window1″
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Shapes"
    Title="Window1″ Height="610.122″ Width="633.46″>

    <Window.Resources>

        <!– The 3D cube –>
        <MeshGeometry3D x:Key="CubeMesh"
            TriangleIndices = "0,1,2     2,3,0
                               4,7,6     6,5,4
                               8,11,10   10,9,8
                               12,13,14  14,15,12
                               16,17,18  18,19,16
                               20,23,22  22,21,20″

             Positions      = "-1,-1,1   -1,-1,-1  1,-1,-1  1,-1,1
                               -1,1,1    -1,1,-1   1,1,-1   1,1,1
                               -1,-1,1   -1,1,1    1,1,1    1,-1,1
                               -1,-1,-1  -1,1,-1   1,1,-1   1,-1,-1
                               -1,-1,1   -1,1,1   -1,1,-1  -1,-1,-1
                                1,-1,1    1,1,1    1,1,-1   1,-1,-1″ />
    </Window.Resources>

    <Viewport3D>

        <Viewport3D.Camera>
            <PerspectiveCamera x:Name="camera" Position="-2,2,5″
                               LookDirection="2,-2,-5″ FieldOfView="90″ />
        </Viewport3D.Camera>

        <!– Container for 3D Elements –>
        <ContainerUIElement3D x:Name="container">
            <ContainerUIElement3D.Transform>
                <RotateTransform3D>
                    <RotateTransform3D.Rotation>
                        <AxisAngleRotation3D Axis="0, 1, 0″ Angle="0″ />
                    </RotateTransform3D.Rotation>
                </RotateTransform3D>
            </ContainerUIElement3D.Transform>

            <!– A fully Fledged 3d element complete with routed events >
            <ModelUIElement3D MouseDown="Cube1_MouseDown">
                <ModelUIElement3D.Transform>
                    <Transform3DGroup>
                        <TranslateTransform3D OffsetZ="1.5″ />
                        <RotateTransform3D>
                            <RotateTransform3D.Rotation>
                                <AxisAngleRotation3D Axis="0, 1, 0″ Angle="0″ />
                            </RotateTransform3D.Rotation>
                        </RotateTransform3D>
                    </Transform3DGroup>
                </ModelUIElement3D.Transform>
                <ModelUIElement3D.Model>
                    <GeometryModel3D Geometry="{StaticResource CubeMesh}">
                        <GeometryModel3D.Material>
                            <DiffuseMaterial x:Name="cube1Material" Brush="Blue" />
                        </GeometryModel3D.Material>
                    </GeometryModel3D>
                </ModelUIElement3D.Model>
            </ModelUIElement3D>
        </ContainerUIElement3D>

        <ModelVisual3D>
            <ModelVisual3D.Content>
                <DirectionalLight Color="White" Direction="-1,-1,-1″/>
            </ModelVisual3D.Content>
        </ModelVisual3D>

    </Viewport3D>

</Window>

And here is the C# code that has the event for the ModelUIElement3D.

C#
 1:  using System;
 2:  using System.Collections.Generic;
 3:  using System.Linq;
 4:  using System.Text;
 5:  using System.Windows;
 6:  using System.Windows.Controls;
 7:  using System.Windows.Data;
 8:  using System.Windows.Documents;
 9:  using System.Windows.Input;
10:  using System.Windows.Media;
11:  using System.Windows.Media.Animation;
12:  using System.Windows.Media.Media3D;
13:  using System.Windows.Media.Imaging;
14:  using System.Windows.Navigation;
15:  using System.Windows.Shapes;
16:
17:  namespace Shapes
18:  {
19:      /// <summary>
20:      /// Interaction logic for Window1.xaml
21:      /// </summary>
22:      public partial class Window1 : Window
23:      {
24:
25:
26:          public Window1()
27:          {
28:              InitializeComponent();
29:          }
30:
31:
32:          /// <summary>
33:          /// 3d Element Mouse Event, Neat
34:          /// </summary>
35:          private void Cube1_MouseDown(object sender, MouseButtonEventArgs e)
36:          {
37:              ModelUIElement3D currentObject = sender as ModelUIElement3D;
38:              if (currentObject.Transform is Transform3DGroup)
39:              {
40:                  RotateTransform3D rotateTrans = null;
41:
42:                  Transform3DGroup transGroup =
43:                      currentObject.Transform as Transform3DGroup;
44:                  rotateTrans = TryFindChild<RotateTransform3D>(transGroup);
45:                  if (rotateTrans != null)
46:                  {
47:                      // spin the object around
48:                      DoubleAnimation doubleAnimation =
49:                          new DoubleAnimation(0,360,
50:                          new Duration(TimeSpan.FromSeconds(0.5)));
51:                      rotateTrans.Rotation.BeginAnimation(
52:                          AxisAngleRotation3D.AngleProperty, doubleAnimation);
53:                  }
54:              }
55:          }
56:
57:
58:          /// <summary>
59:          /// Try and find child of type T in the Transform3DGroup
60:          /// </summary>
61:          public static T TryFindChild<T>(Transform3DGroup parent)
62:            where T : DependencyObject
63:          {
64:              foreach (DependencyObject child in parent.Children)
65:              {
66:                  if (child is T)
67:                  {
68:                      return child as T;
69:                  }
70:              }
71:              return null;
72:          }
73:
74:
75:      }
76:  }

And that is all there is to it. So in this example, if the cube gets a MouseDown, I lookup its RotateTransform3D and spin it around by 360 degrees.

37354/image-thumb6.png

And here is a zip file with the demo project code.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)

- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence

Both of these at Sussex University UK.

Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2016
  • Codeproject MVP 2016
  • Microsoft C# MVP 2015
  • Codeproject MVP 2015
  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Comments and Discussions

 
-- There are no messages in this forum --