我需要使用WPF在3D中绘制一个点。我正在使用类ScreenSpaceLines3D在3D中绘制一条线,但我无法在3D中绘制点(模型缩放时)。有谁能够帮我?一些示例代码将不胜感激。感谢
答案 0 :(得分:1)
使用PointsVisual3D
中的helixtoolkit
课程,您可以在viewport
上添加颜色,大小的点数。即使你也可以应用变换。
答案 1 :(得分:0)
无法看到一点,因为它没有表面区域。遗憾的是,WPF 3d不是光线跟踪引擎。
然而,有人建立了一个相当不错的光线跟踪入门库。如果你想用WPF进行射线追踪,这个项目是一个很好的起点:http://raytracer.codeplex.com/。
答案 2 :(得分:0)
这不是一项复杂的任务。
下载Helix3D库
在样本中找到球体网格代码
将scphere的半径附加到缩放实现。
答案 3 :(得分:0)
我可以创建一个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;
}
}