def _trackball_point(self, point): n_point = self._nearplane_point(point) v = n_point - self.prev_pos v /= np.sqrt(v.dot(v)) l = self.prev_ref - self.prev_pos ll = l.dot(l) t = l.dot(v) dd = max(0.0, ll - t * t) d = np.sqrt(dd) r = min(self.radius, np.sqrt(l.dot(l)) - self.near) rr = r * r len_l = np.sqrt(ll) unit_l = l / len_l axis = np.cross(unit_l, v) if dd > rr: sin = r / len_l s = np.sqrt(ll - rr) cos = s / len_l q = qt.from_axis_and_angle(axis, sin, cos) p = self.prev_pos + s * qt.rotate(q, unit_l) else: # intersects sin = d / len_l cos = t / len_l q = qt.from_axis_and_angle(axis, sin, cos) dt = np.sqrt(rr - dd) t -= dt p = self.prev_pos + t * qt.rotate(q, unit_l) return p
def rotate(self, target): s = self.t_source - self.prev_ref e = self._trackball_point(target) - self.prev_ref q = ~qt.from_two_vectors(s, e) v = self.prev_pos - self.prev_ref self.pos = self.prev_ref + qt.rotate(q, v) self.up = qt.rotate(q, self.prev_up) self._look_at()
def rotate(self, rot_about, theta): """rot_about = unit vector to rotate about theta = radians""" r = quaternion.rotate([self.vec[0][0], self.vec[1][0], self.vec[2][0]], [rot_about[0], rot_about[1], rot_about[2]], theta) return Position(r[0], r[1], r[2])
def roll(self, phi): """Roll camera, positive phi right.""" self.up = quat.rotate(self.up, self.forward, phi).normalize()
def yaw(self, phi): """Yaw camera, positive phi right.""" self.forward = quat.rotate(self.forward, self.up, -phi).normalize()
def pitch(self, phi): """Pitch camera, positive phi down.""" left = (self.up @ self.forward).normalize() self.forward = quat.rotate(self.forward, left, phi).normalize() self.up = quat.rotate(self.up, left, phi).normalize()
def rotateZ(self, theta): r = quaternion.rotate([self.vec[0][0], self.vec[1][0], self.vec[2][0]], [0, 0, 1], theta) return Position(r[0], r[1], r[2])
def rotateZ(self, theta): p = quaternion.rotate(self.pos, [0, 0, 1], theta) uv = quaternion.rotate(self.upvec, [0, 0, 1], theta) return Position.VCam(p, uv)