WPF - автоматическое вращение Helix Toolkit - PullRequest
1 голос
/ 13 июля 2020

Я исследовал это на прошлой неделе - 2 недели, и я не смог найти решение. Я загружаю 3D-модель из файла STL и пытаюсь автоматически повернуть 3D-модель вокруг 1 оси. Идея могла бы быть чем-то вроде медленной анимации, которая отображает вид на 360 градусов вокруг оси Y модели.

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();
    }

Это не сработало ... Ничего не изменилось ?

Спасибо!

1 Ответ

1 голос
/ 18 июля 2020

Я не уверен, правильно ли я понял, что вы пытаетесь выполнить sh, поэтому дайте мне знать, если я неправильно понял: в показанном вами коде вы загружаете несколько GeometryModel3D, поэтому вы пытаетесь заставить их все вращаться или просто one?

Один из способов заставить его вращаться - использовать свойство Transform в GeometryModel3D.

Вам нужно будет настроить DispatcherTimer и обновлять угол поворота для каждого тика:

Я сделал пример на основе того, что вы предоставили, где я вращаю одну 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;
}

На моем конце вращение было довольно плавным с этими параметрами, но вам придется протестировать / адаптировать это в вашем заявлении.

...