c# - 重建相机 "Look At"功能的矩阵变换

标签 c# wpf math graphics

总结:

我在 3D 空间中得到了一系列点,我想从任何视角分析它们。我试图弄清楚如何在 WPF 中重现 OpenGL 的“查看”功能。我希望鼠标移动 X、Y 来操纵相机的 Phi 和 Theta 球坐标(分别),这样当我移动鼠标时,相机似乎绕着点云的质心(通常是原点)运行, 这将代表 Look At 的目标

我做了什么:

我已经编写了以下代码,但到目前为止它并没有按照我的要求进行:

    internal static Matrix3D CalculateLookAt(Vector3D eye, Vector3D at = new Vector3D(), Vector3D up = new Vector3D())
    {
        if (Math.Abs(up.Length - 0.0) < double.Epsilon) up = new Vector3D(0, 1, 0);
        var zaxis = (at - eye);
        zaxis.Normalize();
        var xaxis = Vector3D.CrossProduct(up, zaxis);
        xaxis.Normalize();
        var yaxis = Vector3D.CrossProduct(zaxis, xaxis);

        return new Matrix3D(
            xaxis.X, yaxis.X, zaxis.X, 0,
            xaxis.Y, yaxis.Y, zaxis.Y, 0,
            xaxis.Z, yaxis.Z, zaxis.Z, 0,
            Vector3D.DotProduct(xaxis, -eye), Vector3D.DotProduct(yaxis, -eye), Vector3D.DotProduct(zaxis, -eye), 1
            );
    }

我从这个链接得到了算法:http://msdn.microsoft.com/en-us/library/bb205342(VS.85).aspx

然后我使用这个将返回的矩阵应用到所有的点:

    var vector = new Vector3D(p.X, p.Y, p.Z);

    var projection = Vector3D.Multiply(vector, _camera);    // _camera is the LookAt Matrix

    if (double.IsNaN(projection.X)) projection.X = 0;
    if (double.IsNaN(projection.Y)) projection.Y = 0;
    if (double.IsNaN(projection.Z)) projection.Z = 0;

    return new Point(
        (dispCanvas.ActualWidth * projection.X / 320),
        (dispCanvas.ActualHeight * projection.Y / 240)
        );

我正在计算所有点的中心作为 at 向量,并且我一直在将我的初始 eye 向量设置在 (center.X, center.Y,center.Z + 100) 离所有的点都很远

然后我移动鼠标并应用以下代码来获取球坐标并将其放入 CalculateLookAt 函数中:

        var center = GetCenter(_points);
        var pos = e.GetPosition(Canvas4);   //e is of type MouseButtonEventArgs
        var delta = _previousPoint - pos;

        double r = 100;
        double theta = delta.Y * Math.PI / 180;
        double phi = delta.X * Math.PI / 180;

        var x = r * Math.Sin(theta) * Math.Cos(phi);
        var y = r * Math.Cos(theta);
        var z = -r * Math.Sin(theta) * Math.Sin(phi);

        _camera = MathHelper.CalculateLookAt(new Vector3D(center.X * x, center.Y * y, center.Z * z), new Vector3D(center.X, center.Y, center.Z));

        UpdateCanvas();   // Redraws the points on the canvas using the new _camera values

结论:

这不会使相机围绕点旋转。因此,要么我对如何使用 Look At 函数的理解不正确,要么我的数学不正确。

非常感谢任何帮助。

最佳答案

Vector3D不会在仿射空间中变换。 Vector3D不会平移,因为它是一个向量,不存在于仿射空间(即具有平移分量的 3D 向量空间)中,仅存在于向量空间中。你需要一个Point3D :

var m = new Matrix3D(
                1, 0, 0, 0, 
                0, 1, 0, 0, 
                0, 0, 1, 0, 
                10, 10, 10, 1);

var v = new Point3D(1, 1, 1);
var r = Point3D.Multiply(v, m); // 11,11,11

请注意,您假定的答案也不正确,应该是 10 + 1对于每个组件,因为您的矢量是 [1,1,1] .

关于c# - 重建相机 "Look At"功能的矩阵变换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9179689/

相关文章:

c# - 如何使用多个条件 + OR 进行 linq 连接

wpf - 为特定控件设置 WPF 数据上下文

sql - 需要 SQL Server 查询来求解三阶多项式回归

C# 如何在运行时使用 XElement 使用 Dynamic Linq 创建自定义(动态)类

c# - 如何在 Cake 任务的 `WithCriteria` 中使用全局变量?

c# - 如何为此 PCL 库制作 NuGet 包

c# - 如何使用 DataContext 绑定(bind)到 List<T>?

c# - 将 WPF 窗口附加到另一个进程的窗口

java - 牛顿拉夫森法 Java

math - 具有一定数量的字符和长度,可以有多少个唯一的字符串?