【问题标题】:WPF - Helix Toolkit Auto RotationWPF - Helix 工具包自动旋转
【发布时间】:2020-07-13 18:14:18
【问题描述】:

上周我一直在研究这个问题 - 2 周,但我一直无法找到解决方案。我正在从 STL 文件加载 3D 模型并尝试围绕 1 个轴自动旋转 3D 模型。这个想法类似于缓慢移动的动画,围绕模型的 Y 轴显示 360 度视图。

XAML:

<Grid>
    <StackPanel x:Name="myViewPort">
        <helix:HelixViewport3D x:Name="viewPort3d" ZoomExtentsWhenLoaded="true" RotateAroundMouseDownPoint="true" CameraRotationMode="Turntable" Height="1000" ShowViewCube="false">
            <helix:DefaultLights/>
            <ModelVisual3D x:Name="visualModel"/>
        </helix:HelixViewport3D>
    </StackPanel>
</Grid>

C#:

public void load3dModel()
    {
        StLReader stlReader = new StLReader();
        Model3DGroup MyModel = stlReader.Read(MODEL_PATH);

        /* Auto Rotate Here */

        System.Windows.Media.Media3D.Material mat = MaterialHelper.CreateMaterial(new SolidColorBrush(Color.FromRgb(255, 255, 255)));

        foreach (System.Windows.Media.Media3D.GeometryModel3D geometryModel in MyModel.Children)
        {
            geometryModel.Material = mat;
            geometryModel.BackMaterial = mat;
        }

        visualModel.Content = MyModel;
    }

这方面的棘手部分是我需要能够仅使用代码来旋转模型。生成的模型可以是数百个中的一个,这取决于模型的应用程序......所以代码需要能够处理围绕同一轴旋转,我可以保证何时导出 3D 模型对于 STL 文件,它将沿 X 轴平坦。

--- 更新 --- 通过情节提要尝试旋转:

public void load3dModel()
    {
        StLReader stlReader = new StLReader();
        Model3DGroup MyModel = stlReader.Read(MODEL_PATH);

        System.Windows.Media.Media3D.Material mat = MaterialHelper.CreateMaterial(new SolidColorBrush(Color.FromRgb(255, 255, 255)));

        foreach (System.Windows.Media.Media3D.GeometryModel3D geometryModel in MyModel.Children)
        {
            geometryModel.Material = mat;
            geometryModel.BackMaterial = mat;
        }

        visualModel.Content = MyModel;

        /* Auto Rotate Here */
        GeometryModel3D geoModel = new GeometryModel3D()
        {
            Transform = new RotateTransform3D()
            {
                Rotation = new AxisAngleRotation3D()
                {
                    Axis = new Vector3D(0, 1, 0),
                    Angle = 0
                }
            }
        };

        MyModel.Children.Add(geoModel);

        var Rotation3DAnimation = new Rotation3DAnimation();

        var FromAxis = new AxisAngleRotation3D()
        {
            Axis = new Vector3D(0, 1, 0),
            Angle = 0
        };

        var ToAxis = new AxisAngleRotation3D()
        {
            Axis = new Vector3D(0, 1, 0),
            Angle = 359
        };

        Rotation3DAnimation.From = FromAxis;
        Rotation3DAnimation.To = ToAxis;
        Rotation3DAnimation.Duration = Duration.Forever; //ADDED DURATION, Still did not work!

        var rotateStoryboard = new Storyboard
        {
            Duration = new Timespan(0, 0, 12),
            RepeatBehavior = RepeatBehavior.Forever,
        };

        Storyboard.SetTarget(Rotation3DAnimation, geoModel.Transform);
        Storyboard.SetTargetProperty(Rotation3DAnimation, new PropertyPath("Rotation"));

        rotateStoryboard.Children.Add(Rotation3DAnimation);
        rotateStoryboard.Begin();
    }

这不起作用...没有任何改变?

谢谢!

【问题讨论】:

    标签: wpf 3d 3d-modelling helix


    【解决方案1】:

    我不确定我是否正确理解了您要完成的工作,所以如果我误解了,请告诉我: 在您展示的代码中,您正在加载几个 GeometryModel3D,那么您是想让它们全部旋转还是只旋转一个?

    让它旋转的一种方法是通过 GeometryModel3D 的 Transform 属性。

    您必须设置 DispatcherTimer 并更新每个 Tick 的旋转角度:

    我根据您提供的内容制作了一个示例,我在其中旋转了一个 3D 模型:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.Load3dModel();
            this.timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(10) };
            this.timer.Tick += Timer_Tick;
            this.timer.Start();
        }
    
        /// <summary>
        /// Change the rotation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Timer_Tick(object sender, EventArgs e)
        {
            if (this.angle >= 360)
            {
                this.angle = 0;
            }
            else
            {
                //Nothing to do
            }
            this.angle = this.angle + 0.25;
            //You can adapt the code if you have many children 
            GeometryModel3D geometryModel3D = (GeometryModel3D)((Model3DGroup)visualModel.Content).Children.First();
            if (geometryModel3D.Transform is RotateTransform3D rotateTransform3 && rotateTransform3.Rotation is AxisAngleRotation3D rotation)
            {
                rotation.Angle = this.angle;
            }
            else
            {
                ///Initialize the Transform (I didn't do it in my example but you could do this initialization in <see Load3dModel/>)
                geometryModel3D.Transform = new RotateTransform3D()
                {
                    Rotation = new AxisAngleRotation3D()
                    {
                        Axis = new Vector3D(0, 1, 0),
                        Angle = this.angle,
                    }
                };
            }
        }
    
        private DispatcherTimer timer;
    
        public void Load3dModel()
        {
            StLReader stlReader = new StLReader();
            /*
            Model3DGroup MyModel = stlReader.Read(OrLoadFromPath));
            */
            Model3DGroup myModel = new Model3DGroup();
            // Create a mesh builder and add a box to it
            var meshBuilder = new MeshBuilder(false, false);
            meshBuilder.AddBox(new Point3D(0, 0, 1), 1, 2, 0.5);
            meshBuilder.AddBox(new Rect3D(0, 0, 1.2, 0.5, 1, 0.4));
    
            // Create a mesh from the builder (and freeze it)
            var mesh = meshBuilder.ToMesh(true);
    
            // Add 3 models to the group (using the same mesh, that's why we had to freeze it)
            myModel.Children.Add(new GeometryModel3D { Geometry = mesh});
            myModel.Children.Add(new GeometryModel3D { Geometry = mesh, Transform = new TranslateTransform3D(-2, 0, 0)});
            myModel.Children.Add(new GeometryModel3D { Geometry = mesh, Transform = new TranslateTransform3D(2, 0, 0)});
    
            System.Windows.Media.Media3D.Material mat = MaterialHelper.CreateMaterial(new SolidColorBrush(Color.FromRgb(255, 255, 255)));
    
            foreach (System.Windows.Media.Media3D.GeometryModel3D geometryModel in myModel.Children)
            {
                geometryModel.Material = mat;
                geometryModel.BackMaterial = mat;
            }
    
            visualModel.Content = myModel;
        }
    
        private double angle = 0;
    }
    

    使用这些参数,我的旋转非常顺利,但您必须在您的应用程序上测试/调整它。

    【讨论】:

    • 你是英雄!谢谢你。这会让我继续前进,旋转足够平滑!
    • 我很高兴有帮助:)
    猜你喜欢
    • 1970-01-01
    • 2013-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-26
    • 1970-01-01
    • 2014-08-18
    相关资源
    最近更新 更多