none
WPF .net 4.0中Viewport3D 出现一条缝,3.5中不会,怎么解决? RRS feed

  • 问题

  • 我在Viewport3D中建了个 球体模型,将一张全景图片贴在球体内侧面,把Camera放在球心中,实现3D浏览全景图的效果。

    但是在.net 4.0中,会出现一条缝,.net 3.5中却不会出现这条缝。如何在.net 4.0 中不要让这条缝出现?

    这是后台代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Controls;
    using System.Windows;
    using System.Windows.Media.Media3D;
    using System.Windows.Media;
    using System.Windows.Input;
    using System.Windows.Media.Animation;
    using System.Collections.Specialized;
    
    namespace WpfApplication15
    {
        public class PanoramaViewer : Viewport3D
        {
            public PanoramaViewer()
            {
                InitializeViewer();
                
            }
    
            public double FieldOfView
            {
                get { return (double)GetValue(FieldOfViewProperty); }
                set
                {
                    if (value >= MinFieldOfView && value <= MaxFieldOfView)
                    {
                        SetValue(FieldOfViewProperty, value);
                    }
                }
            }
            public static readonly DependencyProperty FieldOfViewProperty = DependencyProperty.Register("FieldOfView", typeof(double), typeof(PanoramaViewer), new PropertyMetadata(90.0, new PropertyChangedCallback(OnFieldOfViewChanged)));
    
            private static void OnFieldOfViewChanged(Object sender, DependencyPropertyChangedEventArgs e)
            {
                PanoramaViewer Viewer = (PanoramaViewer)sender;
                PerspectiveCamera Camera = Viewer.Camera as PerspectiveCamera;
                Camera.FieldOfView = Viewer.FieldOfView;
            }
    
            public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(PanoramaViewer), new PropertyMetadata(null, new PropertyChangedCallback(UpdateImageSource)));
    
            private static void UpdateImageSource(DependencyObject sender, DependencyPropertyChangedEventArgs args)
            {
                PanoramaViewer viewer = sender as PanoramaViewer;
                if (viewer.ImageSource == null)
                {
                    viewer._panoramaGeometry.BackMaterial = null;
                }
                else
                {
                    viewer._panoramaGeometry.BackMaterial = new DiffuseMaterial(new ImageBrush(viewer.ImageSource));
                }
            }
    
            public ImageSource ImageSource
            {
                get { return (ImageSource)GetValue(ImageSourceProperty); }
                set { SetValue(ImageSourceProperty, value); }
            }
    
            #region Rotation
    
            public static readonly DependencyProperty RotationXProperty = DependencyProperty.Register("RotationX", typeof(double), typeof(PanoramaViewer), new PropertyMetadata(0.0, UpdateRotation));
            public static readonly DependencyProperty RotationYProperty = DependencyProperty.Register("RotationY", typeof(double), typeof(PanoramaViewer), new PropertyMetadata(0.0, UpdateRotation));
    
    
    
            public double RotationX
            {
                get { return (double)GetValue(RotationXProperty); }
                set
                {
                    if (value <= 90 && value >= -90)
                    {
                        SetValue(RotationXProperty, value);
                    }
                }
            }
            public double RotationY
            {
                get { return (double)GetValue(RotationYProperty); }
                set { SetValue(RotationYProperty, value); }
            }
    
            private static void UpdateRotation(DependencyObject sender, DependencyPropertyChangedEventArgs args)
            {
                PanoramaViewer viewer = sender as PanoramaViewer;
                viewer.AxisAngleRotationX.Angle = viewer.RotationX;
                viewer.AxisAngleRotationY.Angle = viewer.RotationY;
    
                if (viewer.CameraRotated != null)
                {
                    viewer.CameraRotated(viewer, null);
                }
            }
    
            public event EventHandler CameraRotated;
    
            private RotateTransform3D RotateTransformX { get; set; }
            private RotateTransform3D RotateTransformY { get; set; }
    
            private AxisAngleRotation3D AxisAngleRotationX { get; set; }
            private AxisAngleRotation3D AxisAngleRotationY { get; set; }
            #endregion
    
    
            private ModelVisual3D _panoramaObject;
            private GeometryModel3D _panoramaGeometry;
    
            private void InitializeViewer()
            {
                PerspectiveCamera camera = new PerspectiveCamera();
                camera.Position = new Point3D(0, -0.0, 0);
                camera.UpDirection = new Vector3D(0, 1, 0);
                camera.LookDirection = new Vector3D(0, 0, -1);
                camera.FieldOfView = 90;
                this.Camera = camera;
    
                ModelVisual3D lightModel = new ModelVisual3D();
                lightModel.Content = new AmbientLight(Colors.White);
                this.Children.Add(lightModel);
    
                _panoramaObject = new ModelVisual3D();
                _panoramaGeometry = new GeometryModel3D();
                _panoramaGeometry.Geometry = CreateGeometry();
                _panoramaObject.Content = _panoramaGeometry;
    
    
                AxisAngleRotationX = new AxisAngleRotation3D() { Axis = new Vector3D(1, 0, 0) };
                AxisAngleRotationY = new AxisAngleRotation3D() { Axis = new Vector3D(0, 1, 0) };
    
                RotateTransformX = new RotateTransform3D() { Rotation = AxisAngleRotationX };
                RotateTransformY = new RotateTransform3D() { Rotation = AxisAngleRotationY };
                ScaleTransform3D ScaleTransform = new ScaleTransform3D() { ScaleX = 1, ScaleY = 1, ScaleZ = 1 };
                Transform3DGroup Group = new Transform3DGroup();
    
                Group.Children.Add(ScaleTransform);
                Group.Children.Add(RotateTransformX);
                Group.Children.Add(RotateTransformY);
                this.Camera.Transform = Group;
    
                this.Children.Add(_panoramaObject);
    
                this.MouseLeftButtonDown += PanoramaViewer_MouseLeftButtonDown;
                this.PreviewMouseLeftButtonUp += PanoramaViewer_PreviewMouseLeftButtonUp;
    
            }
            private double _minFieldOfView = 45;
    
            public double MinFieldOfView
            {
                get { return _minFieldOfView; }
                set { _minFieldOfView = value; }
            }
    
            private double _maxFieldOfView = 90;
    
            public double MaxFieldOfView
            {
                get { return _maxFieldOfView; }
                set { _maxFieldOfView = value; }
            }
    
            private double _fieldOfViewDeltaOnMouseWheel = 5;
    
            public double FieldOfViewDeltaOnMouseWheel
            {
                get { return _fieldOfViewDeltaOnMouseWheel; }
                set { _fieldOfViewDeltaOnMouseWheel = value; }
            }
    
    
            void PanoramaViewer_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                this.MouseMove -= PanoramaViewer_MouseMove;
                this.ReleaseMouseCapture();
            }
    
            void PanoramaViewer_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
    
                _downPoint = e.GetPosition(this);
                _rotationVector.X = RotationX;
                _rotationVector.Y = RotationY;
                Mouse.Capture(this, CaptureMode.Element);
                this.MouseMove -= PanoramaViewer_MouseMove;
                this.MouseMove += PanoramaViewer_MouseMove;
            }
    
            private Vector _rotationVector = new Vector();
            private Point _downPoint = new Point();
    
            void PanoramaViewer_MouseMove(object sender, MouseEventArgs e)
            {
                if (e.LeftButton == MouseButtonState.Pressed)
                {
                    Vector Offset = Point.Subtract(e.GetPosition(this), _downPoint) * 0.25;
    
                    SetValue(RotationYProperty, _rotationVector.Y + Offset.X);
                    double rotationX = _rotationVector.X + Offset.Y;
                    if (rotationX >= -90 && rotationX <= 90)
                    {
                        SetValue(RotationXProperty, rotationX);
                    }
    
                }
                else
                {
                    this.MouseMove -= PanoramaViewer_MouseMove;
                    this.ReleaseMouseCapture();
                }
            }
    
            private int _slices = 64;
            private int _stacks = 64;
    
            public int Slices
            {
                get { return _slices; }
            }
    
            public int Stacks
            {
                get { return _stacks; }
            }
    
            private double _radius = 1;
    
            public double Radius
            {
                get { return _radius; }
            }
    
            private Geometry3D CreateGeometry()
            {
                MeshGeometry3D mesh = new MeshGeometry3D();           
                for (int stack = 0; stack <= Stacks; stack++)
                {
                    double phi = Math.PI / 2 + stack * Math.PI / Stacks;
                    double y = Radius * Math.Sin(phi);
                    double scale = -Radius * Math.Cos(phi);
    
                    for (int slice = 0; slice <= Slices; slice++)
                    {
                        double theta = slice * 2 * Math.PI / Slices;
                        double x = scale * Math.Sin(theta);
                        double z = scale * Math.Cos(theta);
    
                        Point3D position = new Point3D(x, y, z);
                        Vector3D normal = new Vector3D(x, y, z);
                        mesh.Positions.Add(position);
                        mesh.Normals.Add(normal);
                        mesh.TextureCoordinates.Add(new Point(-theta, phi));
                    }
                }
    
                for (int stack = 0; stack < Stacks; stack++)
                {
                    int top = (stack + 0) * (Slices + 1);
                    int bot = (stack + 1) * (Slices + 1);
    
                    for (int slice = 0; slice < Slices; slice++)
                    {
                        if (stack < Stacks - 1)
                        {
                            mesh.TriangleIndices.Add(top + slice + 1);
                            mesh.TriangleIndices.Add(bot + slice);
                            mesh.TriangleIndices.Add(bot + slice + 1);
                        }
                        if (stack != 0)
                        {
                            mesh.TriangleIndices.Add(top + slice);
                            mesh.TriangleIndices.Add(bot + slice);
                            mesh.TriangleIndices.Add(top + slice + 1);
                        }
                    }
                }
                mesh.Freeze();
                return mesh;
            }
    
        }
    }
    

    xaml:

    <Window xmlns:my="clr-namespace:WpfApplication15"  x:Class="WpfApplication15.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <my:PanoramaViewer ImageSource="/WpfApplication15;component/Images/20140520112135777cpATM(小).jpg" />
        </Grid>
    </Window>
    

    我在论坛发不了图,该怎么发图?

    2014年7月2日 8:56

全部回复

  •  项目文件地址:http://pan.baidu.com/s/1tlDyY  

    2014年7月2日 9:29
  • 你好,

    论坛需要一段时间验证账号,一段时间后就可以发帖和链接。

    另外,我在本机运行的效果,没有看到那条线。

    我建议升级一下.NET 4.0,把相应的补丁打上。

    另外:我在.NET 4.5的环境下也做了测试,没有一条缝。:(

    谢谢!


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2014年7月3日 5:53
    版主
  • 要旋转到一定角度才能看到那条线。

    左键点击按住界面进行拖动旋转。

    http://pan.baidu.com/s/1gdkUbmF  这个是3.5与4.0的对比图

    2014年7月4日 2:12
  • 下载到你的图片看了下。不过在.NET 4.5平台下就OK了。我本地没有装.NET 4.0.建议你用最新平台吧。代码一样,效果不同,很可能是个BUG。:)
    2014年7月7日 5:59