Beispiel #1
0
/*!
    Returns a copy of this array of QVector2D values, translated
    by the components of \a value.

    \sa translate()
*/
QArray<QVector2D> QVector2DArray::translated(const QVector2D& value) const
{
    QArray<QVector2D> result;
    int size = count();
    QVector2D *dst = result.extend(size);
    const QVector2D *src = constData();
    for (int index = 0; index < size; ++index)
        *dst++ = *src++ + value;
    return result;
}
Beispiel #2
0
/*!
    Returns a copy of this array of QVector2D values,
    transformed by \a matrix.

    \sa transform()
*/
QArray<QVector2D> QVector2DArray::transformed(const QMatrix4x4& matrix) const
{
    QArray<QVector2D> result;
    int size = count();
    const QVector2D *src = constData();
    QVector2D *dst = result.extend(size);
    for (int index = 0; index < size; ++index)
        *dst++ = (matrix * QVector3D(*src++, 0.0f)).toVector2D();
    return result;
}
/*!
    Returns a copy of this array of QVector3D values, multiplied
    by the \a scale.

    \sa scale()
*/
QVector3DArray QVector3DArray::scaled(qreal scale) const
{
    QArray<QVector3D> result;
    int size = count();
    const QVector3D *src = constData();
    QVector3D *dst = result.extend(size);
    for (int index = 0; index < size; ++index)
        *dst++ = *src++ * scale;
    return result;
}
Beispiel #4
0
/*!
    Returns a copy of this array of QVector2D values, multiplied
    by the \a scale.

    \sa scale()
*/
QVector2DArray QVector2DArray::scaled(qreal scale) const
{
    const qreal identity = 1.0;
    if (qFuzzyCompare(scale, identity))
        return *this;
    QArray<QVector2D> result;
    int size = count();
    const QVector2D *src = constData();
    QVector2D *dst = result.extend(size);
    for (int index = 0; index < size; ++index)
        *dst++ = *src++ * scale;
    return result;
}
Beispiel #5
0
/*!
    Translates the elements in this array of QVector2D values
    by the components of \a value.

    \sa translated()
*/
void QVector2DArray::translate(const QVector2D& value)
{
    if (isDetached()) {
        // Modify the array in-place.
        int size = count();
        QVector2D *dst = data();
        for (int index = 0; index < size; ++index)
            *dst++ += value;
    } else {
        // Create a new array, translate the values, and assign.
        QArray<QVector2D> result;
        int size = count();
        const QVector2D *src = constData();
        QVector2D *dst = result.extend(size);
        for (int index = 0; index < size; ++index)
            *dst++ = *src++ + value;
        *this = result;
    }
}
Beispiel #6
0
/*!
    Transforms the elements in this array of QVector2D values
    by \a matrix.

    \sa transformed()
*/
void QVector2DArray::transform(const QMatrix4x4& matrix)
{
    if (isDetached()) {
        // Modify the array in-place.
        int size = count();
        QVector2D *dst = data();
        for (int index = 0; index < size; ++index) {
            *dst = (matrix * QVector3D(*dst, 0.0f)).toVector2D();
            ++dst;
        }
    } else {
        // Create a new array, transform the values, and assign.
        QArray<QVector2D> result;
        int size = count();
        const QVector2D *src = constData();
        QVector2D *dst = result.extend(size);
        for (int index = 0; index < size; ++index)
            *dst++ = (matrix * QVector3D(*src++, 0.0f)).toVector2D();
        *this = result;
    }
}
Beispiel #7
0
QT_BEGIN_NAMESPACE

/*!
    \class QVector2DArray
    \brief The QVector2DArray class is a convenience for wrapping a QArray of QVector2D values.
    \since 4.8
    \ingroup qt3d
    \ingroup qt3d::arrays

    QVector2DArray is used to build an array of 2D vector values
    based on floating-point x and y arguments:

    \code
    QVector2DArray array;
    array.append(1.0f, 2.0f);
    array.append(-1.0f, 2.0f);
    array.append(1.0f, -2.0f);
    \endcode

    This is more convenient and readable than the equivalent with
    QArray:

    \code
    QArray<QVector2D> array;
    array.append(QVector2D(1.0f, 2.0f));
    array.append(QVector2D(-1.0f, 2.0f));
    array.append(QVector2D(1.0f, -2.0f));
    \endcode

    QVector2DArray also has convenience functions for transforming
    the contents of the array with translate(), translated(),
    transform(), and transformed().

    \sa QArray, QVector3DArray, QVector4DArray
*/

/*!
    \fn QVector2DArray::QVector2DArray()

    Constructs an empty array of QVector2D values.
*/

/*!
    \fn QVector2DArray::QVector2DArray(int size, const QVector2D& value)

    Constructs an array of QVector2D values with an initial \a size.
    All elements in the array are initialized to \a value.
*/

/*!
    \fn QVector2DArray::QVector2DArray(const QArray<QVector2D>& other)

    Constructs a copy of \a other.
*/

