Ejemplo n.º 1
0
 PolarVec::PolarVec(const QVector4D& _vec)
 {
   if (_vec.w() != 0.0)
     operator=(QVector3D(_vec.x()/_vec.w(),_vec.y()/_vec.w(),_vec.z()/_vec.w()));
   else
     operator=(QVector3D(_vec.x(),_vec.y(),_vec.z()));
 }
Ejemplo n.º 2
0
void GLWidget::screenCoordinatesPerspective(QVector4D *answer, const TwoDimArray &a, double h, const QVector4D &screenCoordinates)
{
    double x = screenCoordinates.x(), y = screenCoordinates.y();
    double w = (a(2, 2) - a(3, 2) * h) / ((a(3, 0) * a(2, 2) - a(3, 2) * a(2, 0)) * x + (a(3, 1) * a(2, 2) - a(3, 2) * a(2, 1)) * y + a(3, 3) * a(2, 2) - a(3, 2) * a(2, 3));
    *answer = QVector4D(screenCoordinates.x(), screenCoordinates.y(), (h - (a(2, 0) * x + a(2, 1) * y + a(2, 3)) * w) / a(2, 2), w);
    for(int i = 0; i < 2; i++) (*answer)[i] *= w;
}
Ejemplo n.º 3
0
QVector4D Cylinder::surfaceNormal(const QVector4D &p, const Ray &ray)
{
    QVector4D lp = m_worldToObject * p;
    QMatrix4x4 a = m_worldToObject.transposed();
    a.setRow(3, QVector4D(0.0, 0.0, 0.0, 1.0));


    if (m_hasCaps && fabs(fabs(lp.y()) - m_length * 0.5) < MathUtils::dEpsilon) {
        // Return cap normal
        QVector4D n;
        if (lp.y() < 0.0)
            n = QVector4D(0.0, -1.0, 0.0, 0.0);
        else
            n = QVector4D(0.0, 1.0, 0.0, 0.0);
        return (a * n).normalized();
    } else {
        // calculate cylinder normal
        QVector4D o = QVector4D(0.0, lp.y(), 0.0, 1.0);
        QVector4D n = lp - o;
        n = a * n;

        QVector4D rd = -ray.direction();
        if (QVector4D::dotProduct(n, rd) < 0)
            return -n.normalized();
        else
            return n.normalized();
    }
}
Ejemplo n.º 4
0
QVector<float> UniformItem::getGlData() const
{
    QVector<float> glData;
    if (type == UniformType::SPHERICAL_3D) {
        QVector4D cartesian = CoordinateConversions::sphericalToCartesian(data[0], data[1], data[2], 0.0);
        glData.push_back(cartesian.x());
        glData.push_back(cartesian.y());
        glData.push_back(cartesian.z());
    } else if (type == UniformType::SPHERICAL_4D) {
        QVector4D cartesian = CoordinateConversions::sphericalToCartesian(data[0], data[1], data[2], data[3]);
        glData.push_back(cartesian.x());
        glData.push_back(cartesian.y());
        glData.push_back(cartesian.z());
        glData.push_back(cartesian.w());
    } else if (type == UniformType::COLOR) {
        glData.push_back(data[0] / 255.0f);
        glData.push_back(data[1] / 255.0f);
        glData.push_back(data[2] / 255.0f);
    } else if (type == UniformType::COLOR_ALPHA) {
        glData.push_back(data[0] / 255.0f);
        glData.push_back(data[1] / 255.0f);
        glData.push_back(data[2] / 255.0f);
        glData.push_back(data[3] / 255.0f);
    } else {
        glData = data;
    }
    return glData;
}
Ejemplo n.º 5
0
QVector4D iPolacion::ipEsferica(QVector4D q1, QVector4D q2, float lam){
    // Caso facil primero.
        if (lam <= 0.0f)
            return q1;
        else if (lam >= 1.0f)
            return q2;

        // Determinamos el angulo
        QVector4D q2b;
        float dot;
        dot = q1.x() * q2.x() + q1.y() * q2.y() + q1.z() * q2.z() + q1.w() * q2.w();
        if (dot >= 0.0f) {
            q2b = q2;
        } else {
            q2b = -q2;
            dot = -dot;
        }

        // Obtenemos los factores de interpolacion
        float factor1 = 1.0f - lam;
        float factor2 = lam;
        if ((1.0f - dot) > 0.0000001) {
            float angle = float(acos(dot));
            float sinOfAngle = float(sin(angle));
            if (sinOfAngle > 0.0000001) {
                factor1 = float(sin((1.0f - lam) * angle)) / sinOfAngle;
                factor2 = float(sin(lam * angle)) / sinOfAngle;

            }
        }

        // Construimos el nuevo quaternion
        return q1 * factor1 + q2b * factor2;
}
Ejemplo n.º 6
0
static bool fuzzyCompare(const QVector4D &v1, const QVector4D &v2)
{
    return qAbs(v1.x() - v2.x()) <= 0.00001 &&
           qAbs(v1.y() - v2.y()) <= 0.00001 &&
           qAbs(v1.z() - v2.z()) <= 0.00001 &&
           qAbs(v1.w() - v2.w()) <= 0.00001;
}
Ejemplo n.º 7
0
QVector3D Camera::screenToWorld(QVector3D vec, QMatrix4x4 modelview, QMatrix4x4 projection)
{
    int viewport[4];
    glGetIntegerv(GL_VIEWPORT, viewport);
    float winX = vec.x();
    float winY = vec.y();
    winY = viewport[3] - winY;
    float winZ;
    glReadPixels(winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);

    QVector4D v((winX-(float)viewport[0])/(float)viewport[2]*2.0-1.0,
                   (winY-(float)viewport[1])/(float)viewport[3]*2.0-1.0,
                   0, 1);


    QVector4D v2((winX-(float)viewport[0])/(float)viewport[2]*2.0-1.0,
                   (winY-(float)viewport[1])/(float)viewport[3]*2.0-1.0,
                   1, 1);

    QMatrix4x4 mat(modelview * projection);

    QVector4D t = v * mat.inverted();
    float w = 1 / t.w();
    QVector3D pt1(t.x() * w, t.y() * w, t.z() * w);

    t = v2 * mat.inverted();
    w = 1 / t.w();
    QVector3D pt2(t.x() * w, t.y() * w, t.z() * w);

    QVector3D out;
    intersects(QVector3D(1, 0, vec.z()), QVector3D(0, 1, vec.z()), QVector3D(1, 1, vec.z()),
               pt1, pt2, out);
    return out;
}
Ejemplo n.º 8
0
PropertyGroup::PropertyGroup(QVector4D min, QVector4D max, QVector4D t, QString name)
{
	createBox(name);

	properties.emplace_back(new Property(min.x(), max.x(), t.x(), box));
	properties.emplace_back(new Property(min.y(), max.y(), t.y(), box));
	properties.emplace_back(new Property(min.z(), max.z(), t.z(), box));
	properties.emplace_back(new Property(min.w(), max.w(), t.w(), box));

	config();
}
static inline int qsg_colorDiff(const QVector4D &a, const QVector4D &b)
{
    if (a.x() != b.x())
        return a.x() > b.x() ? 1 : -1;
    if (a.y() != b.y())
        return a.y() > b.y() ? 1 : -1;
    if (a.z() != b.z())
        return a.z() > b.z() ? 1 : -1;
    if (a.w() != b.w())
        return a.w() > b.w() ? 1 : -1;
    return 0;
}
Ejemplo n.º 10
0
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;
}
void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
	if ((event->buttons() & Qt::RightButton) && dragging) {
		double xtrans = (event->pos().x() - lastPoint.x()) / 1000.0;
		double ytrans = -(event->pos().y() - lastPoint.y()) / 1000.0; //Qt y-coord is inverted
		QVector4D trans(xtrans, ytrans, 0, 1);
		QVector4D worldTrans = trans * camera->getCameraMatrix();
		if(cameraActive) {
            this->camera->setpointOfInterest(scene->getMainBoat()->getPosition());
			this->camera->translate(-worldTrans.x(), -worldTrans.y(), -worldTrans.z());

			updateGL();
		} else {
			emit translate(worldTrans.x(), worldTrans.y(), worldTrans.z());
		}
	}

