WPF - Helix 工具包自动旋转
WPF - Helix Toolkit Auto Rotation
上周我一直在研究这个 - 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();
}
这没有用...没有任何改变?
谢谢!
我不确定我是否正确理解了你想要完成的事情,所以如果我误解了请告诉我:
在您展示的代码中,您正在加载多个 GeometryModel3D,因此您是想让它们都旋转还是只加载一个?
使它旋转的一种方法是通过 GeometryModel3D 的变换 属性。
您必须设置一个 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;
}
我使用这些参数进行旋转非常顺利,但您必须在您的应用程序中test/adapt它。
上周我一直在研究这个 - 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();
}
这没有用...没有任何改变?
谢谢!
我不确定我是否正确理解了你想要完成的事情,所以如果我误解了请告诉我: 在您展示的代码中,您正在加载多个 GeometryModel3D,因此您是想让它们都旋转还是只加载一个?
使它旋转的一种方法是通过 GeometryModel3D 的变换 属性。
您必须设置一个 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;
}
我使用这些参数进行旋转非常顺利,但您必须在您的应用程序中test/adapt它。