我能够直接在 XAML 中设置放置在 viewport3d 中的透视相机的位置和方向。但我想知道如何使用鼠标输入旋转相机。我更喜欢 C# 语言。我实际上被困在如何使用鼠标输入旋转相机的问题上。请帮我。如果有人给我一个示例代码会很有帮助....
问问题
15907 次
2 回答
3
我认为这两个链接可以帮助你很多......
在 WPF 中为 3D 相机的位置设置动画 (还有一个示例项目可以尝试!)
我同意 XNA 可能是 3D 情况的最佳解决方案,但原生 3D 支持和硬件加速渲染也是 WPF 和 XAML 的绝佳功能!
如您所见,用于 XAML 的 3D 相机Viewport3D
非常适合应用程序,也使用绑定:
<Viewport3D.Camera>
<PerspectiveCamera x:Name="camera"
UpDirection="0,0,1"
LookDirection="{Binding RelativeSource={RelativeSource Self}, Path=Position, Converter={StaticResource lookBackConverter}}"
Position="0,0,0" />
</Viewport3D.Camera>
IValueConverter
...以及让相机移动的通常实现:
public class LookBackConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return new Point3D(0,0,0) - (Point3D)value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
于 2012-08-28T19:09:23.557 回答
0
以下扩展方法实现了投影相机在任何方向和旋转到欧几里得 3D 空间的自由飞行。
using System.Windows.Input;
using System.Windows.Media.Media3D;
using static System.Windows.Input.Key;
using static System.Windows.Input.ModifierKeys;
public static class ProjectionCameraExtensions
{
public static TCamera Move<TCamera>(this TCamera camera, Vector3D axis, double step)
where TCamera : ProjectionCamera
{
camera.Position += axis * step;
return camera;
}
public static TCamera Rotate<TCamera>(this TCamera camera, Vector3D axis, double angle)
where TCamera : ProjectionCamera
{
Matrix3D matrix3D = new();
matrix3D.RotateAt(new(axis, angle), camera.Position);
camera.LookDirection *= matrix3D;
return camera;
}
public static Vector3D GetYawAxis(this ProjectionCamera camera) => camera.UpDirection;
public static Vector3D GetRollAxis(this ProjectionCamera camera) => camera.LookDirection;
public static Vector3D GetPitchAxis(this ProjectionCamera camera) => Vector3D.CrossProduct(camera.UpDirection, camera.LookDirection);
public static PerspectiveCamera MoveBy(this PerspectiveCamera camera, Key key) => camera.MoveBy(key, camera.FieldOfView / 180d);
public static PerspectiveCamera RotateBy(this PerspectiveCamera camera, Key key) => camera.RotateBy(key, camera.FieldOfView / 45d);
public static TCamera MoveBy<TCamera>(this TCamera camera, Key key, double step) where TCamera : ProjectionCamera => key switch
{
W => camera.Move(Keyboard.Modifiers.HasFlag(Shift) ? camera.GetYawAxis() : camera.GetRollAxis(), +step),
S => camera.Move(Keyboard.Modifiers.HasFlag(Shift) ? camera.GetYawAxis() : camera.GetRollAxis(), -step),
A => camera.Move(camera.GetPitchAxis(), +step),
D => camera.Move(camera.GetPitchAxis(), -step),
_ => camera
};
public static TCamera RotateBy<TCamera>(this TCamera camera, Key key, double angle) where TCamera : ProjectionCamera => key switch
{
Left => camera.Rotate(camera.GetYawAxis(), +angle),
Right => camera.Rotate(camera.GetYawAxis(), -angle),
Down => camera.Rotate(camera.GetPitchAxis(), +angle),
Up => camera.Rotate(camera.GetPitchAxis(), -angle),
_ => camera
};
}
键盘和鼠标输入的处理程序
private void Window_PreviewKeyDown(object sender, KeyEventArgs e) =>
Camera.MoveBy(e.Key).RotateBy(e.Key);
Point from;
private void Window_PreviewMouseMove(object sender, MouseEventArgs e)
{
var till = e.GetPosition(sender as IInputElement);
double dx = till.X - from.X;
double dy = till.Y - from.Y;
from = till;
var distance = dx * dx + dy * dy;
if (distance <= 0)
return;
if (e.MouseDevice.LeftButton is MouseButtonState.Pressed)
{
var angle = (distance / Camera.FieldOfView) % 45;
Camera.Rotate(new(dy, -dx, 0d), angle);
}
}
于 2022-02-17T14:32:19.690 回答