#include #include "Frustum.h" using namespace projection; using namespace gmtl; /** * Constructor. */ Frustum::Frustum() : QObject() { m_bShow = true; m_bShowArea = true; m_visibleFar = 1.2f; m_color.setRgb(0, 0, 255); m_transformMatrix.setUseScaling(false); } /** * Destructor. */ Frustum::~Frustum() { } /** * Set projection matrix of the frustum. * * @param matrix Projection matrix of the frustum. */ void Frustum::setProjectionMatrix(const ProjectionMatrix& matrix) { m_projectionMatrix = matrix; emit dataChanged(); } /** * Retrieve projection matrix of the frustum. * * @return Projection matrix of the frustum. */ ProjectionMatrix Frustum::getProjectionMatrix() const { return m_projectionMatrix; } /** * Set transform matrix of the frustum. * * @param matrix Transform matrix of the frustum. */ void Frustum::setTransformMatrix(const TransformMatrix& matrix) { m_transformMatrix = matrix; emit dataChanged(); } /** * Retrieve transform matrix of the frustum. * * @return Transform matrix of the frustum. */ TransformMatrix Frustum::getTransformMatrix() const { return m_transformMatrix; } /** * Set color of the frustum shape object. * * @param color Color of the frustum shape object. */ void Frustum::setColor(const QColor& color) { m_color = color; emit dataChanged(); } /** * Retrieve color of the frustum shape object. * * @return Color of the frustum shape object. */ QColor Frustum::getColor() const { return m_color; } /** * Show or hide the frustum shape object. * * @param bShow True to show the frustum shape object, false to hide. */ void Frustum::setShow(bool bShow) { m_bShow = bShow; emit dataChanged(); } /** * Check whether the frustum shape object is shown or not. * * @return True if the frustum shape object is shown. */ bool Frustum::getShow() const { return m_bShow; } /** * Show or hide the frustum projected area. * * @param bShow True to show the frustum projected area, false to hide. */ void Frustum::setShowArea(bool bShow) { m_bShowArea = bShow; emit dataChanged(); } /** * Check whether the frustum projected area is shown or not. * * @return True if the frustum projected area is shown. */ bool Frustum::getShowArea() const { return m_bShowArea; } /** * Set far clip plane distance of the frame shape object. It doesn't modify the data. * * @param farDist Far clip plane distance of the frame shape object. */ void Frustum::setVisibleFar(float farDist) { m_visibleFar = farDist; } /** * Retrieve far clip plane distance of the frame shape object. * * @return Far clip plane distance of the frame shape object. */ float Frustum::getVisibleFar() const { return m_visibleFar; } /** * Draw frustum shape object. * * @param bSelected True to draw with selection highlight. */ void Frustum::draw(bool bSelected) { if (m_bShow) { glPushMatrix(); glMultMatrixf(m_transformMatrix.getMatrix().getData()); glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_LINE_BIT); if (bSelected) glLineWidth(3.0f); float left = -tanf(Math::deg2Rad(m_projectionMatrix.getFOV()/2.0f)) * m_projectionMatrix.getAspectRatio() + m_projectionMatrix.getOffaxisX(); float right = tanf(Math::deg2Rad(m_projectionMatrix.getFOV()/2.0f)) * m_projectionMatrix.getAspectRatio() + m_projectionMatrix.getOffaxisX(); float top = -tanf(Math::deg2Rad(m_projectionMatrix.getFOV()/2.0f)) + m_projectionMatrix.getOffaxisY(); float bottom = tanf(Math::deg2Rad(m_projectionMatrix.getFOV()/2.0f)) + m_projectionMatrix.getOffaxisY(); float nearDist = m_projectionMatrix.getNear(); float farDist = m_projectionMatrix.getFar(); if (m_visibleFar < farDist) farDist = m_visibleFar; glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glDisable(GL_LIGHTING); glBegin(GL_LINE_LOOP); glVertex3f(nearDist*left, nearDist*bottom, -nearDist); glVertex3f(nearDist*right, nearDist*bottom, -nearDist); glVertex3f(nearDist*right, nearDist*top, -nearDist); glVertex3f(nearDist*left, nearDist*top, -nearDist); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(farDist*left, farDist*bottom, -farDist); glVertex3f(farDist*right, farDist*bottom, -farDist); glVertex3f(farDist*right, farDist*top, -farDist); glVertex3f(farDist*left, farDist*top, -farDist); glEnd(); glBegin(GL_LINES); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(farDist*left, farDist*bottom, -farDist); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(farDist*right, farDist*bottom, -farDist); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(farDist*right, farDist*top, -farDist); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(farDist*left, farDist*top, -farDist); glEnd(); glColor4f((float)m_color.red()/255.0f, (float)m_color.green()/255.0f, (float)m_color.blue()/255.0f, 0.25f); glEnable(GL_LIGHTING); glEnable(GL_BLEND); glDepthMask(false); glBegin(GL_TRIANGLES); glNormal3f(0.0f, cosf(Math::deg2Rad(m_projectionMatrix.getFOV())/2.0f), -sinf(Math::deg2Rad(m_projectionMatrix.getFOV())/2.0f)); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(farDist*left, farDist*bottom, -farDist); glVertex3f(farDist*right, farDist*bottom, -farDist); glNormal3f( cosf(Math::deg2Rad(m_projectionMatrix.getFOV())*m_projectionMatrix.getAspectRatio()/2.0f), 0.0f, -sinf(Math::deg2Rad(m_projectionMatrix.getFOV())*m_projectionMatrix.getAspectRatio()/2.0f)); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(farDist*right, farDist*bottom, -farDist); glVertex3f(farDist*right, farDist*top, -farDist); glNormal3f(0.0f, -cosf(Math::deg2Rad(m_projectionMatrix.getFOV())/2.0f), -sinf(Math::deg2Rad(m_projectionMatrix.getFOV())/2.0f)); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(farDist*right, farDist*top, -farDist); glVertex3f(farDist*left, farDist*top, -farDist); glNormal3f(-cosf(Math::deg2Rad(m_projectionMatrix.getFOV())*m_projectionMatrix.getAspectRatio()/2.0f), 0.0f, -sinf(Math::deg2Rad(m_projectionMatrix.getFOV())*m_projectionMatrix.getAspectRatio()/2.0f)); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(farDist*left, farDist*top, -farDist); glVertex3f(farDist*left, farDist*bottom, -farDist); glEnd(); glDepthMask(true); glPopAttrib(); glPopMatrix(); } } /** * Assignment operator. * * @param frustum Assignment source frustum. */ Frustum& Frustum::operator=(const Frustum& frustum) { if (this != &frustum) { m_projectionMatrix = frustum.m_projectionMatrix; m_transformMatrix = frustum.m_transformMatrix; m_bShow = frustum.m_bShow; m_visibleFar = frustum.m_visibleFar; m_color = frustum.m_color; } return *this; } /** * Restore the frustum data from XML data. * * @param element Parent XML element of the frustum data. */ void Frustum::initFromDOMElement(const QDomElement& element) { if (!element.isNull()) { m_projectionMatrix.initFromDOMElement(element.firstChildElement("ProjectionMatrix")); m_transformMatrix.initFromDOMElement(element.firstChildElement("TransformMatrix")); m_bShow = element.attribute("show").toLower()=="true"; m_bShowArea = element.attribute("showArea").toLower()=="true"; } } /** * Store the current frustum data as XML data. * * @param name XML node name of the data. * @param doc XML document to store the data. * @return Current frustum data as XML data. */ QDomElement Frustum::domElement(const QString& name, QDomDocument& doc) const { QDomElement de = doc.createElement(name); de.appendChild(m_projectionMatrix.domElement("ProjectionMatrix", doc)); de.appendChild(m_transformMatrix.domElement("TransformMatrix", doc)); de.setAttribute("show", (m_bShow?"true":"false")); de.setAttribute("showArea", (m_bShowArea?"true":"false")); return de; }