WPF 中的动态运行时 3D 点
Dynamic Runtime 3D Points in WPF
我正在尝试使用 WPF 创建 3D 点的动态视图,我能够绘制第一组点,但随后它崩溃了,因为 Mesh3DGeometry 被冻结了.. 是否可以解冻 Mesh3DGeomerty 并清除网格以便可以绘制下一组?
var rand = new Random();
while (true)
{
points.Clear();
for (int i = 0; i < 100; i++)
{
points.Add(new Point3D(rand.NextDouble(), rand.NextDouble(), rand.NextDouble()));
}
for (int i = 0; i < points.Count; i++)
{
AddCubeToMesh(pointCloudMesh, points[i], 0.01);
}
pointCloudMesh.Freeze();
}
还有XAML在这里
<Grid Grid.Row="1" Grid.Column="1" Margin="0 20 0 -20" Background="LightGray" Name="MyCanvas" >
<Viewport3D>
<Viewport3D.Camera>
<PerspectiveCamera x:Name="camMain" Position="0 0 5" LookDirection="0 0 -5"/>
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<Model3DGroup.Children>
<AmbientLight Color="#AAAAAA" />
</Model3DGroup.Children>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D x:Name="pointCloudMesh" />
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial Brush="Red"/>
</GeometryModel3D.Material>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
</Grid>
AddCubeToMesh 代码
private void AddCubeToMesh(MeshGeometry3D mesh, Point3D center, double size)
{
if (mesh != null)
{
int offset = mesh.Positions.Count;
mesh.Positions.Add(new Point3D(center.X - size, center.Y + size, center.Z - size));
mesh.Positions.Add(new Point3D(center.X + size, center.Y + size, center.Z - size));
mesh.Positions.Add(new Point3D(center.X + size, center.Y + size, center.Z + size));
mesh.Positions.Add(new Point3D(center.X - size, center.Y + size, center.Z + size));
mesh.Positions.Add(new Point3D(center.X - size, center.Y - size, center.Z - size));
mesh.Positions.Add(new Point3D(center.X + size, center.Y - size, center.Z - size));
mesh.Positions.Add(new Point3D(center.X + size, center.Y - size, center.Z + size));
mesh.Positions.Add(new Point3D(center.X - size, center.Y - size, center.Z + size));
mesh.TriangleIndices.Add(offset + 3);
mesh.TriangleIndices.Add(offset + 2);
mesh.TriangleIndices.Add(offset + 6);
mesh.TriangleIndices.Add(offset + 3);
mesh.TriangleIndices.Add(offset + 6);
mesh.TriangleIndices.Add(offset + 7);
mesh.TriangleIndices.Add(offset + 2);
mesh.TriangleIndices.Add(offset + 1);
mesh.TriangleIndices.Add(offset + 5);
mesh.TriangleIndices.Add(offset + 2);
mesh.TriangleIndices.Add(offset + 5);
mesh.TriangleIndices.Add(offset + 6);
mesh.TriangleIndices.Add(offset + 1);
mesh.TriangleIndices.Add(offset + 0);
mesh.TriangleIndices.Add(offset + 4);
mesh.TriangleIndices.Add(offset + 1);
mesh.TriangleIndices.Add(offset + 4);
mesh.TriangleIndices.Add(offset + 5);
mesh.TriangleIndices.Add(offset + 0);
mesh.TriangleIndices.Add(offset + 3);
mesh.TriangleIndices.Add(offset + 7);
mesh.TriangleIndices.Add(offset + 0);
mesh.TriangleIndices.Add(offset + 7);
mesh.TriangleIndices.Add(offset + 4);
mesh.TriangleIndices.Add(offset + 7);
mesh.TriangleIndices.Add(offset + 6);
mesh.TriangleIndices.Add(offset + 5);
mesh.TriangleIndices.Add(offset + 7);
mesh.TriangleIndices.Add(offset + 5);
mesh.TriangleIndices.Add(offset + 4);
mesh.TriangleIndices.Add(offset + 2);
mesh.TriangleIndices.Add(offset + 3);
mesh.TriangleIndices.Add(offset + 0);
mesh.TriangleIndices.Add(offset + 2);
mesh.TriangleIndices.Add(offset + 0);
mesh.TriangleIndices.Add(offset + 1);
}
}
我有点用的解决方案是将所有这些添加到一个单独的 UserControl 中,并在每次新数据到达时调用它
首先:在不给 UI 线程时间的情况下生成 UI 部分的无限循环将不起作用。在单独的线程上生成数据并将数据传递给 UI 线程以创建模型并显示它。
然后,无法解冻可冻结对象:
"Unfreezing" a Freezable Once frozen, a Freezable can never be
modified or unfrozen; however, you can create an unfrozen clone using
the Clone or CloneCurrentValue method.
因此,如果您认为确实需要 Freeze/Unfreeze,您可以通过克隆来实现。我认为这里不需要。
我想出的解决方案是将点云视图与另一个用户控件分开,每次我想显示一组新数据时,我都会销毁旧的用户控件并重建它..这是一种激进的方法,但有效很好
XAML 用于新的用户控件
<UserControl x:Class="LPDTool.View3D"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:LPDTool"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="500"
KeyDown="Window_KeyDown">
<GroupBox x:Name="GBox" Margin="0 20 0 -20" Foreground="#AAAAAA" FontSize="18" FontWeight="Medium" Background="#DDDBDA" BorderBrush="#7B7704" BorderThickness="2" FontFamily="Abadi MT">
<Viewport3D>
<Viewport3D.Camera>
<PerspectiveCamera x:Name="camMain"/>
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<Model3DGroup.Children>
<AmbientLight Color="#AAAAAA" />
</Model3DGroup.Children>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D x:Name="pointCloudMesh" />
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial Brush="Red"/>
</GeometryModel3D.Material>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
</GroupBox>
初始化构造函数
public View3D()
{
InitializeComponent();
PositionCamera();
for (int i = 0; i < LPDTest.points.Count; i++)
{
AddCubeToMesh(pointCloudMesh, points[i], 0.02);
}
}
XAML为包含部分
<Grid x:Name="My3dview">
</Grid>
这里是生成代码部分(带有dumpy数据)
var rand = new Random();
while (true)
{
My3dview.Children.Clear();
points.Clear();
for (int i = 0; i < 100; i++)
{
points.Add(new Point3D(rand.NextDouble(), rand.NextDouble(), rand.NextDouble()));
}
My3dview.Children.Add(new View3D());
}
我正在尝试使用 WPF 创建 3D 点的动态视图,我能够绘制第一组点,但随后它崩溃了,因为 Mesh3DGeometry 被冻结了.. 是否可以解冻 Mesh3DGeomerty 并清除网格以便可以绘制下一组?
var rand = new Random();
while (true)
{
points.Clear();
for (int i = 0; i < 100; i++)
{
points.Add(new Point3D(rand.NextDouble(), rand.NextDouble(), rand.NextDouble()));
}
for (int i = 0; i < points.Count; i++)
{
AddCubeToMesh(pointCloudMesh, points[i], 0.01);
}
pointCloudMesh.Freeze();
}
还有XAML在这里
<Grid Grid.Row="1" Grid.Column="1" Margin="0 20 0 -20" Background="LightGray" Name="MyCanvas" >
<Viewport3D>
<Viewport3D.Camera>
<PerspectiveCamera x:Name="camMain" Position="0 0 5" LookDirection="0 0 -5"/>
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<Model3DGroup.Children>
<AmbientLight Color="#AAAAAA" />
</Model3DGroup.Children>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D x:Name="pointCloudMesh" />
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial Brush="Red"/>
</GeometryModel3D.Material>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
</Grid>
AddCubeToMesh 代码
private void AddCubeToMesh(MeshGeometry3D mesh, Point3D center, double size)
{
if (mesh != null)
{
int offset = mesh.Positions.Count;
mesh.Positions.Add(new Point3D(center.X - size, center.Y + size, center.Z - size));
mesh.Positions.Add(new Point3D(center.X + size, center.Y + size, center.Z - size));
mesh.Positions.Add(new Point3D(center.X + size, center.Y + size, center.Z + size));
mesh.Positions.Add(new Point3D(center.X - size, center.Y + size, center.Z + size));
mesh.Positions.Add(new Point3D(center.X - size, center.Y - size, center.Z - size));
mesh.Positions.Add(new Point3D(center.X + size, center.Y - size, center.Z - size));
mesh.Positions.Add(new Point3D(center.X + size, center.Y - size, center.Z + size));
mesh.Positions.Add(new Point3D(center.X - size, center.Y - size, center.Z + size));
mesh.TriangleIndices.Add(offset + 3);
mesh.TriangleIndices.Add(offset + 2);
mesh.TriangleIndices.Add(offset + 6);
mesh.TriangleIndices.Add(offset + 3);
mesh.TriangleIndices.Add(offset + 6);
mesh.TriangleIndices.Add(offset + 7);
mesh.TriangleIndices.Add(offset + 2);
mesh.TriangleIndices.Add(offset + 1);
mesh.TriangleIndices.Add(offset + 5);
mesh.TriangleIndices.Add(offset + 2);
mesh.TriangleIndices.Add(offset + 5);
mesh.TriangleIndices.Add(offset + 6);
mesh.TriangleIndices.Add(offset + 1);
mesh.TriangleIndices.Add(offset + 0);
mesh.TriangleIndices.Add(offset + 4);
mesh.TriangleIndices.Add(offset + 1);
mesh.TriangleIndices.Add(offset + 4);
mesh.TriangleIndices.Add(offset + 5);
mesh.TriangleIndices.Add(offset + 0);
mesh.TriangleIndices.Add(offset + 3);
mesh.TriangleIndices.Add(offset + 7);
mesh.TriangleIndices.Add(offset + 0);
mesh.TriangleIndices.Add(offset + 7);
mesh.TriangleIndices.Add(offset + 4);
mesh.TriangleIndices.Add(offset + 7);
mesh.TriangleIndices.Add(offset + 6);
mesh.TriangleIndices.Add(offset + 5);
mesh.TriangleIndices.Add(offset + 7);
mesh.TriangleIndices.Add(offset + 5);
mesh.TriangleIndices.Add(offset + 4);
mesh.TriangleIndices.Add(offset + 2);
mesh.TriangleIndices.Add(offset + 3);
mesh.TriangleIndices.Add(offset + 0);
mesh.TriangleIndices.Add(offset + 2);
mesh.TriangleIndices.Add(offset + 0);
mesh.TriangleIndices.Add(offset + 1);
}
}
我有点用的解决方案是将所有这些添加到一个单独的 UserControl 中,并在每次新数据到达时调用它
首先:在不给 UI 线程时间的情况下生成 UI 部分的无限循环将不起作用。在单独的线程上生成数据并将数据传递给 UI 线程以创建模型并显示它。
然后,无法解冻可冻结对象:
"Unfreezing" a Freezable Once frozen, a Freezable can never be modified or unfrozen; however, you can create an unfrozen clone using the Clone or CloneCurrentValue method.
因此,如果您认为确实需要 Freeze/Unfreeze,您可以通过克隆来实现。我认为这里不需要。
我想出的解决方案是将点云视图与另一个用户控件分开,每次我想显示一组新数据时,我都会销毁旧的用户控件并重建它..这是一种激进的方法,但有效很好
XAML 用于新的用户控件
<UserControl x:Class="LPDTool.View3D"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:LPDTool"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="500"
KeyDown="Window_KeyDown">
<GroupBox x:Name="GBox" Margin="0 20 0 -20" Foreground="#AAAAAA" FontSize="18" FontWeight="Medium" Background="#DDDBDA" BorderBrush="#7B7704" BorderThickness="2" FontFamily="Abadi MT">
<Viewport3D>
<Viewport3D.Camera>
<PerspectiveCamera x:Name="camMain"/>
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<Model3DGroup.Children>
<AmbientLight Color="#AAAAAA" />
</Model3DGroup.Children>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D x:Name="pointCloudMesh" />
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial Brush="Red"/>
</GeometryModel3D.Material>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
</GroupBox>
初始化构造函数
public View3D()
{
InitializeComponent();
PositionCamera();
for (int i = 0; i < LPDTest.points.Count; i++)
{
AddCubeToMesh(pointCloudMesh, points[i], 0.02);
}
}
XAML为包含部分
<Grid x:Name="My3dview">
</Grid>
这里是生成代码部分(带有dumpy数据)
var rand = new Random();
while (true)
{
My3dview.Children.Clear();
points.Clear();
for (int i = 0; i < 100; i++)
{
points.Add(new Point3D(rand.NextDouble(), rand.NextDouble(), rand.NextDouble()));
}
My3dview.Children.Add(new View3D());
}