/*
    QGL Camera
    Ivan Pelipenko peri4ko@yandex.ru

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "gltypes.h"
#include "qglview.h"


Camera::Camera() {
	type_       = glCamera;
	fov_        = 60.;
	roll_       = 0.;
	depth_start = 0.1f;
	mirror_x = mirror_y = false;
}


QMatrix4x4 Camera::offsetMatrix() const {
	QMatrix4x4 ret;
	ret.translate(parent_ ? -offset_ : -aim());
	return ret;
}


void Camera::assign(const Camera & c) {
	trans       = c.trans;
	aim_dist    = c.aim_dist;
	fov_        = c.fov_;
	mirror_x    = c.mirror_x;
	mirror_y    = c.mirror_y;
	depth_start = c.depth_start;
	buildTransform();
}


ObjectBase * Camera::clone(bool withChildren) {
	Camera * o = new Camera(*this);
	o->is_init = false;
	o->name_   = name_;
	o->scene_  = nullptr;
	o->children_.clear();
	if (withChildren) {
		for (int i = 0; i < children_.size(); ++i)
			o->addChild(children_[i]->clone(withChildren));
	}
	o->trans       = trans;
	o->aim_dist    = aim_dist;
	o->fov_        = fov_;
	o->roll_       = roll_;
	o->mirror_x    = mirror_x;
	o->mirror_y    = mirror_y;
	o->depth_start = depth_start;
	o->meta        = meta;
	return o;
}


QMatrix4x4 Camera::viewMatrix() const {
	QMatrix4x4 ret;
	// qDebug() << pos() << aim();
	ret.translate(0., 0., -distance());
	ret.rotate(-roll_, 0., 0., 1.);
	ret *= trans.matrixRotateScale().inverted();
	if (parent_) {
		QMatrix4x4 pmat = parent_->worldTransform();
		offset_         = pmat.column(3).toVector3D();
		pmat(0, 3) = pmat(1, 3) = pmat(2, 3) = 0.;
		pmat.translate(aim());
		ret *= pmat.inverted();
	}
	return ret;
}


QMatrix4x4 Camera::projectionMatrix(double aspect) const {
	return glMatrixPerspective(fov_, aspect, depth_start);
}