/*!
    \fn void QVector2DArray::append(qreal x, qreal y)
    \overload

    Appends (\a x, \a y) to this array of QVector2D values.
*/

/*!
    \fn void QVector2DArray::append(const QPointF& point)
    \overload

    Appends \a point to this array of QVector2D values.
*/

/*!
    \fn void QVector2DArray::append(const QPoint& point);
    \overload

    Appends \a point to this array of QVector2D values.
*/

/*!
    Multiplies the elements in this array of QVector2D values by
    the \a scale.

    \sa scaled()
*/
void QVector2DArray::scale(qreal scale)
{
    if (isDetached()) {
        // Modify the array in-place.
        int size = count();
        QVector2D *dst = data();
        for (int index = 0; index < size; ++index)
            *dst++ *= scale;
    } else {
        // Create a new array, translate the values, and assign.
        QArray<QVector2D> result;
        int size = count();
        const QVector2D *src = constData();
        QVector2D *dst = result.extend(size);
        for (int index = 0; index < size; ++index)
            *dst++ = *src++ * scale;
        *this = result;
    }
}
Beispiel #8
0
/*!
    Uploads the vertex data specified by previous addAttribute()
    calls into the GL server as a vertex buffer object.

    Returns true if the data could be uploaded; false if vertex buffer
    objects are not supported or there is insufficient memory to complete
    the request.  Returns true if the data was already uploaded.

    Once the vertex data has been uploaded, the client-side copies of
    the data arrays will be released.  If the vertex data could not be
    uploaded, then it is retained client-side.  This way, regardless of
    whether the data could be uploaded or not, QGLPainter::setVertexBundle()
    can be used to support drawing of primitives using this object.

    \sa isUploaded(), addAttribute(), QGLPainter::setVertexBundle()
*/
bool QGLVertexBundle::upload()
{
    Q_D(QGLVertexBundle);
    QGLVertexBundleAttribute *attr;

    // Nothing to do if already uploaded or there are no attributes.
    if (d->buffer.isCreated())
        return true;
    if (d->attributes.isEmpty())
        return false;

    // Create the VBO in the GL server and bind it.
    if (!d->buffer.create())
        return false;
    d->buffer.bind();

    // If there is only one attribute, then realloc and write in one step.
    if (d->attributes.size() == 1) {
        attr = d->attributes[0];
        d->buffer.allocate(attr->value.data(),
                           attr->count() * attr->elementSize());
        attr->value.setOffset(0);
        attr->clear();
        d->buffer.release();
        return true;
    }

    // Calculate the total size of the VBO that we will need,
    // the maximum number of interleaved vertices, and the
    // interleaved stride.
    int size = 0;
    int stride = 0;
    int maxCount = 0;
    for (int index = 0; index < d->attributes.size(); ++index) {
        attr = d->attributes[index];
        int count = attr->count();
        if (count > maxCount)
            maxCount = count;
        int elemSize = attr->elementSize();
        size += count * elemSize;
        stride += elemSize;
    }
    int bufferSize = size;
    d->buffer.allocate(bufferSize);
    stride /= sizeof(float);

    // Determine how to upload the data, using a map if possible.
    // Interleave the data into the final buffer.  We do it in
    // sections so as to keep locality problems to a minimum.
    void *mapped = d->buffer.map(QOpenGLBuffer::WriteOnly);
    int offset = 0;
    QArray<float> temp;
    float *dst;
    if (mapped)
        dst = reinterpret_cast<float *>(mapped);
    else
        dst = temp.extend(1024);
    int sectionSize = 1024 / stride;
    for (int vertex = 0; vertex < maxCount; vertex += sectionSize) {
        int attrPosn = 0;
        for (int index = 0; index < d->attributes.size(); ++index) {
            attr = d->attributes[index];
            int count = attr->count() - vertex;
            if (count <= 0)
                continue;
            count = qMin(count, sectionSize);
            int components = attr->elementSize() / sizeof(float);
            vertexBufferInterleave
                (dst + attrPosn, stride,
                 reinterpret_cast<const float *>(attr->value.data()) +
                        vertex * components,
                 components, count);
            attrPosn += attr->elementSize() / sizeof(float);
        }
        size = sectionSize * stride;
        if (mapped) {
            dst += size;
        } else {
            size *= sizeof(float);
            if ((offset + size) > bufferSize)    // buffer overflow check
                size = bufferSize-offset;
            d->buffer.write(offset, dst, size);
            offset += size;
        }
    }
    offset = 0;
    for (int index = 0; index < d->attributes.size(); ++index) {
        attr = d->attributes[index];
        attr->value.setOffset(offset);
        attr->value.setStride(stride * sizeof(float));
        offset += attr->elementSize();
        attr->clear();
    }
    if (mapped)
        d->buffer.unmap();

    // Buffer is uploaded and ready to go.
    d->buffer.release();
    return true;
}