Резюме:
Мне дан ряд точек в трехмерном пространстве, и я хочу проанализировать их с любого угла обзора. Я пытаюсь выяснить, как воспроизвести функциональность Open Look в OpenFL в WPF. Я хочу, чтобы движение мышью X, Y управляло сферическими координатами Phi и Theta (соответственно) камеры, чтобы при перемещении мыши камера вращалась вокруг центра масс (обычно источника) облака точек. , который будет представлять цель взгляда на
Что я сделал:
Я сделал следующий код, но пока он не выполняет то, что я хочу:
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
Вывод:
Это не заставляет камеру вращаться вокруг точек. Так что либо мое понимание того, как использовать функцию «Смотреть на», отключено, либо моя математика неверна.
Любая помощь будет принята с благодарностью.