#include "DefaultProjectorData.h" #include #include #include #ifndef M_PI #define M_PI 3.1415926535897932384626433832795 #endif // M_PI #define RAD(angle) ((angle)*M_PI/180.f) const QString DefaultPluginData::g_projector_name=QObject::tr("Standard Frustum"); /** * Default constructor fot the DefaultPluginData. * */ DefaultPluginData::DefaultPluginData(ProjectorInterface* plugin, float fov, float aspectRatio, float nearDist, float farDist, float offaxisX, float offaxisY): ProjectorData(plugin), m_fov(fov), m_aspectRatio(aspectRatio), m_nearDist(nearDist), m_farDist(farDist), m_offaxisX(offaxisX), m_offaxisY(offaxisY), m_visibleFar(1.2f) { } /** * Destructor fot the DefaultPluginData. * */ DefaultPluginData::~DefaultPluginData() { } /** * Implements the copy from other datas. * * This method is used by the copy constructor. * * @param data The source data. * * @return true if the copy is ok, false otherwise. The copy can fail if * ProjectorData is not a DefaultPluginData. * * @seealso is_equal_to * */ bool DefaultPluginData::copy_from(const ProjectorData& data) { if (!ProjectorData::copy_from(data)) return false; Q_ASSERT(NULL!=plugin()); Q_ASSERT(NULL!=data.plugin()); const DefaultPluginData& _data = static_cast(data); m_fov = _data.m_fov; m_aspectRatio = _data.m_aspectRatio; m_nearDist = _data.m_nearDist; m_farDist = _data.m_farDist; m_offaxisX = _data.m_offaxisX; m_offaxisY = _data.m_offaxisY; m_visibleFar = _data.m_visibleFar; return true; } /** * Implements the egality-test with other datas. * * This could be an operator==. * * @param data The data to test with. * * @return true if the data are equal, false otherwise. The test can fail if * the data have different parameters, but also it ProjectorData is * not a DefaultPluginData. * * @seealso copy_from * */ bool DefaultPluginData::is_equal_to(const ProjectorData& data) const { if (!ProjectorData::is_equal_to(data)) return false; const DefaultPluginData& _data = static_cast(data); return m_fov==_data.m_fov&& m_aspectRatio==_data.m_aspectRatio&& m_nearDist==_data.m_nearDist&& m_farDist==_data.m_farDist&& m_offaxisX==_data.m_offaxisX&& m_offaxisY==_data.m_offaxisY&& m_visibleFar==_data.m_visibleFar; } /** * Draws the frustum (a truncated pyramid). * * This method draws the frustum from outside. If the frustum is selected, * the lines are a little bigger. * * @param bSelected true if the frustum is selected. * * @seealso copy_from * */ void DefaultPluginData::draw(bool bSelected) { QColor m_color(0,0,255); if (m_bShow) { glPushMatrix(); glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_LINE_BIT); if (bSelected) glLineWidth(3.0f); float left = -tan(RAD(m_fov/2.0f)) * m_aspectRatio + m_offaxisX; float right = tan(RAD(m_fov/2.0f)) * m_aspectRatio + m_offaxisX; float top = -tan(RAD(m_fov/2.0f)) + m_offaxisY; float bottom = tan(RAD(m_fov/2.0f)) + m_offaxisY; float nearDist = m_nearDist; float farDist = m_farDist; 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, cos(RAD(m_fov)/2.0f), -sin(RAD(m_fov)/2.0f)); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(farDist*left, farDist*bottom, -farDist); glVertex3f(farDist*right, farDist*bottom, -farDist); glNormal3f( cos(RAD(m_fov)*m_aspectRatio/2.0f), 0.0f, -sin(RAD(m_fov)*m_aspectRatio/2.0f)); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(farDist*right, farDist*bottom, -farDist); glVertex3f(farDist*right, farDist*top, -farDist); glNormal3f(0.0f, -cos(RAD(m_fov)/2.0f), -sin(RAD(m_fov)/2.0f)); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(farDist*right, farDist*top, -farDist); glVertex3f(farDist*left, farDist*top, -farDist); glNormal3f(-cos(RAD(m_fov)*m_aspectRatio/2.0f), 0.0f, -sin(RAD(m_fov)*m_aspectRatio/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(); } } /** * Begins the draw through the frustum. * * The draw must end with a endDraw(). * * This is the same than glFrustum(), with some glPush...() before. * * @seealso endDraw * */ void DefaultPluginData::beginDraw(void) { // Get the previous matrix mode GLint previous_matrix_mode=-1; glGetIntegerv(GL_MATRIX_MODE, &previous_matrix_mode); // Push and load the new projection matrix glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glFrustum((-tan(RAD(m_fov) / 2.0 * m_aspectRatio) - m_offaxisX) * m_nearDist, ( tan(RAD(m_fov) / 2.0 * m_aspectRatio) - m_offaxisX) * m_nearDist, (-tan(RAD(m_fov) / 2.0) + m_offaxisY) * m_nearDist, ( tan(RAD(m_fov) / 2.0) + m_offaxisY) * m_nearDist, m_nearDist, m_farDist); // Restore the previous matrix mode glMatrixMode(previous_matrix_mode); } /** * Ends the draw through the frustum. * * Must be used each time a draw through the projector has begun with a * beginDraw(). * * This is the same than some glPop...(). * * @seealso beginDraw * */ void DefaultPluginData::endDraw(void) { // Get the previous matrix mode GLint previous_matrix=-1; glGetIntegerv(GL_MATRIX_MODE, &previous_matrix); // Pop the projection matrix stack glMatrixMode(GL_PROJECTION); glPopMatrix(); // Restore the previous matrix mode glMatrixMode(previous_matrix); } /** * Begins the projection. * * The projection must end with a endProjection(). * * This is the same than glFrustum(), without anything else. * beginDraw and beginProjection are quite close and it is perhaps to merge * them, but for the moment, to respect the Projection Designer * implementation, it will be let like this. * * endProjection is not implemented here because it does nothing more than * the ProjectorData::endProjection(). * */ void DefaultPluginData::beginProjection(void) { glFrustum((-tan(RAD(m_fov) / 2.0 * m_aspectRatio) - m_offaxisX) * m_nearDist, ( tan(RAD(m_fov) / 2.0 * m_aspectRatio) - m_offaxisX) * m_nearDist, (-tan(RAD(m_fov) / 2.0) + m_offaxisY) * m_nearDist, ( tan(RAD(m_fov) / 2.0) + m_offaxisY) * m_nearDist, m_nearDist, m_farDist); } /** * Loads the frustum from a QDomElement. * * @param element The QDomElement to read from. * */ void DefaultPluginData::initFromDOMElement(const QDomElement& element) { if (!element.isNull()) { m_fov=element.attribute("fov").toFloat(); m_aspectRatio=element.attribute("aspectRatio").toFloat(); m_nearDist=element.attribute("near").toFloat(); m_farDist=element.attribute("far").toFloat(); m_offaxisX=element.attribute("offaxisX").toFloat(); m_offaxisY=element.attribute("offaxisY").toFloat(); m_visibleFar=element.attribute("visibleFar").toFloat(); ProjectorData::initFromDOMElement(element); } } /** * Writes the frustum in a QDomDocument. * * @param name The name of the element. * @param doc The document whom belongs the element. * * @return The QDomElement to add. * */ QDomElement DefaultPluginData::domElement(const QString& name, QDomDocument& doc) const { QDomElement de = ProjectorData::domElement(name, doc); de.setAttribute("fov", m_fov); de.setAttribute("aspectRatio", m_aspectRatio); de.setAttribute("near", m_nearDist); de.setAttribute("far", m_farDist); de.setAttribute("offaxisX", m_offaxisX); de.setAttribute("offaxisY", m_offaxisY); de.setAttribute("visibleFar", m_visibleFar); return de; }