/* Universidade Federal Fluminense
 * Programa de Pós-Graduação em Computação
 *
 * Tópicos Avançados em Computação Visual e Interfaces II (Técnicas Avançadas de Rendering)
 * Professor: Leandro Augusto Frata Fernandes
 *
 * Version: 2012.05.05-001
 */

#include "object.h"

Object::Object() {
	setPosition(coord3f(0.0f, 0.0f, 0.0f), coord3f(0.0f, 0.0f, 1.0f), coord3f(0.0f, 1.0f, 0.0f));
}

Object::Object(const coord3f& location_, const coord3f& forwardDirection_, const coord3f& upDirection_) {
	setPosition(location_, forwardDirection_, upDirection_);
}

coord3f Object::getForwardDirection() const {
	return coord3f(m_modelMatrix[2], m_modelMatrix[6], m_modelMatrix[10]);
}

coord3f Object::getLocation() const {
	return coord3f(m_modelMatrix[12], m_modelMatrix[13], m_modelMatrix[14]);
}

coord3f Object::getRightDirection() const {
	return coord3f(m_modelMatrix[0], m_modelMatrix[4], m_modelMatrix[8]);
}

coord3f Object::getUpDirection() const {
	return coord3f(m_modelMatrix[1], m_modelMatrix[5], m_modelMatrix[9]);
}

void Object::rotate(const coord3f& axis, const GLfloat& angleInRadians) {
	m_modelMatrix = multiply(m_modelMatrix, rotation(axis, angleInRadians));
}

void Object::scale(const coord3f& factor) {
	m_modelMatrix = multiply(m_modelMatrix, scaling(factor));
}

void Object::setPosition(const coord3f& location_, const coord3f& forwardDirection_, const coord3f& upDirection_) {
	const coord3f& unitForward = normalize(forwardDirection_);
	const coord3f& unitUp = normalize(upDirection_);
	const coord3f& unitRight = normalize(cross(upDirection_, forwardDirection_));

	m_modelMatrix[ 0] = unitRight.x;
	m_modelMatrix[ 1] = unitUp.x;
	m_modelMatrix[ 2] = unitForward.x;
	m_modelMatrix[ 3] = 0.0f;

	m_modelMatrix[ 4] = unitRight.y;
	m_modelMatrix[ 5] = unitUp.y;
	m_modelMatrix[ 6] = unitForward.y;
	m_modelMatrix[ 7] = 0.0f;

	m_modelMatrix[ 8] = unitRight.z;
	m_modelMatrix[ 9] = unitUp.z;
	m_modelMatrix[10] = unitForward.z;
	m_modelMatrix[11] = 0.0f;

	m_modelMatrix[12] = dot(unitRight, location_);
	m_modelMatrix[13] = dot(unitUp, location_);
	m_modelMatrix[14] = dot(unitForward, location_);
	m_modelMatrix[15] = 1.0f;
}

void Object::translate(const coord3f& delta) {
	m_modelMatrix = multiply(m_modelMatrix, translation(delta));
}
