module Rabbit::TrackBall
Constants
- RENORM_COUNT
Given two rotations, e2 and e2, expressed as quaternion rotations, figure out the equivalent single rotation and stuff it into dest.
This routine also normalizes the result every
RENORM_COUNT
times it is called, to keep error from creeping in.NOTE: This routine is written so that q1 or q2 may be the same as dest (or each other).
- SIZE
This size should really be based on the distance from the center of rotation to the point on the object underneath the mouse. That point would then track the mouse as closely as possible. This is a simple example, though, so that is left as an Exercise for the Programmer.
Public Instance Methods
add_quats(q1, q2)
click to toggle source
# File lib/rabbit/trackball.rb, line 210 def add_quats(q1, q2) t1 = q1.vscale(q2[3]) t2 = q2.vscale(q1[3]) t3 = q2.vcross(q1) tf = t1.vadd(t2) tf = t3.vadd(tf) tf[3] = q1[3] * q2[3] - q1.vdot(q2, 3) @@quats_count += 1 ret = tf if (@@quats_count > RENORM_COUNT) @@quats_count = 0 ret = tf.normalize_quat end ret end
tb_project_to_sphere(r, x, y)
click to toggle source
Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet if we are away from the center of the sphere.
# File lib/rabbit/trackball.rb, line 185 def tb_project_to_sphere(r, x, y) d = Math.sqrt(x * x + y * y) if (d < r * 0.70710678118654752440) # Inside sphere z = Math.sqrt(r * r - d * d) else # On hyperbola t = r / 1.41421356237309504880 z = t * t / d end z end
trackball(p1x, p1y, p2x, p2y)
click to toggle source
# File lib/rabbit/trackball.rb, line 156 def trackball(p1x, p1y, p2x, p2y) if (p1x == p2x && p1y == p2y) return Vector.new([0.0, 0.0, 0.0, 1.0]) end # First, figure out z-coordinates for projection of P1 and P2 to # deformed sphere p1 = Vector.new([p1x, p1y, tb_project_to_sphere(SIZE, p1x, p1y)]) p2 = Vector.new([p2x, p2y, tb_project_to_sphere(SIZE, p2x, p2y)]) # Now, we want the cross product of P1 and P2 a = p2.vcross(p1) # Figure out how much to rotate around that axis. d = p1.vsub(p2) t = d.vlength / (2.0 * SIZE) # Avoid problems with out-of-control values... t = 1.0 if (t > 1.0) t = -1.0 if (t < -1.0) phi = 2.0 * Math.asin(t) a.axis_to_quat(phi) end