Export (0) Print
Expand All
0 out of 1 rated this helpful - Rate this topic

UIElement3D Class

UIElement3D is a base class for WPF core level implementations building on Windows Presentation Foundation (WPF) elements and basic presentation characteristics.

Namespace:  System.Windows
Assembly:  PresentationCore (in PresentationCore.dll)
public abstract class UIElement3D : Visual3D, 
	IInputElement
This class is abstract; see Inheritance Hierarchy for derived non-abstract classes usable in XAML.

UIElement3D is an abstract base class from which you can derive classes to represent specific 3D elements.

Much of the input, focusing, and eventing behavior for 3D elements in general is defined in the UIElement3D class. This includes the events for keyboard, mouse, and stylus input, and related status properties. Many of these events are routed events, and many of the input-related events have both a bubbling routing version as well as a tunneling version of the event. These paired events are typically the events of greatest interest to control authors.

UIElement3D also includes APIs that relate to the WPF event model, including methods that can raise specified routed events that are sourced from an element instance.

A UIElement3D has the following capabilities that are specifically defined by the UIElement3D class:

  • Can respond to user input (including control of where input is sent via handling of event routing or routing of commands).

  • Can raise routed events that travel a route through the logical element tree.

Important noteImportant Note:

Visibility state affects all input handling by that element. Elements that are not visible do not participate in hit testing and do not receive input events, even if the mouse is over the bounds of where the element would be if were visible.

Unlike the UIElement class, the UIElement3D class does not include layout. Therefore, the UIElement3D class does not include Measure or Arrange methods.

A class that derives from UIElement3D and maintains its own collection of Visual3D objects by overriding GetVisual3DChild and Visual3DChildrenCount must still pass new Visual3D objects to AddVisual3DChild.

UIElement3D is introduced in the .NET Framework version 3.5. For more information, see .NET Framework 3.5 Architecture.

The following example shows how to derive from the UIElement3D class to create a Sphere class:

public class Sphere : UIElement3D
{
    // OnUpdateModel is called in response to InvalidateModel and provides 
    // a place to set the Visual3DModel property. 
    //  
    // Setting Visual3DModel does not provide parenting information, which 
    // is needed for data binding, styling, and other features. Similarly, creating render data 
    // in 2-D does not provide the connections either. 
    //  
    // To get around this, we create a Model dependency property which 
    // sets this value.  The Model DP then causes the correct connections to occur 
    // and the above features to work correctly. 
    //  
    // In this update model we retessellate the sphere based on the current 
    // dependency property values, and then set it as the model.  The brush 
    // color is blue by default, but the code can easily be updated to let 
    // this be set by the user. 

    protected override void OnUpdateModel()
    {
        GeometryModel3D model = new GeometryModel3D();

        model.Geometry = Tessellate(ThetaDiv, PhiDiv, Radius);
        model.Material = new DiffuseMaterial(System.Windows.Media.Brushes.Blue);

        Model = model;
    }

    // The Model property for the sphere 
    private static readonly DependencyProperty ModelProperty =
        DependencyProperty.Register("Model",
                                    typeof(Model3D),
                                    typeof(Sphere),
                                    new PropertyMetadata(ModelPropertyChanged));

