private boolean processTouch(int action, MotionEvent e, boolean sensorMode) {
    switch (action) {
      case MotionEvent.ACTION_DOWN:
        if (mCurrentTouchState == TouchState.INIT) {
          mInitX = (int) e.getX();
          mInitY = (int) e.getY();
          if (sensorMode) {
            return true;
          }
          mCurrentTouchState = TouchState.DRAG_ONE;
          mPreviousX1 = e.getX();
          mPreviousY1 = e.getY();
          return true;
        }
      case MotionEvent.ACTION_POINTER_DOWN:
        if (sensorMode) {
          return true;
        }
        if (mCurrentTouchState == TouchState.DRAG_ONE) {
          mCurrentTouchState = TouchState.DRAG_TWO;
          mPointerIndex = e.getActionIndex();
          mPreviousX1 = e.getX();
          mPreviousY1 = e.getY();
          mPreviousX2 = e.getX(mPointerIndex);
          mPreviousY2 = e.getY(mPointerIndex);
          return true;
        }
      case MotionEvent.ACTION_MOVE:
        if (sensorMode) {
          return true;
        }
        if (mCurrentTouchState == TouchState.DRAG_ONE) {
          float currentX = e.getX();
          float currentY = e.getY();
          float deltaX = currentX - mPreviousX1;
          float deltaY = currentY - mPreviousY1;

          float radsPerPixel = mStarMapperRenderer.mFovYRad / mStarMapperRenderer.mScreenHeight;
          changeMapX(-deltaX * radsPerPixel);
          changeMapY(-deltaY * radsPerPixel);

          mStarMapperRenderer.mLookX = mUser.getLookX();
          mStarMapperRenderer.mLookY = mUser.getLookY();
          mStarMapperRenderer.mLookZ = mUser.getLookZ();
          mStarMapperRenderer.mUpX = mUser.getNormalX();
          mStarMapperRenderer.mUpY = mUser.getNormalY();
          mStarMapperRenderer.mUpZ = mUser.getNormalZ();

          mPreviousX1 = currentX;
          mPreviousY1 = currentY;
          return true;
        } else if (mCurrentTouchState == TouchState.DRAG_TWO) {
          float currentX1 = e.getX();
          float currentY1 = e.getY();
          float currentX2 = e.getX(mPointerIndex);
          float currentY2 = e.getY(mPointerIndex);
          float deltaX1 = currentX1 - mPreviousX1;
          float deltaY1 = currentY1 - mPreviousY1;
          float deltaX2 = currentX2 - mPreviousX2;
          float deltaY2 = currentY2 - mPreviousY2;

          float radsPerPixel = mStarMapperRenderer.mFovYRad / mStarMapperRenderer.mScreenHeight;
          changeMapX(-((deltaX1 + deltaX2) / 2) * radsPerPixel);
          changeMapY(-((deltaY1 + deltaY2) / 2) * radsPerPixel);

          float vPreviousX = mPreviousX1 - mPreviousX2;
          float vPreviousY = mPreviousY1 - mPreviousY2;
          float vCurrentX = currentX1 - currentX2;
          float vCurrentY = currentY1 - currentY2;

          /* Need a 'stretch' function here for field of view once zoom is implemented */
          float vectorRatio =
              (float)
                  Math.sqrt(
                      (vCurrentX * vCurrentX + vCurrentY * vCurrentY)
                          / (vPreviousX * vPreviousX + vPreviousY * vPreviousY));
          mStarMapperRenderer.mFovYRad =
              mZoomer.zoomBy(mStarMapperRenderer.mFovYRad, 1.0f / vectorRatio);
          mStarMapperRenderer.mUpdatePerspective = true;

          double anglePrevious = Math.atan2(vPreviousX, vPreviousY);
          double angleCurrent = Math.atan2(vCurrentX, vCurrentY);
          float angleDelta = (float) (anglePrevious - angleCurrent);

          rotate(angleDelta);

          mStarMapperRenderer.mLookX = mUser.getLookX();
          mStarMapperRenderer.mLookY = mUser.getLookY();
          mStarMapperRenderer.mLookZ = mUser.getLookZ();
          mStarMapperRenderer.mUpX = mUser.getNormalX();
          mStarMapperRenderer.mUpY = mUser.getNormalY();
          mStarMapperRenderer.mUpZ = mUser.getNormalZ();

          mPreviousX1 = currentX1;
          mPreviousY1 = currentY1;
          mPreviousX2 = currentX2;
          mPreviousY2 = currentY2;
          return true;
        }
      case MotionEvent.ACTION_UP:
        int last_X = (int) e.getX();
        int last_Y = (int) e.getY();
        int dx = Math.abs(last_X - mInitX);
        int dy = Math.abs(last_Y - mInitY);
        if (dx <= 20 && dy <= 20) {
          for (Label label : mStarMapperRenderer.mLabelManager.LabelSet) {
            int xll = label.screenPos_xll;
            int yll = label.screenPos_yll;
            int xur = label.screenPos_xur;
            int yur = label.screenPos_yur;
            LabelTypeEnum type = label.getType();
            if (label.isOnScreen()
                && xll <= mInitX
                && xur >= mInitX
                && yll <= mInitY
                && yur >= mInitY
                && type != LabelTypeEnum.GRID) {
              String name = label.getText().replaceAll(" ", "_");
              String URL = "http://en.wikipedia.org/wiki/" + name;
              if (type == LabelTypeEnum.CONSTELLATION
                  || type == LabelTypeEnum.STAR
                  || type == LabelTypeEnum.PLANET) {
                URL = URL + "_(" + label.getType().name().toLowerCase() + ")";
              }
              Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(URL));
              startActivity(browserIntent);
              // Toast.makeText(this, label.getText(), Toast.LENGTH_SHORT).show();
            }
          }
        }
        if (sensorMode) {
          return true;
        }
        if (mCurrentTouchState != TouchState.INIT) {
          mCurrentTouchState = TouchState.INIT;
          return true;
        }
      case MotionEvent.ACTION_POINTER_UP:
        if (sensorMode) {
          return true;
        }
        if (mCurrentTouchState == TouchState.DRAG_TWO) {
          mCurrentTouchState = TouchState.INIT;
        }
    }
    return false;
  }
  @Override
  public void onSensorChanged(SensorEvent event) {
    // smoothing code
    for (int i = 0; i < 3; ++i) {
      last[i] = current[i];
      float diff = event.values[i] - last[i];
      float correction = diff * alpha;
      for (int j = 1; j < exponent; ++j) {
        correction *= Math.abs(diff);
      }
      if (correction > Math.abs(diff) || correction < -Math.abs(diff)) {
        correction = diff;
      }
      current[i] = last[i] + correction;
    }

    mNewAccelerationReading.x = -current[0];
    mNewAccelerationReading.y = -current[1];
    mNewAccelerationReading.z = -current[2];

    mUser.setAcceleration(mNewAccelerationReading);

    Matrix3x3 phoneSpaceMatrix = mUser.getLocalNorthAndUpMatrix_PhoneSpace();
    Matrix3x3 celestialSpaceMatrix = mUser.getLocalNorthAndUpMatrix_CelestialSpace();
    Matrix3x3 viewTransform = MathUtils.multiplyMatrices(celestialSpaceMatrix, phoneSpaceMatrix);

    Geocentric lookVector = MathUtils.multiplyGeocentricAndMatrix3x3(viewTransform, Z_DOWN_VECTOR);
    Geocentric upVector = MathUtils.multiplyGeocentricAndMatrix3x3(viewTransform, INIT_UP_VECTOR);

    //		Log.d("AccelerometerModel", "INSIDE ACCELEROMETER SENSORCHANGED");

    //		Log.d("AccelerometerModel", "ps_xx: " + String.valueOf(phoneSpaceMatrix.xx) + " ps_xy: " +
    // String.valueOf(phoneSpaceMatrix.xy) + " ps_xz: " + String.valueOf(phoneSpaceMatrix.xz));
    //		Log.d("AccelerometerModel", "ps_yx: " + String.valueOf(phoneSpaceMatrix.yx) + " ps_yy: " +
    // String.valueOf(phoneSpaceMatrix.yy) + " ps_yz: " + String.valueOf(phoneSpaceMatrix.yz));
    //		Log.d("AccelerometerModel", "ps_zx: " + String.valueOf(phoneSpaceMatrix.zx) + " ps_zy: " +
    // String.valueOf(phoneSpaceMatrix.zy) + " ps_zz: " + String.valueOf(phoneSpaceMatrix.zz));

    //		Log.d("AccelerometerModel", "vt_xx: " + String.valueOf(viewTransform.xx) + " vt_xy: " +
    // String.valueOf(viewTransform.xy) + " vt_xz: " + String.valueOf(viewTransform.xz));
    //		Log.d("AccelerometerModel", "vt_yx: " + String.valueOf(viewTransform.yx) + " vt_yy: " +
    // String.valueOf(viewTransform.yy) + " vt_yz: " + String.valueOf(viewTransform.yz));
    //		Log.d("AccelerometerModel", "vt_zx: " + String.valueOf(viewTransform.zx) + " vt_zy: " +
    // String.valueOf(viewTransform.zy) + " vt_zz: " + String.valueOf(viewTransform.zz));

    //		Log.d("AccelerometerModel", "event.values[0]: " + String.valueOf(event.values[0]) + "
    // event.values[1]: " + String.valueOf(event.values[1] + " event.values[2]: " +
    // String.valueOf(event.values[2])));

    mUser.lookDir = lookVector;
    mUser.lookNormal = upVector;

    mRenderer.mLookX = mUser.getLookX();
    mRenderer.mLookY = mUser.getLookY();
    mRenderer.mLookZ = mUser.getLookZ();
    mRenderer.mUpX = mUser.getNormalX();
    mRenderer.mUpY = mUser.getNormalY();
    mRenderer.mUpZ = mUser.getNormalZ();

    //		Log.d("AccelerometerModel", "lastX: " + String.valueOf(last[0]) + " lastY: " +
    // String.valueOf(last[1]) + " lastZ: " + String.valueOf(last[2]));
    //		Log.d("AccelerometerModel", "currentX: " + String.valueOf(current[0]) + " currentY: " +
    // String.valueOf(current[1]) + " currentZ: " + String.valueOf(current[2]));
    //		Log.d("AccelerometerModel", "mLookX: " + String.valueOf(mUser.getLookX()) + " mLookY: " +
    // String.valueOf(mUser.getLookY()) + " mLookZ: " + String.valueOf(mUser.getLookZ()));
    //		Log.d("AccelerometerModel", "mUpX: " + String.valueOf(mUser.getNormalX()) + " mUpY: " +
    // String.valueOf(mUser.getNormalY()) + " mUpZ: " + String.valueOf(mUser.getNormalZ()));

    // mGLSurfaceView.requestRender();
  }