void motionCallback(int x, int y)
{
  if (selectedView == FRONT)
  {
    controlPoints[selectedPoint[0]][selectedPoint[1]][0] = ToLocalX(x);
    controlPoints[selectedPoint[0]][selectedPoint[1]][1] = ToLocalY(y - height/2);
  }
  else if (selectedView == UP)
  {
    controlPoints[selectedPoint[0]][selectedPoint[1]][0] = ToLocalX(x);
    controlPoints[selectedPoint[0]][selectedPoint[1]][2] = -ToLocalY(y);
  }
  else if (selectedView == LEFT)
  {
    controlPoints[selectedPoint[0]][selectedPoint[1]][2] = -ToLocalX(x - width/2);
    controlPoints[selectedPoint[0]][selectedPoint[1]][1] = ToLocalY(y - height/2);
  }
  else if (selectedView == ROTATE)
  {
    Vector3d lastP = getMousePoint(lastX, lastY, width / 2.0f, height / 2.0f, radius);
    Vector3d currentP = getMousePoint(x - width / 2.0f, y, width / 2.0f, height / 2.0f, radius);

    if (mouseButton == GLUT_LEFT_BUTTON)
    {
      Vector3d rotateVector;
      rotateVector.cross(currentP, lastP);
      double angle = -currentP.angle(lastP) * 2;
      rotateVector = unProjectToEye(rotateVector, eye, center, upVector);

      Vector3d dEye;
      dEye.sub(center, eye);
      dEye = rotate(dEye, rotateVector, -angle);
      upVector = rotate(upVector, rotateVector, -angle);
      eye.sub(center, dEye);
    }
    else if (mouseButton == GLUT_RIGHT_BUTTON) {
      Vector3d dEye;
      dEye.sub(center, eye);
      double offset = 0.025;
      if ((y - lastY) < 0) {
        dEye.scale(1 - offset);
      }
      else {
        dEye.scale(1 + offset);
      }
      eye.sub(center, dEye);
    }
    else if (mouseButton == GLUT_MIDDLE_BUTTON) {
      double dx = x - width / 2.0f - lastX;
      double dy = y - lastY;
      if (dx != 0 || dy != 0)
      {
        Vector3d moveVector(dx, dy, 0);
        moveVector = unProjectToEye(moveVector, eye, center, upVector);
        moveVector.normalize();
        double eyeDistance = Vector3d(eye).distance(Vector3d(center));
        moveVector.scale(std::sqrt(dx*dx + dy*dy) / 1000 * eyeDistance);
        center.add(moveVector);
        eye.add(moveVector);
      }
    }
    lastX = x - width / 2;
    lastY = y;
  }

  EvaluateSurface();
  glutPostRedisplay();
}
void DrawSurface()
{
  for (int i = 0; i <= LOD; i++)
    for (int j = 0; j <= LOD; j++)
    {
      // calculating reflecting vector
      Vector3d mapped;
      mapped.sub(center, eye);
      Vector3d n = Vector3d(surfaceNormals[i][j][0], surfaceNormals[i][j][1], surfaceNormals[i][j][2]);
      n.scale(-2 * n.dot(mapped));
      mapped.add(n);
      mapped.normalize();

      if (mapped.z >= 0) {
        float parabolic_x = ((mapped.x / (2 * (1 + mapped.z))) + 0.5) / 2;
        float parabolic_y = (-mapped.y / (2 * (1 + mapped.z))) + 0.5;
        texCoords[i][j][0] = parabolic_x;
        texCoords[i][j][1] = parabolic_y;
      } else {
        float parabolic_x = ((mapped.x / (2 * (1 - mapped.z))) + 0.5) / 2 + 0.5;
        float parabolic_y = (-mapped.y / (2 * (1 - mapped.z))) + 0.5;
        texCoords[i][j][0] = parabolic_x;
        texCoords[i][j][1] = parabolic_y;
      }

      // double sum = sqrt(mapped.x*mapped.x + mapped.y*mapped.y + pow(mapped.z+1,2));
      // texCoords[i][j][0] = (mapped.x/sum + 1) / 2;
      // texCoords[i][j][1] = (-mapped.y/sum + 1) / 2;
      // float padding_y = 1/3.0;
      // float padding_x = 1/4.0;
      // if (mapped.x >= std::abs(mapped.y) && mapped.x >= std::abs(mapped.z)) { // right
      //   texCoords[i][j][0] = (-mapped.z / mapped.x + 1) / 2 / 4 + padding_x * 2;
      //   texCoords[i][j][1] = (-mapped.y / mapped.x + 1) / 2 / 3 + padding_y;
      // } else if (mapped.y >= std::abs(mapped.x) && mapped.y >= std::abs(mapped.z)) { // top
      //   texCoords[i][j][0] = (mapped.x / mapped.y + 1) / 2 / 4 + padding_x;
      //   texCoords[i][j][1] = (mapped.z / mapped.y + 1) / 2 / 3;
      // } else if (mapped.z >= std::abs(mapped.x) && mapped.z >= std::abs(mapped.y)) { // front
      //   texCoords[i][j][0] = (mapped.x / mapped.z + 1) / 2 / 4 + padding_x;
      //   texCoords[i][j][1] = (-mapped.y / mapped.z + 1) / 2 / 3 + padding_y;
      // } else if (mapped.x <= -std::abs(mapped.y) && mapped.x <= -std::abs(mapped.z)) { // left
      //   texCoords[i][j][0] = (-mapped.z / mapped.x + 1) / 2 / 4;
      //   texCoords[i][j][1] = (mapped.y / mapped.x + 1) / 2 / 3 + padding_y;
      // } else if (mapped.y <= -std::abs(mapped.x) && mapped.y <= -std::abs(mapped.z)) { // bottom
      //   texCoords[i][j][0] = (-mapped.x / mapped.y + 1) / 2 / 4 + padding_x;
      //   texCoords[i][j][1] = (mapped.z / mapped.y + 1) / 2 / 3 + padding_y * 2;
      // } else if (mapped.z <= -std::abs(mapped.x) && mapped.z <= -std::abs(mapped.y)) { // back
      //   texCoords[i][j][0] = (mapped.x / mapped.z + 1) / 2 / 4 + padding_x * 3;
      //   texCoords[i][j][1] = (mapped.y / mapped.z + 1) / 2 / 3 + padding_y;
      // }
    }

  glEnable(GL_TEXTURE_2D);
  for (int i = 0; i < LOD; i++)
  {
    glBegin(GL_QUAD_STRIP);
    for (int j = 0; j <= LOD; j++)
    {
      glTexCoord2dv(texCoords[i][j]);
      glVertex3dv(surfacePoints[i][j]);
      glTexCoord2dv(texCoords[i+1][j]);
      glVertex3dv(surfacePoints[i+1][j]);
    }
    glEnd();
  }
  glDisable(GL_TEXTURE_2D);
}