UIElement3D.OnUpdateModel 메서드

정의

파생 클래스에서 재정의된 경우 렌더링 작업에 참여합니다.

protected:
 virtual void OnUpdateModel();
protected virtual void OnUpdateModel ();
abstract member OnUpdateModel : unit -> unit
override this.OnUpdateModel : unit -> unit
Protected Overridable Sub OnUpdateModel ()

예제

다음 예제에서는 클래스에서 파생하여 클래스를 UIElement3D 만드는 방법을 보여줍니다.Sphere

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;
    }
}
Public Class Sphere
    Inherits 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 Overrides Sub OnUpdateModel()
        Dim model As New GeometryModel3D()

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

        Me.Model = model
    End Sub

    ' The Model property for the sphere
    Private Shared ReadOnly ModelProperty As DependencyProperty = DependencyProperty.Register("Model", GetType(Model3D), GetType(Sphere), New PropertyMetadata(AddressOf ModelPropertyChanged))

    Private Shared Sub ModelPropertyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        Dim s As Sphere = CType(d, Sphere)
        s.Visual3DModel = s.Model
    End Sub

    Private Property Model() As Model3D
        Get
            Return CType(GetValue(ModelProperty), Model3D)
        End Get

        Set(ByVal value As Model3D)
            SetValue(ModelProperty, value)
        End Set
    End Property

    ' The number of divisions to make in the theta direction on the sphere
    Public Shared ReadOnly ThetaDivProperty As DependencyProperty = DependencyProperty.Register("ThetaDiv", GetType(Integer), GetType(Sphere), New PropertyMetadata(15, AddressOf ThetaDivPropertyChanged))

    Private Shared Sub ThetaDivPropertyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        Dim s As Sphere = CType(d, Sphere)
        s.InvalidateModel()
    End Sub

    Public Property ThetaDiv() As Integer
        Get
            Return CInt(GetValue(ThetaDivProperty))
        End Get

        Set(ByVal value As Integer)
            SetValue(ThetaDivProperty, value)
        End Set
    End Property

    ' The number of divisions to make in the phi direction on the sphere
    Public Shared ReadOnly PhiDivProperty As DependencyProperty = DependencyProperty.Register("PhiDiv", GetType(Integer), GetType(Sphere), New PropertyMetadata(15, AddressOf PhiDivPropertyChanged))

    Private Shared Sub PhiDivPropertyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        Dim s As Sphere = CType(d, Sphere)
        s.InvalidateModel()
    End Sub

    Public Property PhiDiv() As Integer
        Get
            Return CInt(GetValue(PhiDivProperty))
        End Get

        Set(ByVal value As Integer)
            SetValue(PhiDivProperty, value)
        End Set
    End Property

    ' The radius of the sphere
    Public Shared ReadOnly RadiusProperty As DependencyProperty = DependencyProperty.Register("Radius", GetType(Double), GetType(Sphere), New PropertyMetadata(1.0, AddressOf RadiusPropertyChanged))

    Private Shared Sub RadiusPropertyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        Dim s As Sphere = CType(d, Sphere)
        s.InvalidateModel()
    End Sub

    Public Property Radius() As Double
        Get
            Return CDbl(GetValue(RadiusProperty))
        End Get

        Set(ByVal value As Double)
            SetValue(RadiusProperty, value)
        End Set
    End Property

    ' Private helper methods
    Private Shared Function GetPosition(ByVal theta As Double, ByVal phi As Double, ByVal radius As Double) As Point3D
        Dim x As Double = radius * Math.Sin(theta) * Math.Sin(phi)
        Dim y As Double = radius * Math.Cos(phi)
        Dim z As Double = radius * Math.Cos(theta) * Math.Sin(phi)

        Return New Point3D(x, y, z)
    End Function

    Private Shared Function GetNormal(ByVal theta As Double, ByVal phi As Double) As Vector3D
        Return CType(GetPosition(theta, phi, 1.0), Vector3D)
    End Function

    Private Shared Function DegToRad(ByVal degrees As Double) As Double
        Return (degrees / 180.0) * Math.PI
    End Function

    Private Shared Function GetTextureCoordinate(ByVal theta As Double, ByVal phi As Double) As System.Windows.Point
        Dim p As New System.Windows.Point(theta / (2 * Math.PI), phi / (Math.PI))

        Return p
    End Function

    ' Tesselates the sphere and returns a MeshGeometry3D representing the 
    ' tessellation based on the given parameters
    Friend Shared Function Tessellate(ByVal tDiv As Integer, ByVal pDiv As Integer, ByVal radius As Double) As MeshGeometry3D
        Dim dt As Double = DegToRad(360.0) / tDiv
        Dim dp As Double = DegToRad(180.0) / pDiv

        Dim mesh As New MeshGeometry3D()

        For pi As Integer = 0 To pDiv
            Dim phi As Double = pi * dp

            For ti As Integer = 0 To tDiv
                ' we want to start the mesh on the x axis
                Dim theta As Double = ti * dt

                mesh.Positions.Add(GetPosition(theta, phi, radius))
                mesh.Normals.Add(GetNormal(theta, phi))
                mesh.TextureCoordinates.Add(GetTextureCoordinate(theta, phi))
            Next ti
        Next pi

        For pi As Integer = 0 To pDiv - 1
            For ti As Integer = 0 To tDiv - 1
                Dim x0 As Integer = ti
                Dim x1 As Integer = (ti + 1)
                Dim y0 As Integer = pi * (tDiv + 1)
                Dim y1 As Integer = (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)
            Next ti
        Next pi

        mesh.Freeze()
        Return mesh
    End Function
End Class

전체 샘플은 UIElement3D Sphere 샘플을 참조하세요.

설명

클래스에서 UIElement3D 클래스를 파생할 때 이 메서드를 메서드와 InvalidateModel 함께 사용하여 요소의 모델을 새로 고칠 수 있습니다.

고급 시나리오에서는 이 메서드를 호출하기만 하면 됩니다. 이러한 고급 시나리오 중 하나는 파생 클래스에 모양에 영향을 주는 여러 속성이 있고 기본 모델을 한 번만 업데이트하려는 경우입니다. 메서드 내에서 OnUpdateModel 클래스의 속성을 업데이트할 Visual3DModel 수 있습니다 Visual3D .

이 메서드는 클래스에 기본 구현이 UIElement3D 없습니다.

OnUpdateModel .NET Framework 버전 3.5에서에서 도입 되었습니다. 자세한 내용은 버전 및 종속성을 참조하세요.

적용 대상