    private static void ModelPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Sphere s = (Sphere)d;
        s.Visual3DModel = s.Model;
    }

    private Model3D Model
    {
        get
        {
            return (Model3D)GetValue(ModelProperty);
        }

        set
        {
            SetValue(ModelProperty, value);
        }
    }

    // The number of divisions to make in the theta direction on the sphere 
    public static readonly DependencyProperty ThetaDivProperty =
        DependencyProperty.Register("ThetaDiv",
                                    typeof(int),
                                    typeof(Sphere),
                                    new PropertyMetadata(15, ThetaDivPropertyChanged));

    private static void ThetaDivPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Sphere s = (Sphere)d;
        s.InvalidateModel();
    }

    public int ThetaDiv
    {
        get
        {
            return (int)GetValue(ThetaDivProperty);
        }

        set
        {
            SetValue(ThetaDivProperty, value);
        }
    }

    // The number of divisions to make in the phi direction on the sphere 
    public static readonly DependencyProperty PhiDivProperty =
        DependencyProperty.Register("PhiDiv",
                                    typeof(int),
                                    typeof(Sphere),
                                    new PropertyMetadata(15, PhiDivPropertyChanged));

    private static void PhiDivPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Sphere s = (Sphere)d;
        s.InvalidateModel();
    }

    public int PhiDiv
    {
        get
        {
            return (int)GetValue(PhiDivProperty);
        }

        set
        {
            SetValue(PhiDivProperty, value);
        }
    }

    // The radius of the sphere 
    public static readonly DependencyProperty RadiusProperty =
        DependencyProperty.Register("Radius",
                                    typeof(double),
                                    typeof(Sphere),
                                    new PropertyMetadata(1.0, RadiusPropertyChanged));

    private static void RadiusPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Sphere s = (Sphere)d;
        s.InvalidateModel();
    }

    public double Radius
    {
        get
        {
            return (double)GetValue(RadiusProperty);
        }

        set
        {
            SetValue(RadiusProperty, value);
        }
    }

    // Private helper methods 
    private static Point3D GetPosition(double theta, double phi, double radius)
    {
        double x = radius * Math.Sin(theta) * Math.Sin(phi);
        double y = radius * Math.Cos(phi);
        double z = radius * Math.Cos(theta) * Math.Sin(phi);

        return new Point3D(x, y, z);
    }

    private static Vector3D GetNormal(double theta, double phi)
    {
        return (Vector3D)GetPosition(theta, phi, 1.0);
    }

    private static double DegToRad(double degrees)
    {
        return (degrees / 180.0) * Math.PI;
    }

    private static System.Windows.Point GetTextureCoordinate(double theta, double phi)
    {
        System.Windows.Point p = new System.Windows.Point(theta / (2 * Math.PI),
                            phi / (Math.PI));

        return p;
    }

    // Tesselates the sphere and returns a MeshGeometry3D representing the  
    // tessellation based on the given parameters 
    internal static MeshGeometry3D Tessellate(int tDiv, int pDiv, double radius)
    {            
        double dt = DegToRad(360.0) / tDiv;
        double dp = DegToRad(180.0) / pDiv;

        MeshGeometry3D mesh = new MeshGeometry3D();

        for (int pi = 0; pi <= pDiv; pi++)
        {
            double phi = pi * dp;

            for (int ti = 0; ti <= tDiv; ti++)
            {
                // we want to start the mesh on the x axis 
                double theta = ti * dt;

                mesh.Positions.Add(GetPosition(theta, phi, radius));
                mesh.Normals.Add(GetNormal(theta, phi));
                mesh.TextureCoordinates.Add(GetTextureCoordinate(theta, phi));
            }
        }

        for (int pi = 0; pi < pDiv; pi++)
        {
            for (int ti = 0; ti < tDiv; ti++)
            {
                int x0 = ti;
                int x1 = (ti + 1);
                int y0 = pi * (tDiv + 1);
                int y1 = (pi + 1) * (tDiv + 1);

                mesh.TriangleIndices.Add(x0 + y0);
                mesh.TriangleIndices.Add(x0 + y1);
                mesh.TriangleIndices.Add(x1 + y0);

                mesh.TriangleIndices.Add(x1 + y0);
                mesh.TriangleIndices.Add(x0 + y1);
                mesh.TriangleIndices.Add(x1 + y1);
            }
        }

        mesh.Freeze();
        return mesh;
    }
}

For the complete sample, see UIElement3D Sphere Sample.

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

Windows 7, Windows Vista, Windows XP SP2, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003

The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

.NET Framework

Supported in: 3.5 SP1, 3.0 SP1
Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback

Community Additions

ADD
Show:
© 2014 Microsoft. All rights reserved.