Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

file 83 lines (63 sloc) 2.309 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
#include "vgl_arcballcamera.h"

#include "vgl_funcs.h"
#include "vgl_matrix4.h"
#include "vgl_quaternion.h"
#include "vgl_ray3.h"

namespace vgl {


//
// ArcballCamera methods
//

ArcballCamera::ArcballCamera(const Vec3f& pos,
                             const Vec3f& target,
                             const Vec3f& up,
                             float left,
                             float right,
                             float bottom,
                             float top,
                             float aperture,
                             unsigned int pixelWidth,
                             unsigned int pixelHeight) :
  BaseCamera(pos, target, up, left, right, bottom, top,
      aperture, pixelWidth, pixelHeight)
{
}



void ArcballCamera::roll(int prevX, int prevY, int currX, int currY)
{
  if (prevX == currX && prevY == currY)
    return;

  prevY = (_pixelHeight - 1) - prevY;
  currY = (_pixelHeight - 1) - currY;

  Vec3f prev = unproject(prevX, prevY);
  Vec3f curr = unproject(currX, currY);

  const float kSphereRadius = 1;

  Ray3f prevRay(_pos, prev - _pos);
  Ray3f currRay(_pos, curr - _pos);

  Vec3f prevHit, currHit;
  bool didPrevHit = intersectRaySphere(prevRay, _target, kSphereRadius, prevHit);
  bool didCurrHit = intersectRaySphere(currRay, _target, kSphereRadius, currHit);
  if ( didPrevHit && didCurrHit ) {
    float c = dot(norm(currHit), norm(prevHit));
    // Need to use the inverse rotation, since we're rotating the camera
    // rather than the scene.
    Quaternionf q = inverse(rotation(
        cross(prevHit - _target, currHit - _target), std::acos(c)));
    _pos = rotate(q, _pos - _target) + _target;
  }
}


void ArcballCamera::move(int prevX, int prevY, int currX, int currY)
{
  if (prevX == currX && prevY == currY)
    return;

  // The viewer gives us y coordinates which increase downwards. We want ones
  // which increase upwards, so we need to invert them.
  prevY = (_pixelHeight - 1) - prevY;
  currY = (_pixelHeight - 1) - currY;

  Vec3f prev = unproject(prevX, prevY, 0.6);
  Vec3f curr = unproject(currX, currY, 0.6);
  Vec3f delta = curr - prev;

  // Because we're moving the camera not the scene, we need to do the
  // opposite movement.
  _pos = (_pos - delta);
  _target = (_target - delta);
}


} // namespace vgl
Something went wrong with that request. Please try again.