float Ray::intersectionWithPolygonAlt(Ray &ray, const QVector<QVector4D> polygon, QVector3D &normal, QVector3D &intersection, Ray &mirror) { if(polygon.size() < 3) return std::numeric_limits<float>::max(); normal = QVector3D::crossProduct((polygon[1] - polygon[0]).toVector3D(), (polygon[2] - polygon[1]).toVector3D()); float distanceFromOrigin = QVector3D::dotProduct(normal, polygon[1].toVector3D() - polygon[0].toVector3D()); QVector4D ba = ray.endPoint() - ray.startPoint(); QVector4D pa = polygon[2] - ray.startPoint(); float nDotA = QVector3D::dotProduct(normal, pa.toVector3D()); float nDotBA = QVector3D::dotProduct(normal, ba.toVector3D()); intersection = ray.startPoint().toVector3D() + (((distanceFromOrigin - nDotA)/nDotBA) * ba.toVector3D()); QVector3D vector(QVector4D(intersection,1.0f)- ray.startPoint()); QMatrix4x4 mat; mat.rotate(180, normal); vector = mat * vector; mirror = Ray(QVector4D(intersection,1.0), QVector4D(vector+intersection,1.0f)); return calcAngleSum(intersection, polygon); }
ShipCAD::PickRay ViewportView::convertMouseCoordToWorld(QPoint pos, int w, int h) const { float x = (2.0f * pos.x()) / w - 1.0f; float y = 1.0f - (2.0f * pos.y()) / h; QVector4D from = _worldInv * QVector4D(x, y, -1.0, 1.0); QVector4D to = _worldInv * QVector4D(x, y, 1.0, 1.0); from /= from.w(); to /= to.w(); PickRay ray; ray.pt = from.toVector3D(); ray.dir = to.toVector3D() - from.toVector3D(); ray.dir.normalize(); #if 0 cout << "from:" << from.x() << "," << from.y() << "," << from.z() << endl; cout << "to:" << to.x() << "," << to.y() << "," << to.z() << endl; // find the intersection with the xz plane if possible Plane xz(0,1,0,0); bool coplanar; QVector3D intpt; if (!xz.intersectLine(ray.pt, ray.dir, coplanar, intpt)) cout << "xz intersect:" << intpt.x() << "," << intpt.y() << "," << intpt.z() << endl; else cout << "parallel to xz" << endl; if (coplanar) cout << "coplanar" << endl; // find the intersection with the yz plane if possible Plane yz(1,0,0,0); if (!yz.intersectLine(ray.pt, ray.dir, coplanar, intpt)) cout << "yz intersect:" << intpt.x() << "," << intpt.y() << "," << intpt.z() << endl; else cout << "parallel to yz" << endl; if (coplanar) cout << "coplanar" << endl; // find the intersection with the xy plane if possible Plane xy(0,0,1,0); if (!xy.intersectLine(ray.pt, ray.dir, coplanar, intpt)) cout << "xy intersect:" << intpt.x() << "," << intpt.y() << "," << intpt.z() << endl; else cout << "parallel to xy" << endl; if (coplanar) cout << "coplanar" << endl; #endif return ray; }
QPointF GLScene::mapToScene(const QPointF &p){ // Code below will work OK while projection is ortogonal // For some reason in perspective projection everything is flipped and not accurate QVector4D rNear = unproject(QVector3D(p.x(), p.y(), -1)); QVector4D rFar = unproject(QVector3D(p.x(), p.y(), 1)); QVector<QVector3D> triangle; triangle << QVector3D(0, 0, 0) << QVector3D(0, 1, 0) << QVector3D(1, 0, 0); QVector3D normal = QVector3D::normal(triangle.at(0), triangle.at(1), triangle.at(2)); qreal d1 = QVector3D::dotProduct(rNear.toVector3D() - triangle.at(0), normal); qreal d2 = QVector3D::dotProduct(rFar.toVector3D() - triangle.at(0), normal); QVector3D point = rNear.toVector3D() + (rFar.toVector3D() - rNear.toVector3D()) * (-d2 / (d2 - d1)); return point.toPointF(); }
void FormImageProp::colorPicked(QVector4D color){ if(imageProp.bRoughnessColorPickingToggled){ ui->pushButtonRoughnessPickColor->setChecked(false); imageProp.bRoughnessColorPickingToggled = false; imageProp.pickedColor = color.toVector3D()/255.0; QPalette palette = ui->labelRoughnessPickedColor->palette(); palette.setColor(ui->labelRoughnessPickedColor->backgroundRole(), QColor(color.x(),color.y(),color.z())); palette.setColor(ui->labelRoughnessPickedColor->foregroundRole(), QColor(color.x(),color.y(),color.z())); ui->labelRoughnessPickedColor->setPalette(palette); update(); emit imageChanged(); } }
static QVector3D unproject( QVector3D v, const QMatrix4x4 &modelView, const QMatrix4x4 &projection, QRect viewport ) { // Reimplementation of QVector3D::unproject() - see qtbase/src/gui/math3d/qvector3d.cpp // The only difference is that the original implementation uses tolerance 1e-5 // (see qFuzzyIsNull()) as a protection against division by zero. For us it is however // common to get lower values (e.g. as low as 1e-8 when zoomed out to the whole Earth with web mercator). QMatrix4x4 inverse = QMatrix4x4( projection * modelView ).inverted(); QVector4D tmp( v, 1.0f ); tmp.setX( ( tmp.x() - float( viewport.x() ) ) / float( viewport.width() ) ); tmp.setY( ( tmp.y() - float( viewport.y() ) ) / float( viewport.height() ) ); tmp = tmp * 2.0f - QVector4D( 1.0f, 1.0f, 1.0f, 1.0f ); QVector4D obj = inverse * tmp; if ( qgsDoubleNear( obj.w(), 0, 1e-10 ) ) obj.setW( 1.0f ); obj /= obj.w(); return obj.toVector3D(); }
void CubeMapRefractionScene::render() { // Clear the buffer with the current clearing color glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // Set up the view matrix QVector3D eye( 0.0f, 0.0f, 0.0f ); QVector3D center( 0.0f, 0.0f, 1.0f ); QVector3D up( 0.0f, 1.0f, 0.0f ); m_viewMatrix.setToIdentity(); m_viewMatrix.lookAt( eye, center, up ); m_viewMatrix.rotate( m_phi, 1.0f, 0.0f, 0.0f ); m_viewMatrix.rotate( m_theta, 0.0f, 1.0f, 0.0f ); m_modelMatrix.setToIdentity(); QMatrix4x4 modelViewMatrix = m_viewMatrix * m_modelMatrix; QMatrix4x4 mvp = m_projectionMatrix * modelViewMatrix; // We need a pointer to the material's shader to set uniform variables QOpenGLShaderProgramPtr shader = m_skyBox->material()->shader(); // Draw the skybox shader->setUniformValue( "drawSkyBox", true ); glDepthFunc(GL_LEQUAL); m_skyBox->render( mvp ); glDepthFunc(GL_LESS); eye = QVector3D( 0.0f, 0.0f, -4.0f ); m_viewMatrix.setToIdentity(); m_viewMatrix.lookAt( eye, center, up ); m_viewMatrix.rotate( m_phi, 1.0f, 0.0f, 0.0f ); m_viewMatrix.rotate( m_theta, 0.0f, 1.0f, 0.0f ); // Calculate the position of the camera in world coordinates QMatrix4x4 rot; rot.rotate( -m_theta, 0.0f, 1.0f, 0.0f ); rot.rotate( -m_phi, 1.0f, 0.0f, 0.0f ); QVector4D worldEye = rot * eye; QVector3D worldCamera = worldEye.toVector3D(); // Rotate (and scale the model) m_modelMatrix.setToIdentity(); static float theta = 0.0f; theta += 0.3f; m_modelMatrix.rotate( theta, 0.0f, 1.0f, 0.0f ); m_modelMatrix.scale( 0.05f ); // Scale the toyplane mesh down to a reasonable size modelViewMatrix = m_viewMatrix * m_modelMatrix; mvp = m_projectionMatrix * modelViewMatrix; QMatrix3x3 normalMatrix = modelViewMatrix.normalMatrix(); shader->setUniformValue( "worldCameraPosition", worldCamera ); shader->setUniformValue( "modelViewMatrix", modelViewMatrix ); shader->setUniformValue( "modelMatrix", m_modelMatrix ); shader->setUniformValue( "normalMatrix", normalMatrix ); shader->setUniformValue( "projectionMatrix", m_projectionMatrix ); shader->setUniformValue( "mvp", mvp ); // Draw the reflective mesh shader->setUniformValue( "drawSkyBox", false ); shader->setUniformValue( "material.eta", 0.96f ); shader->setUniformValue( "material.reflectionFactor", 0.0f ); m_mesh->render(); }