6

viewport3d に配置したパースペクティブ カメラの位置と方向を XAML で直接設定できました。しかし、マウス入力を使用してカメラを回転させる方法を知りたいです。私はC#言語を好むでしょう。実はマウス入力でカメラを回転させる方法に行き詰まりました。私を助けてください。誰かが私にサンプルコードを与えてくれると助かります....

4

2 に答える 2

3

これらの 2 つのリンクが大いに役立つと思います...

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

ここに画像の説明を入力

以下の拡張メソッドは、Euclid 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 に答える