WPF 3D POINT DRAWING

时间:2011-08-24 17:31:19

标签: wpf 3d

我需要使用WPF在3D中绘制一个点。我正在使用类ScreenSpaceLines3D在3D中绘制一条线,但我无法在3D中绘制点(模型缩放时)。有谁能够帮我?一些示例代码将不胜感激。感谢

4 个答案:

答案 0 :(得分:1)

使用PointsVisual3D中的helixtoolkit课程,您可以在viewport上添加颜色,大小的点数。即使你也可以应用变换。

答案 1 :(得分:0)

无法看到一点,因为它没有表面区域。遗憾的是,WPF 3d不是光线跟踪引擎。

然而,有人建立了一个相当不错的光线跟踪入门库。如果你想用WPF进行射线追踪,这个项目是一个很好的起点:http://raytracer.codeplex.com/

答案 2 :(得分:0)

这不是一项复杂的任务。

  1. 下载Helix3D库

  2. 在样本中找到球体网格代码

  3. 将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;
    }
}