
#include "camera.h"
using namespace std;

Camera::Camera()
{
    EyeDistanceInCm = 75; // cm
}

void Camera::TurnRight(double angle)
{
    this->angle -= angle * M_PI / 180;
}

void Camera::TurnLeft(double angle)
{
    this->angle += angle * M_PI / 180;
}

void Camera::PanUp(double angle)
{
    slope -= angle * M_PI / 180;
}

void Camera::PanDown(double angle)
{
    slope += angle * M_PI / 180;
}

void Camera::MoveForward(double distance)
{
    position.z += distance * cos(angle);
    position.x -= distance * sin(angle);
}

void Camera::MoveBackward(double distance)
{
    position.z -= distance * cos(angle);
    position.x += distance * sin(angle);
}

void Camera::StrafeLeft(double distance)
{
    position.z -= distance * sin(angle);
    position.x -= distance * cos(angle);
}

void Camera::StrafeRight(double distance)
{
    position.z += distance * sin(angle);
    position.x += distance * cos(angle);
}

void Camera::MoveUp(double distance)
{
    position.y -= distance;
}

void Camera::MoveDown(double distance)
{
    position.y += distance;
}

void Camera::ZoomIn(double distance)
{
    position.z += distance * cos(angle);
    position.x -= distance * sin(angle);
    position.y += distance * tan(slope);
}

void Camera::ZoomOut(double distance)
{
    position.z -= distance * cos(angle);
    position.x += distance * sin(angle);
    position.y -= distance * tan(slope);
}



void Camera::Render(Scene* scene, QPainter* painter)
{
    double ResolutionDPI = 96;
    double CmPerInch = 2.54;


    double matrixY[3][3];
    matrixY[0][0] = cos(angle);  matrixY[0][1] = 0; matrixY[0][2] = sin(angle);
    matrixY[1][0] = 0;           matrixY[1][1] = 1; matrixY[1][2] = 0;
    matrixY[2][0] = -sin(angle); matrixY[2][1] = 0; matrixY[2][2] = cos(angle);

    double matrixX[3][3];
    matrixX[0][0] = 1; matrixX[0][1] = 0;          matrixX[0][2] = 0;
    matrixX[1][0] = 0; matrixX[1][1] = cos(slope); matrixX[1][2] = -sin(slope);
    matrixX[2][0] = 0; matrixX[2][1] = sin(slope); matrixX[2][2] = cos(slope);


    for(vector<Mesh*>::iterator mesh = scene->meshes.begin(); mesh != scene->meshes.end(); mesh++)
    {
        for(vector<Face*>::iterator face = (*mesh)->faces.begin(); face != (*mesh)->faces.end(); face++)
        {
            for(int i = (*face)->verts.size()-1; i >= 0; --i)
            {
                Point3D a = *(*face)->verts[i];
                a.x -= position.x;
                a.y -= position.y;
                a.z -= position.z;
                a.LinearTransform(matrixY);
                a.LinearTransform(matrixX);

                Point3D b = *(*face)->verts[(i+1) % (*face)->verts.size()];
                b.x -= position.x;
                b.y -= position.y;
                b.z -= position.z;
                b.LinearTransform(matrixY);
                b.LinearTransform(matrixX);

                if(a.z >= 0.0d && b.z >= 0.0d)
                {
                    double ax = a.x * EyeDistanceInCm / (EyeDistanceInCm+a.z) * (ResolutionDPI / CmPerInch) + painter->window().width()/2;
                    double ay = a.y * EyeDistanceInCm / (EyeDistanceInCm+a.z) * (ResolutionDPI / CmPerInch) + painter->window().height()/2;
                    double bx = b.x * EyeDistanceInCm / (EyeDistanceInCm+b.z) * (ResolutionDPI / CmPerInch) + painter->window().width()/2;
                    double by = b.y * EyeDistanceInCm / (EyeDistanceInCm+b.z) * (ResolutionDPI / CmPerInch) + painter->window().height()/2;

                    painter->drawLine((int)ax, (int)ay, (int)bx, (int)by);
                }
            }

        }
    }
}


