title: Matrix transformations to recreate camera "Look At" functionality
body: <p><strong>Summary:</strong></p>
  
  <p>I'm given a series of points in 3D space, and I want to analyze them from any viewing angle.  I'm trying to figure out how to reproduce the "Look At" functionality of OpenGL in WPF.  I want the mouse move X,Y to manipulate the Phi and Theta Spherical Coordinates (respectively) of the camera so that I as I move my mouse, the camera appears to orbit around the center of mass (generally the origin) of the point cloud, which will represent the target of the Look At</p>
  
  <p><strong>What I've done:</strong></p>
  
  <p>I have made the following code, but so far it isn't doing what I want:</p>
  
  <pre><code>    internal static Matrix3D CalculateLookAt(Vector3D eye, Vector3D at = new Vector3D(), Vector3D up = new Vector3D())
      {
          if (Math.Abs(up.Length - 0.0) &lt; 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
              );
      }
  </code></pre>
  
  <p>I got the algorithm from this link: <a href="http://msdn.microsoft.com/en-us/library/bb205342(VS.85).aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/bb205342(VS.85).aspx</a></p>
  
  <p>I then apply the returned matrix to all of the points using this:</p>
  
  <pre><code>    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)
          );
  </code></pre>
  
  <p>I am calculating the center of all the points as the <code>at</code> vector, and I've been setting my initial <code>eye</code> vector at <code>(center.X,center.Y,center.Z + 100)</code> which is plenty far away from all the points</p>
  
  <p>I then take the mouse move and apply the following code to get the Spherical Coordinates and put that into the <code>CalculateLookAt</code> function:</p>
  
  <pre><code>        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
  </code></pre>
  
  <p><strong>Conclusion:</strong></p>
  
  <p>This does not make the camera orbit around the points.  So either my understanding of how to use the Look At function is off, or my math is incorrect.</p>
  
  <p>Any help would be very much appreciated.</p>