teaching machines

CS 455 Lecture 10 – Virtual Trackball

February 26, 2015 by . Filed under cs455, lectures, spring 2015.

Agenda

TODO

Code

Pseudocode for mapping a pixel position onto a virtual unit sphere:

project_pixel_onto_ball(x_pixels, y_pixels) do
  v_pixels = vec4(x_pixels, y_pixel, 0, 1)

  // The pixel is in [0, width] x [0, height]. We want to overlay a
  // virtual unit sphere in this window, whose coordinates are
  // in [-1, 1] x [-1, 1]. We first scale the pixel location into 
  // [0, 2] x [0, 2]. Then we shift it into [-1, 1] x [-1, 1].
  v_ball = translate by (-1, -1, 0) * scale by (2 / width, 2 / height, 1) * v_pixels

  // v_ball.x and v_ball.x tell us the xy-components on this
  // virtual sphere, but we don't yet know the z-component.
  // However, we do know 1 = x^2 + y^2 + z^2. Let's solve for
  // z^2.
  z_squared = 1 - v_ball.x ^ 2 - v_ball.y ^ 2

  // If xy isn't on the unit sphere, but perhaps in a corner, we
  // end up with z_squared < 0. Let's clamp our projection to
  // the sphere.
  if z_squared < 0
    z_squared = 0
  end

  v_ball.z = z_squared ^ 0.5
  normalize v_ball

  return v_ball
end

Now, to implement the trackball:

  1. On left mouse down, persistĀ the mouse location’s projection. Let’s call it fore.
  2. On left mouse drag:
    1. Compute the current mouse location’s projection. Let’s call it aft.
    2. Compute the angle between fore and aft.
    3. If fore and aft more or less coincident, we don’t need to do anything. Otherwise, compute their cross product. This will be our axis of rotation. Rotate about this axis by the angle between them by asking the Matrix4 class for help:
      Matrix4 rotation = Matrix4::GetRotate(theta * 180.0f / 3.14159265358979323846264f, axis);

      Note that this rotation represents just the span between the last mouse event and this one. We want to accumulate this rotation with all the previous rotations. We can do so combining this matrix with the earlier transformations. Suppose xform is our accumulated transformation, then:

      xform = rotation * xform;

      The order is important. The older rotations in xform get applied first, with the new rotation applied last. UploadĀ xform to the vertex shader. Also note that before any mouse events happen, xform should be the identity matrix.

    4. Make the aft vector be the fore vector for the next drag event.

You might notice the rotation is flipped. Try inverting the near and far parameters on your orthographic projection. The convention is to look down the negative z-axis.

Haiku

on scaffolding
New things in my brain
To get to them, I need roads
Metaphorical ones