#include "math/ProjectionMatrix.h" using namespace projection; using namespace gmtl; /** * Constructor. * * Default projection matrix value is : FOV=30.0, * AspectRatio=4/3, Near=0.1, Far=100.0 */ ProjectionMatrix::ProjectionMatrix() { m_fov = 30.0f; m_aspectRatio = 1024.0f / 768.0f; m_near = 0.1f; m_far = 100.0f; m_offaxisX = 0.0f; m_offaxisY = 0.0f; } /** * Destructor. */ ProjectionMatrix::~ProjectionMatrix() { } /** * Copy constructor. * * @param matrix Copy source matrix. */ ProjectionMatrix::ProjectionMatrix(const ProjectionMatrix &matrix) { m_fov = matrix.getFOV(); m_aspectRatio = matrix.getAspectRatio(); m_near = matrix.getNear(); m_far = matrix.getFar(); m_offaxisX = matrix.getOffaxisX(); m_offaxisY = matrix.getOffaxisY(); } /** * Retrieve matrix values for glMultMatrixd(). * * @return Matrix values. */ float* ProjectionMatrix::getMatrix() { // glMultMatrixd(getMatrix()) is same as glFrustum(). float left = (-tanf(Math::deg2Rad(m_fov) / 2.0f * m_aspectRatio) - m_offaxisX) * m_near; float right = ( tanf(Math::deg2Rad(m_fov) / 2.0f * m_aspectRatio) - m_offaxisX) * m_near; float top = ( tanf(Math::deg2Rad(m_fov) / 2.0f) + m_offaxisY) * m_near; float bottom = (-tanf(Math::deg2Rad(m_fov) / 2.0f) + m_offaxisY) * m_near; m_mat[ 0] = (2.0f * m_near) / (right - left); m_mat[ 1] = 0.0f; m_mat[ 2] = 0.0f; m_mat[ 3] = 0.0f; m_mat[ 4] = 0.0f; m_mat[ 5] = (2.0f * m_near) / (top - bottom); m_mat[ 6] = 0.0f; m_mat[ 7] = 0.0f; m_mat[ 8] = (right + left) / (right - left); m_mat[ 9] = (top + bottom) / (top - bottom); m_mat[10] = -(m_far + m_near) / (m_far - m_near); m_mat[11] = -1.0f; m_mat[12] = 0.0f; m_mat[13] = 0.0f; m_mat[14] = -(2.0f * m_far * m_near) / (m_far - m_near); m_mat[15] = 0.0f; return m_mat; } /** * Retrieve four corner vectors. * * @param Four corner vectors. */ void ProjectionMatrix::getCorners(gmtl::Vec3f vecs[4]) const { float left = (-tanf(Math::deg2Rad(m_fov) / 2.0f * m_aspectRatio) + m_offaxisX); float right = ( tanf(Math::deg2Rad(m_fov) / 2.0f * m_aspectRatio) + m_offaxisX); float top = ( tanf(Math::deg2Rad(m_fov) / 2.0f) + m_offaxisY); float bottom = (-tanf(Math::deg2Rad(m_fov) / 2.0f) + m_offaxisY); vecs[0].set(left, 1.0f, top); vecs[1].set(right, 1.0f, top); vecs[2].set(right, 1.0f, bottom); vecs[3].set(left, 1.0f, bottom); normalize(vecs[0]); normalize(vecs[1]); normalize(vecs[2]); normalize(vecs[3]); } /** * Retrieve frustum parameters as 'Frustum left right bottom top near far;'. * * @param numSpaces Number of space characters for indent. * @return Frustum params. */ QString ProjectionMatrix::getParams(int numSpaces) const { QString spc; spc.fill(' ', numSpaces); double left = (-tan(Math::deg2Rad(m_fov) / 2.0 * m_aspectRatio) + m_offaxisX); double right = ( tan(Math::deg2Rad(m_fov) / 2.0 * m_aspectRatio) + m_offaxisX); double top = ( tan(Math::deg2Rad(m_fov) / 2.0) + m_offaxisY); double bottom = (-tan(Math::deg2Rad(m_fov) / 2.0) + m_offaxisY); return spc + QString("Frustum %1 %2 %3 %4 %5 %6;").arg(left*m_near).arg(right*m_near).arg(bottom*m_near).arg(top*m_near).arg(m_near).arg(m_far); } /** * Restore the projection matrix from XML data. * * @param element Parent XML element of the projection matrix data. */ void ProjectionMatrix::initFromDOMElement(const QDomElement& element) { m_fov = element.attribute("fov").toFloat(); m_aspectRatio = element.attribute("aspectRatio").toFloat(); m_near = element.attribute("near").toFloat(); m_far = element.attribute("far").toFloat(); m_offaxisX = element.attribute("offaxisX").toFloat(); m_offaxisY = element.attribute("offaxisY").toFloat(); } /** * Store the current projection matrix as XML data. * * @param name XML node name of the data. * @param doc XML document to store the data. * @return Current screen shape data as XML data. */ QDomElement ProjectionMatrix::domElement(const QString& name, QDomDocument& doc) const { QDomElement de = doc.createElement(name); de.setAttribute("fov", QString::number(m_fov)); de.setAttribute("aspectRatio", QString::number(m_aspectRatio)); de.setAttribute("near", QString::number(m_near)); de.setAttribute("far", QString::number(m_far)); de.setAttribute("offaxisX", QString::number(m_offaxisX)); de.setAttribute("offaxisY", QString::number(m_offaxisY)); return de; }