WPF三维点绘制
我需要使用WPF在3D中绘制一个点。我正在使用ScreenSpaceLines3D类在3D中绘制一条线,但我无法在3D中绘制点(在模型缩放时)。有人能帮我吗?一些示例代码将不胜感激。谢谢,一个点看不见,因为它没有表面积。不幸的是,WPF 3d不是光线跟踪引擎WPF三维点绘制,wpf,3d,Wpf,3d,我需要使用WPF在3D中绘制一个点。我正在使用ScreenSpaceLines3D类在3D中绘制一条线,但我无法在3D中绘制点(在模型缩放时)。有人能帮我吗?一些示例代码将不胜感激。谢谢,一个点看不见,因为它没有表面积。不幸的是,WPF 3d不是光线跟踪引擎 然而,有人构建了一个相当不错的光线跟踪初学者库。如果要使用WPF进行光线跟踪,此项目是一个很好的起点:。这不是一项很复杂的任务 下载Helix3D库 在示例中查找球体网格代码 将球体半径附加到缩放实现 使用helixtoolkit中的Poi
然而,有人构建了一个相当不错的光线跟踪初学者库。如果要使用WPF进行光线跟踪,此项目是一个很好的起点:。这不是一项很复杂的任务
使用
helixtoolkit
中的PointsVisual3D
类,您可以使用它在视口
上添加具有颜色、大小的点。甚至您也可以应用转换。我可以创建自己的PointVisual3d类。下面是PointVisual3D的代码,我认为这对你很有帮助
public class PointVisual3D:ModelVisual3D
{
private readonly GeometryModel3D _model;
private readonly MeshGeometry3D _mesh;
private Matrix3D _visualToScreen;
private Matrix3D _screenToVisual;
public PointVisual3D()
{
_mesh = new MeshGeometry3D();
_model = new GeometryModel3D();
_model.Geometry = _mesh;
SetColor(this.Color);
this.Content = _model;
this.Points = new Point3DCollection();
CompositionTarget.Rendering += OnRender;
}
private void OnRender(object sender, EventArgs e)
{
if (Points.Count == 0 && _mesh.Positions.Count == 0)
{
return;
}
if (UpdateTransforms() && MainWindow.mousedown==false)
{
RebuildGeometry();
}
}
public static readonly DependencyProperty ColorProperty = DependencyProperty.Register("Color", typeof(Color), typeof(PointVisual3D), new PropertyMetadata(Colors.White, OnColorChanged));
private static void OnColorChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
((PointVisual3D)sender).SetColor((Color)args.NewValue);
}
private void SetColor(Color color)
{
MaterialGroup unlitMaterial = new MaterialGroup();
unlitMaterial.Children.Add(new DiffuseMaterial(new SolidColorBrush(Colors.Black)));
unlitMaterial.Children.Add(new EmissiveMaterial(new SolidColorBrush(color)));
unlitMaterial.Freeze();
_model.Material = unlitMaterial;
_model.BackMaterial = unlitMaterial;
}
public Color Color
{
get { return (Color)GetValue(ColorProperty); }
set { SetValue(ColorProperty, value); }
}
//public static readonly DependencyProperty ThicknessProperty = DependencyProperty.Register("Thickness", typeof(double), typeof(PointVisual3D), new PropertyMetadata(1.0, OnThicknessChanged));
//private static void OnThicknessChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
//{
// ((PointVisual3D)sender).GeometryDirty();
//}
//public double Thickness
//{
// get { return (double)GetValue(ThicknessProperty); }
// set { SetValue(ThicknessProperty, value); }
//}
public static readonly DependencyProperty PointsProperty = DependencyProperty.Register("Points", typeof(Point3DCollection), typeof(PointVisual3D), new PropertyMetadata(null, OnPointsChanged));
private static void OnPointsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
((PointVisual3D)sender).GeometryDirty();
}
public Point3DCollection Points
{
get { return (Point3DCollection)GetValue(PointsProperty); }
set { SetValue(PointsProperty, value); }
}
private void GeometryDirty()
{
_visualToScreen = MathUtils.ZeroMatrix;
}
private void RebuildGeometry()
{
//double halfThickness = Thickness / 2.0;
//int numLines = Points.Count / 2;
//Point3DCollection positions = new Point3DCollection(numLines * 4);
//for (int i = 0; i < numLines; i++)
//{
// int startIndex = i * 2;
// Point3D startPoint = Points[startIndex];
// Point3D endPoint = Points[startIndex + 1];
// AddSegment(positions, startPoint, endPoint, halfThickness);
//}
//positions.Freeze();
//_mesh.Positions = positions;
Int32Collection indices = new Int32Collection(Points.Count * 6);
for (int i = 0; i < Points.Count; i++)
{
indices.Add(i * 4 + 2);
indices.Add(i * 4 + 1);
indices.Add(i * 4 + 0);
indices.Add(i * 4 + 2);
indices.Add(i * 4 + 3);
indices.Add(i * 4 + 1);
}
indices.Freeze();
_mesh.TriangleIndices = indices;
_mesh.Positions = CreatePositions(this.Points, this.Size, 0.0);
}
public Point3DCollection CreatePositions(IList<Point3D> points, double size = 1.0, double depthOffset = 0.0)
{
double halfSize = size / 2.0;
int numPoints = points.Count;
var outline = new[]
{
new Vector(-halfSize, halfSize), new Vector(-halfSize, -halfSize), new Vector(halfSize, halfSize),
new Vector(halfSize, -halfSize)
};
var positions = new Point3DCollection(numPoints * 4);
for (int i = 0; i < numPoints; i++)
{
var screenPoint = (Point4D)points[i] * this._visualToScreen;
double spx = screenPoint.X;
double spy = screenPoint.Y;
double spz = screenPoint.Z;
double spw = screenPoint.W;
if (!depthOffset.Equals(0))
{
spz -= depthOffset * spw;
}
var p0 = new Point4D(spx, spy, spz, spw) * this._screenToVisual;
double pwinverse = 1 / p0.W;
foreach (var v in outline)
{
var p = new Point4D(spx + v.X * spw, spy + v.Y * spw, spz, spw) * this._screenToVisual;
positions.Add(new Point3D(p.X * pwinverse, p.Y * pwinverse, p.Z * pwinverse));
}
}
positions.Freeze();
return positions;
}
/// <summary>
/// Identifies the <see cref="Size"/> dependency property.
/// </summary>
public static readonly DependencyProperty SizeProperty = DependencyProperty.Register(
"Size", typeof(double), typeof(PointVisual3D), new UIPropertyMetadata(1.0, GeometryChanged));
protected static void GeometryChanged(object sender, DependencyPropertyChangedEventArgs e)
{
((PointVisual3D)sender).GeometryDirty();
}
public double Size
{
get
{
return (double)this.GetValue(SizeProperty);
}
set
{
this.SetValue(SizeProperty, value);
}
}
//private void AddSegment(Point3DCollection positions, Point3D startPoint, Point3D endPoint, double halfThickness)
//{
// Vector3D lineDirection = endPoint * _visualToScreen - startPoint * _visualToScreen;
// lineDirection.Z = 0;
// lineDirection.Normalize();
// Vector delta = new Vector(-lineDirection.Y, lineDirection.X);
// delta *= halfThickness;
// Point3D pOut1, pOut2;
// Widen(startPoint, delta, out pOut1, out pOut2);
// positions.Add(pOut1);
// positions.Add(pOut2);
// Widen(endPoint, delta, out pOut1, out pOut2);
// positions.Add(pOut1);
// positions.Add(pOut2);
//}
//private void Widen(Point3D pIn, Vector delta, out Point3D pOut1, out Point3D pOut2)
//{
// Point4D pIn4 = (Point4D)pIn;
// Point4D pOut41 = pIn4 * _visualToScreen;
// Point4D pOut42 = pOut41;
// pOut41.X += delta.X * pOut41.W;
// pOut41.Y += delta.Y * pOut41.W;
// pOut42.X -= delta.X * pOut42.W;
// pOut42.Y -= delta.Y * pOut42.W;
// pOut41 *= _screenToVisual;
// pOut42 *= _screenToVisual;
// pOut1 = new Point3D(pOut41.X / pOut41.W, pOut41.Y / pOut41.W, pOut41.Z / pOut41.W);
// pOut2 = new Point3D(pOut42.X / pOut42.W, pOut42.Y / pOut42.W, pOut42.Z / pOut42.W);
//}
private bool UpdateTransforms()
{
Viewport3DVisual viewport;
bool success;
Matrix3D visualToScreen = MathUtils.TryTransformTo2DAncestor(this, out viewport, out success);
if (!success || !visualToScreen.HasInverse)
{
_mesh.Positions = null;
return false;
}
if (visualToScreen == _visualToScreen)
{
return false;
}
_visualToScreen = _screenToVisual = visualToScreen;
_screenToVisual.Invert();
return true;
}
}
公共类PointVisual3D:ModelVisual3D
{
私有只读GeometryModel3D_模型;
私有只读网格Geometry3D_网格;
私有矩阵3D_可视屏幕;
私有矩阵3d_屏幕可视;
公共点Visual3D()
{
_mesh=新的MeshGeometry3D();
_模型=新几何模型3D();
_模型几何=_网格;
SetColor(this.Color);
this.Content=\u模型;
this.Points=new Point3DCollection();
CompositionTarget.Rendering+=OnRender;
}
私有void OnRender(对象发送方、事件参数)
{
if(Points.Count==0&&&u mesh.Positions.Count==0)
{
返回;
}
if(UpdateTransforms()&&MainWindow.mousedown==false)
{
重建计量学();
}
}
public static readonly dependencProperty ColorProperty=dependencProperty.Register(“Color”、typeof(Color)、typeof(PointVisual3D)、newpropertyMetadata(Colors.White、OnColorChanged));
私有静态无效OnColorChanged(DependencyObject发送方,DependencyPropertyChangedEventArgs参数)
{
((PointVisual3D)sender.SetColor((Color)args.NewValue);
}
私有void SetColor(颜色)
{
MaterialGroup unlitMaterial=新材料组();
unlitMaterial.Children.Add(新的漫反射材质(新的SolidColorBrush(Colors.Black));
unlitMaterial.Children.Add(新的发射材质(新的SolidColorBrush(颜色));
不重要。冻结();
_模型材料=非材料;
_model.BackMaterial=非材料;
}
公共颜色
{
获取{return(Color)GetValue(ColorProperty);}
set{SetValue(ColorProperty,value);}
}
//public static readonly dependencProperty thicknesproperty=dependencProperty.Register(“厚度”、typeof(双精度)、typeof(PointVisual3D)、新属性元数据(1.0,onthickneschanged));
//ICKNESCHANGED上的私有静态无效(DependencyObject发件人,DependencyPropertyChangedEventArgs参数)
//{
//((PointVisual3D)发送器);
//}
//公共双层厚度
//{
//获取{return(double)GetValue(ThicknessProperty);}
//set{SetValue(ThicknessProperty,value);}
//}
公共静态只读DependencyProperty PointsProperty=DependencyProperty.Register(“点”、typeof(Point3DCollection)、typeof(PointVisual3D)、new PropertyMetadata(null、OnPointsChanged));
私有静态无效OnPointsChanged(DependencyObject发送方,DependencyPropertyChangedEventArgs参数)
{
((PointVisual3D)发送器);
}
公共点收集点
{
获取{return(Point3DCollection)GetValue(PointsProperty);}
set{SetValue(PointsProperty,value);}
}
私人空间几何体()
{
_visualToScreen=MathUtils.ZeroMatrix;
}
私人空间重建测量法()
{
//双半厚度=厚度/2.0;
//int numLines=点数。计数/2;
//Point3DCollection位置=新的Point3DCollection(numLines*4);
//对于(int i=0;i