UIElement3D.OnUpdateModel Method
Definition
Important
Some information relates to prerelease product that may be substantially modified before it’s released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
Participates in rendering operations when overridden in a derived class.
protected:
virtual void OnUpdateModel();
protected virtual void OnUpdateModel ();
abstract member OnUpdateModel : unit -> unit
override this.OnUpdateModel : unit -> unit
Protected Overridable Sub OnUpdateModel ()
Examples
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;
}
}
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
Remarks
When you derive a class from the UIElement3D class, you can use this method together with the InvalidateModel method to refresh the model of the element.
You only need to call this method in advanced scenarios. One such advanced scenario is if the derived class has multiple properties that affect the appearance, and you want to update the underlying model only once. Within the OnUpdateModel method you could update the Visual3DModel property of the Visual3D class.
This method has no default implementation in the UIElement3D class.
Applies to
Зворотний зв’язок
https://aka.ms/ContentUserFeedback.
Очікується незабаром: протягом 2024 року ми будемо припиняти використання механізму реєстрації проблем у GitHub для зворотного зв’язку щодо вмісту й замінювати його новою системою зворотного зв’язку. Докладніше:Надіслати й переглянути відгук про