UIElement3D.InvalidateModel 方法
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
使表示元素的模型无效。
public:
void InvalidateModel();
public void InvalidateModel ();
member this.InvalidateModel : unit -> unit
Public Sub InvalidateModel ()
示例
以下示例演示如何从 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 类派生类时,可以将此方法与 OnUpdateModel 方法一起使用来刷新元素的模型。
只需在高级方案中调用此方法。 其中一种高级方案是,如果派生类具有影响外观的多个属性,并且你只想更新基础模型一次。