//	if ((event->buttons() & Qt::LeftButton) && dragging) {
		//Here we implement the trackball. Sample two points on the sphere and
		//calculate their angle to use as the rotation.

		//normalize to intervals [-1,1]
		double lastx = clampUnit(lastPoint.x() / (this->size().width() / 2.0) - 1.0);
		double lasty = clampUnit(-(lastPoint.y() / (this->size().height() / 2.0) - 1.0));

		double newx = clampUnit(event->pos().x() / (this->size().width() / 2.0) - 1.0);
		double newy = clampUnit(-(event->pos().y() / (this->size().height() / 2.0) - 1.0));

		//Project the two points into the sphere (or the hyperbolic plane)
		QVector3D v1(lastx, lasty, z(lastx, lasty));
		v1.normalize();
		QVector3D v2(newx, newy, z(newx, newy));
		v2.normalize();

		//Determine the normal of the generated plane through the center of the sphere
		QVector3D normal = QVector3D::crossProduct(v1, v2);
		double theta = acos(QVector3D::dotProduct(v1, v2)) / 3.0;

		//angle/2.0, because the quats double cover SO(3)
		QQuaternion newRot = QQuaternion(cos(theta/2.0), sin(theta/2.0) * normal.normalized());
		QQuaternion cameraQuat = M4toQuat(camera->getCameraMatrix());
		QQuaternion worldQuat = cameraQuat.conjugate() * newRot * cameraQuat;
		if(cameraActive) {
			this->camera->rotate(newRot);
			updateGL();
		} else {
			emit rotate(&worldQuat);
		}
