#include "gldisc.h" GLDisc::GLDisc(double radius, double height, QVector3D lowerMiddlePoint, int sides, GLColorRgba color, QString textureFile) : GLBody(sqrt(pow(radius, 2) + pow(0.5 * height, 2)), color, textureFile) { m_height = height; m_sides = sides; m_center = v_Z * 0.5 * m_height; m_circleRadius = radius; m_lowerMiddlePoint = lowerMiddlePoint; } void GLDisc::makeSurface(QVector *pointContainer, QVector *indexContainer) { GLBody::makeSurface(pointContainer, indexContainer); m_firstPoint = m_points->size(); m_points->append(GLPoint(v_Zero, -v_Z, QVector3D(0.5, 0.5, 0.0), m_color)); for (int side = 0; side < m_sides; side++) { QVector2D tmp = calculatePoint(side * 2 * M_PI / m_sides); QVector2D tmpTextCoo = (0.5 * tmp) + QVector2D(0.5, 0.5); m_points->append(GLPoint(m_circleRadius * tmp, -v_Z, tmpTextCoo, m_color)); m_points->append(GLPoint(m_circleRadius * tmp, tmp, tmpTextCoo, m_color)); m_points->append(GLPoint(QVector3D(m_circleRadius * tmp, m_height), tmp, tmpTextCoo, m_color)); m_points->append(GLPoint(QVector3D(m_circleRadius * tmp, m_height), v_Z, tmpTextCoo, m_color)); } m_points->append(GLPoint(m_height * v_Z, v_Z, QVector3D(0.5, 0.5, 0.0), m_color)); m_nextPoint = m_points->size(); m_firstIndex = m_indices->size(); for (int side = 0; side < m_sides - 1; side++) { m_indices->append(m_firstPoint); m_indices->append(m_firstPoint + 1 + 4 * side); m_indices->append(m_firstPoint + 5 + 4 * side); m_indices->append(m_firstPoint + 2 + 4 * side); m_indices->append(m_firstPoint + 6 + 4 * side); m_indices->append(m_firstPoint + 3 + 4 * side); m_indices->append(m_firstPoint + 3 + 4 * side); m_indices->append(m_firstPoint + 7 + 4 * side); m_indices->append(m_firstPoint + 6 + 4 * side); m_indices->append(m_firstPoint + 4 + 4 * side); m_indices->append(m_firstPoint + 8 + 4 * side); m_indices->append(m_nextPoint - 1); } m_indices->append(m_firstPoint); m_indices->append(m_firstPoint + 1 + 4 * (m_sides - 1)); m_indices->append(m_firstPoint + 1); m_indices->append(m_firstPoint + 2 + 4 * (m_sides - 1)); m_indices->append(m_firstPoint + 2); m_indices->append(m_firstPoint + 3 + 4 * (m_sides - 1)); m_indices->append(m_firstPoint + 3 + 4 * (m_sides - 1)); m_indices->append(m_firstPoint + 3); m_indices->append(m_firstPoint + 2); m_indices->append(m_firstPoint + 4 + 4 * (m_sides - 1)); m_indices->append(m_firstPoint + 4); m_indices->append(m_nextPoint - 1); m_nextIndex = m_indices->size(); } bool GLDisc::isHit(QVector3D p1, QVector3D p2) { QVector3D p1New = p1 - m_lowerMiddlePoint; QVector3D p2New = p2 - m_lowerMiddlePoint; if (!GLBody::isHit(p1New, p2New)) { return false; } QVector3D lineVector = p2New - p1New; // Calculate intersection point with the xy plane QVector3D vecBottom = p1New + lineVector * (-p1New.z() / lineVector.z()); if (vecBottom.length() < m_circleRadius) { return true; } // Calculate intersection point with the xy + m_heigth plane // Then drop z so that we get a projection onto the xy plane QVector3D vecTop = (p1New + lineVector * ((m_height - p1New.z()) / lineVector.z())).toVector2D(); if (vecTop.length() < m_circleRadius) { return true; } // Check if the mouse line is hitting the outer disc side QVector2D vecXYProjection = lineVector.toVector2D(); QVector2D vecXYStart = p1New.toVector2D(); // Solved via the "Mitternachtsformel" float a = QVector2D::dotProduct(vecXYProjection, vecXYProjection); float b = 2 * QVector2D::dotProduct(vecXYStart, vecXYProjection); float c = QVector2D::dotProduct(vecXYStart, vecXYStart) - m_circleRadius * m_circleRadius; float discriminant = b * b - 4 * a * c; if (discriminant >= 0) { discriminant = sqrt(discriminant); float lambda1 = (-b - discriminant) / (2*a); float z1 = (p1New + lambda1 * lineVector).z(); if(z1 >= 0 && z1 <= m_height) { return true; } float lambda2 = (-b + discriminant) / (2*a); float z2 = (p1New + lambda2 * lineVector).z(); if(z2 >= 0 && z2 <= m_height) { return true; } } return false; } QVector2D GLDisc::calculatePoint(double sideAngle) { double x = sin(sideAngle); double y = cos(sideAngle); return QVector2D(x, y); } void GLDisc::draw(GLESRenderer *renderer) { renderer->pushMvMatrix(); renderer->translate(m_lowerMiddlePoint); GLBody::draw(renderer); renderer->popMvMatrix(); }