WPF三维点绘制

WPF三维点绘制,wpf,3d,Wpf,3d,我需要使用WPF在3D中绘制一个点。我正在使用ScreenSpaceLines3D类在3D中绘制一条线,但我无法在3D中绘制点(在模型缩放时)。有人能帮我吗?一些示例代码将不胜感激。谢谢,一个点看不见,因为它没有表面积。不幸的是,WPF 3d不是光线跟踪引擎 然而,有人构建了一个相当不错的光线跟踪初学者库。如果要使用WPF进行光线跟踪,此项目是一个很好的起点:。这不是一项很复杂的任务 下载Helix3D库 在示例中查找球体网格代码 将球体半径附加到缩放实现 使用helixtoolkit中的Poi

我需要使用WPF在3D中绘制一个点。我正在使用ScreenSpaceLines3D类在3D中绘制一条线,但我无法在3D中绘制点(在模型缩放时)。有人能帮我吗?一些示例代码将不胜感激。谢谢,一个点看不见,因为它没有表面积。不幸的是,WPF 3d不是光线跟踪引擎


然而,有人构建了一个相当不错的光线跟踪初学者库。如果要使用WPF进行光线跟踪,此项目是一个很好的起点:。

这不是一项很复杂的任务

  • 下载Helix3D库

  • 在示例中查找球体网格代码

  • 将球体半径附加到缩放实现


  • 使用
    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