//	}
}
Ejemplo n.º 12
0
QDebug operator<<(QDebug dbg, const QVector4D &vector)
{
    dbg.nospace() << "QVector4D("
        << vector.x() << ", " << vector.y() << ", "
        << vector.z() << ", " << vector.w() << ')';
    return dbg.space();
}
void ClippingConverter::convert(const QByteArray &clippingData, const QString &directory)
{
    QDataStream stream(clippingData);
    stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
    stream.setByteOrder(QDataStream::LittleEndian);

    QString newDirectory = directory;

    newDirectory.replace('\\', '/');
    if (!newDirectory.endsWith('/'))
        newDirectory.append('/');

    int objectCount, instanceCount;
    stream >> objectCount >> instanceCount;

    for (int i = 0; i < objectCount; ++i) {
        MeshPtr mesh = importObject(stream);

        // Serialize to a temporary file, then read it in again
        QTemporaryFile tempFile;
        if (!tempFile.open()) {
            qWarning("Unable to open the temporary %s file.", qPrintable(tempFile.fileName()));
            continue;
        }

        d->ogre->meshSerializer->exportMesh(mesh.getPointer(), tempFile.fileName().toStdString());

        QByteArray meshData = tempFile.readAll();
        QString meshFilename = QString("%1clipping/mesh-%2.mesh").arg(newDirectory).arg(i+1);

        d->output->writeFile(meshFilename, meshData);
    }

    QByteArray instances;

    instances.append("[");

    for (int i = 0; i < instanceCount; ++i) {
        QVector4D position;
        int index;

        stream >> position >> index;

        QString line = QString("{\"position\":[%1,%2,%3],\"file\":\"%5mesh-%4.mesh\"}")
                .arg(position.x())
                .arg(position.y())
                .arg(position.z())
                .arg(index+1)
                .arg(newDirectory);
        if (i > 0)
            instances.append(",");
        instances.append(line.toAscii());

    }

    instances.append("]");

    d->output->writeFile(newDirectory + "clipping.json", instances);

}
Ejemplo n.º 14
0
void HgTransformedQuad::perspectiveTransformPoints(QVector2D* outPoints, const QMatrix4x4& matrix,
        const QPointF& center, const QSizeF& windowSize)
{
    const QVector4D points[] =
    {
        QVector4D(-0.5f, -0.5f, 0.0f, 1.0f),
        QVector4D( 0.5f, -0.5f, 0.0f, 1.0f),
        QVector4D( 0.5f,  0.5f, 0.0f, 1.0f),
        QVector4D(-0.5f,  0.5f, 0.0f, 1.0f)
    };

    qreal hw = windowSize.width() * 0.5f;
    qreal hh = windowSize.height() * 0.5f;

    for (int i = 0; i < 4; i++)
    {
        QVector4D temp = matrix * points[i];

        outPoints[i] = QVector2D(
                           center.x() + temp.x() / temp.w() * hw,
                           center.y() + (temp.y() / temp.w() * hh) * mYDir);

    }

}
Ejemplo n.º 15
0
colour4::colour4( QVector4D in ) : vectorX( 4 )
{
    r() = in.x();
    g() = in.y();
    b() = in.z();
    a() = in.w();
}
Ejemplo n.º 16
0
void Camera::rotate(float dx, float dy)
{
    float roty = 1.5f * dx / mWidth;
    float rotx = 1.5f * dy / mHeight;
    float phi = rotx;
    float theta = roty;

    QVector3D cameraW = (mLookAtPosition - mCameraPosition).normalized();
    QVector3D cameraU = QVector3D::crossProduct(cameraW, mUpVector).normalized();

    QQuaternion q = (QQuaternion(theta, QVector3D(0.0, 1.0, 0.0)) * QQuaternion(phi, cameraU)).normalized();
    QMatrix4x4 rotMat = QMatrix4x4();
    rotMat.rotate(q);

    QVector3D tmp = mCameraPosition - mLookAtPosition;
    QVector4D myPoint = QVector4D(tmp, 1.0);
    QVector4D myVector = QVector4D(mUpVector);

    QVector4D newPos = rotMat * myPoint;
    QVector4D tmp1 = rotMat * myVector;

    // Hacky fix for some degeneracy
    newPos.setY(-newPos.y());
    tmp1.setY(-tmp1.y());

    mCameraPosition = QVector3D(newPos) + mLookAtPosition;
    mUpVector = QVector3D(tmp1).normalized();
    setViewMatrix(mCameraPosition, mLookAtPosition, mUpVector);
}
static inline QVector4D qt_sRGB_to_linear_RGB(const QVector4D &color)
{
    return QVector4D(qt_sRGB_to_linear_RGB(color.x()),
                     qt_sRGB_to_linear_RGB(color.y()),
                     qt_sRGB_to_linear_RGB(color.z()),
                     color.w());
}
Ejemplo n.º 18
0
QVector3D myCam::getPositionFromViewMatrix(QMatrix4x4 matrix)
{
    QMatrix4x4 viewRot = matrix;
    viewRot.setColumn(3, QVector4D(0,0,0,1));
    QVector4D p = -(viewRot.transposed() * matrix.column(3));
    return QVector3D(p.x(), p.y(), p.z());
}
Ejemplo n.º 19
0
void SQPrimitives::drawCubeGeometry(const QVector4D &color)
{
    // Tell OpenGL which VBOs to use
    glBindBuffer(GL_ARRAY_BUFFER, _vboIds[0]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIds[1]);

    // Offset for position
    quintptr offset = 0;

    // Tell OpenGL programmable pipeline how to locate vertex position data
    int vertexLocation = _program->attributeLocation("a_position");
    _program->enableAttributeArray(vertexLocation);
    glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void *)offset);

    // Offset for texture coordinate
    offset += sizeof(QVector3D);

    // Tell OpenGL programmable pipeline how to locate vertex texture coordinate data
    int texcoordLocation = _program->attributeLocation("a_texcoord");
    _program->enableAttributeArray(texcoordLocation);
    glVertexAttribPointer(texcoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void *)offset);

    int colorLocation = _program->attributeLocation("a_color");
    glVertexAttrib4f(colorLocation, color.x(), color.y(), color.z(), color.w());

    // Draw cube geometry using indices from VBO 1
    glDrawElements(GL_TRIANGLE_STRIP, 34, GL_UNSIGNED_SHORT, 0);
}
Ejemplo n.º 20
0
int
ClipPlanes::inViewport(int x, int y, int ow, int oh)
{
  float ar = (float)ow/(float)oh;
  float y1 = oh-y;
  for(int i=0; i<m_clips.count(); i++)
    {
      QVector4D vp = m_clips[i]->viewport();
      if (m_clips[i]->tfset() >= 0 &&
	  m_clips[i]->tfset() < Global::lutSize() &&
	  vp.x() >= 0.0)
	{
	  int vx, vy, vh, vw;
	  vx = vp.x()*ow;
	  vy = vp.y()*oh;
	  vw = vp.z()*ow;
	  vh = vp.w()*oh;
	  
	  if (x >= vx && x <= vx+vw &&
	      y1 >= vy && y1 <= vy+vh)
	    return i;
	}
    }
  return -1;
}
Ejemplo n.º 21
0
static void setLight(int light, const Light *parameters,
                     const QMatrix4x4& transform = QMatrix4x4())
{
    GLfloat params[4];

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();

    QColor color = parameters->ambientColor();
    params[0] = color.redF();
    params[1] = color.greenF();
    params[2] = color.blueF();
    params[3] = color.alphaF();
    glLightfv(light, GL_AMBIENT, params);

    color = parameters->diffuseColor();
    params[0] = color.redF();
    params[1] = color.greenF();
    params[2] = color.blueF();
    params[3] = color.alphaF();
    glLightfv(light, GL_DIFFUSE, params);

    color = parameters->specularColor();
    params[0] = color.redF();
    params[1] = color.greenF();
    params[2] = color.blueF();
    params[3] = color.alphaF();
    glLightfv(light, GL_SPECULAR, params);

    QVector4D vector = parameters->eyePosition(transform);
    params[0] = vector.x();
    params[1] = vector.y();
    params[2] = vector.z();
    params[3] = vector.w();
    glLightfv(light, GL_POSITION, params);

    QVector3D spotDirection = parameters->eyeSpotDirection(transform);
    params[0] = spotDirection.x();
    params[1] = spotDirection.y();
    params[2] = spotDirection.z();
    glLightfv(light, GL_SPOT_DIRECTION, params);

    params[0] = parameters->spotExponent();
    glLightfv(light, GL_SPOT_EXPONENT, params);

    params[0] = parameters->spotAngle();
    glLightfv(light, GL_SPOT_CUTOFF, params);

    params[0] = parameters->constantAttenuation();
    glLightfv(light, GL_CONSTANT_ATTENUATION, params);

    params[0] = parameters->linearAttenuation();
    glLightfv(light, GL_LINEAR_ATTENUATION, params);

    params[0] = parameters->quadraticAttenuation();
    glLightfv(light, GL_QUADRATIC_ATTENUATION, params);

    glPopMatrix();
}
Ejemplo n.º 22
0
static void _ringToPoly2tri( const QgsCurve *ring, const QgsPoint &ptFirst, const QMatrix4x4 &toNewBase, std::vector<p2t::Point *> &polyline, QHash<p2t::Point *, float> &zHash )
{
  QgsVertexId::VertexType vt;
  QgsPoint pt;

  const int pCount = ring->numPoints();
  double x0 = ptFirst.x(), y0 = ptFirst.y(), z0 = ( std::isnan( ptFirst.z() ) ? 0 : ptFirst.z() );

  polyline.reserve( pCount );

  for ( int i = 0; i < pCount - 1; ++i )
  {
    ring->pointAt( i, pt, vt );
    QVector4D tempPt( pt.x() - x0, pt.y() - y0, std::isnan( pt.z() ) ? 0 : pt.z() - z0, 0 );
    QVector4D newBasePt = toNewBase * tempPt;
    const float x = newBasePt.x();
    const float y = newBasePt.y();
    const float z = newBasePt.z();

    const bool found = std::find_if( polyline.begin(), polyline.end(), [x, y]( p2t::Point *&p ) { return *p == p2t::Point( x, y ); } ) != polyline.end();

    if ( found )
    {
      continue;
    }

    p2t::Point *pt2 = new p2t::Point( x, y );
    polyline.push_back( pt2 );
    zHash[pt2] = z;
  }
}
Ejemplo n.º 23
0
void PropertyGroup::setValue(QVector4D v)
{
	properties.at(0)->setValue(v.x());
	properties.at(1)->setValue(v.y());
	properties.at(2)->setValue(v.z());
	properties.at(3)->setValue(v.w());
}
Ejemplo n.º 24
0
AGE_Vector4D::AGE_Vector4D(const QVector4D &vector)
{
    setX(vector.x());
    setY(vector.y());
    setZ(vector.z());
    setW(vector.w());
}
Ejemplo n.º 25
0
void rpnoc::Cell::setBackGroundColor( QVector4D iColor )
{
	mBackgroundColor = iColor;
    GLfloat color[4] = { iColor.x(), iColor.y(), iColor.z(), iColor.w() };
    Vertex< 4 > oVertex[4] = { color, color, color, color };

    mPanel->setColor( oVertex );
}
Ejemplo n.º 26
0
QDebug operator<<(QDebug dbg, const QVector4D &vector)
{
    QDebugStateSaver saver(dbg);
    dbg.nospace() << "QVector4D("
        << vector.x() << ", " << vector.y() << ", "
        << vector.z() << ", " << vector.w() << ')';
    return dbg;
}
Ejemplo n.º 27
0
// ____________drawing____________
QVector<QVector2D> From3DTo2D (const QVector<QVector3D> Input3D, const QMatrix4x4 view, const QMatrix4x4 perspective){
    QVector<QVector2D> resultPoints = {};
    for (int curPoint = 0; curPoint < Input3D.length(); curPoint++){
        QVector4D temp = QVector4D(Input3D[curPoint].x(), Input3D[curPoint].y(), Input3D[curPoint].z(), 1.0);
        temp = temp * view * perspective;
        resultPoints << QVector2D(temp.x() / temp.w(), temp.y() / temp.w());
    }
    return resultPoints;
}
Ejemplo n.º 28
0
Ogre::String toString(const QVector4D &v)
{
	Ogre::String s="<QVector4D ";
	s+="w="+Ogre::StringConverter::toString((float)v.w())+", ";
	s+="x="+Ogre::StringConverter::toString((float)v.x())+", ";
	s+="y="+Ogre::StringConverter::toString((float)v.y())+", ";
	s+="z="+Ogre::StringConverter::toString((float)v.z());
	s+=">";
	return s;

}
Ejemplo n.º 29
0
QVector4D Cone::surfaceNormal(const QVector4D &p, const Ray &ray)
{
    QVector4D objectP = m_worldToObject * p;

    QVector4D n = fabs(objectP.y()) < MathUtils::dEpsilon ? QVector4D(0.0, -1.0, 0.0, 0.0) :  // We're on the base disc
                                                            QVector4D(objectP.x(), 1.0 - objectP.y(), objectP.z(), 0.0);
    QMatrix4x4 a = m_worldToObject.transposed();
    a.setRow(3, QVector4D(0.0, 0.0, 0.0, 1.0));
    n = a * n;
    return n.normalized();
}
QT_BEGIN_NAMESPACE

#ifndef GL_FRAMEBUFFER_SRGB
#define GL_FRAMEBUFFER_SRGB 0x8DB9
#endif

static inline QVector4D qsg_premultiply(const QVector4D &c, float globalOpacity)
{
    float o = c.w() * globalOpacity;
    return QVector4D(c.x() * o, c.y() * o, c.z() * o, o);
}