summaryrefslogtreecommitdiffstats
path: root/src/threed/geometry/qgeometrydata.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/threed/geometry/qgeometrydata.cpp')
-rw-r--r--src/threed/geometry/qgeometrydata.cpp2030
1 files changed, 0 insertions, 2030 deletions
diff --git a/src/threed/geometry/qgeometrydata.cpp b/src/threed/geometry/qgeometrydata.cpp
deleted file mode 100644
index 6ee4e181..00000000
--- a/src/threed/geometry/qgeometrydata.cpp
+++ /dev/null
@@ -1,2030 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation ([email protected])
-**
-** This file is part of the QtQuick3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qgeometrydata.h"
-#include "qlogicalvertex.h"
-#include "qglpainter.h"
-
-#include <QtOpenGL/qgl.h>
-#include <QtCore/qdebug.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QGeometryData
- \brief The QGeometryData class encapsulates sets of geometry data.
- \since 4.8
- \ingroup qt3d
- \ingroup qt3d::geometry
-
- The QGeometryData class encloses a number of data arrays
- that model most typical vertex data needs. The class provides a
- store for all of the data types in the QGL::VertexAttribute enumeration.
-
- \table
- \header
- \o QGL::VertexAttribute
- \o QGeometryData functions
- \row
- \o QGL::Position
- \o appendVertex(), vertex(), vertices()
- \row
- \o QGL::Normal
- \o appendNormal(), normal(), normals()
- \row
- \o QGL::Color
- \o appendColor(), colorRef(), colors()
- \row
- \o QGL::TextureCoord0 - QGL::TextureCoord3
- \o appendTexCoord(), texCoordRef(), texCoords()
- \row
- \o QGL::CustomVertex0 - QGL::CustomVertex1, QGL::UserVertex
- \o appendAttribute(), vector3DAttribute(), attributes()
- \endtable
-
- Additionally the class provides the following features:
- \list
- \o appendVertex() for adding a QLogicalVertex()
- \o logicalVertexAt() for return the data at an index as a QLogicalVertex()
- \o hasField() to find if a particular data type is present
- \o normalizeNormals() to reduce all normal vectors to unit length
- \o boundingBox() to find the bounds of the geometry
- \endlist
-
- It is up to the user of a QGeometryData instance to ensure that the
- data has an equal number of items in each field. For example, if five
- vertices are added and only two normals are added, the logical vertex at
- position 3 will be corrupt, since it does not have a normal.
-
- While data is being accumulated the counts of different fields will vary,
- since it may be convenient to add several vertices, then several normals,
- colors or attributes at a time. However when a logical vertex is
- constructed or when the data is sent to the GPU, counts of all fields
- must be equal.
-
- QGeometryData uses explicit sharing with lazy creation of internal
- data so that code like:
- \code
- QGeometryData myData;
- if (processed)
- myData = processedData();
- \endcode
- is very inexpensive, since the first declaration and initialization
- does not cause internal data to be created (only to be overwritten by the
- assignment operation).
-
- Since QGeometryData is explicitly shared, variables of type
- QGeometryData behave like references, and the underlying data is modified
- by calling a non-const function on any variable which shares that data.
-
- To force an explicit copy call the detach() function.
-*/
-
-/*!
- \typedef QGL::IndexArray
-
- This is a convenience for either QArray<ushort> (OpenGL/ES) or
- QArray<int> (desktop OpenGL).
-*/
-
-class QGeometryDataPrivate
-{
-public:
- QGeometryDataPrivate();
- ~QGeometryDataPrivate();
- QGeometryDataPrivate *clone() const;
-
- QBasicAtomicInt ref;
-
- QVector3DArray vertices;
- QVector3DArray normals;
- QArray<QColor4ub> colors;
- QList<QCustomDataArray> attributes;
- QList<QVector2DArray> textures;
- QGL::IndexArray indices;
- QGLVertexBundle vertexBundle;
- QGLIndexBuffer indexBuffer;
- bool uploadsViable;
- bool modified;
- QBox3D bb;
- static const int ATTR_CNT = 32;
- quint32 fields;
- qint8 key[ATTR_CNT];
- quint8 size[ATTR_CNT];
- int count;
- int reserved;
- bool boxValid;
- QGeometryData::BufferStrategy bufferStrategy;
-};
-
-QGeometryDataPrivate::QGeometryDataPrivate()
- : uploadsViable(true)
- , modified(false)
- , fields(0)
- , count(0)
- , reserved(-1)
- , boxValid(true)
- , bufferStrategy(QGeometryData::BufferIfPossible | QGeometryData::KeepClientData)
-{
- ref = 0;
- qMemSet(key, -1, ATTR_CNT);
- qMemSet(size, 0, ATTR_CNT);
-}
-
-QGeometryDataPrivate::~QGeometryDataPrivate()
-{
-}
-
-QGeometryDataPrivate *QGeometryDataPrivate::clone() const
-{
- QGeometryDataPrivate *temp = new QGeometryDataPrivate;
- temp->vertices = vertices;
- temp->normals = normals;
- temp->colors = colors;
- temp->attributes = attributes;
- temp->textures = textures;
- temp->indices = indices;
- temp->vertexBundle = vertexBundle;
- temp->indexBuffer = indexBuffer;
- temp->uploadsViable = uploadsViable;
- temp->modified = modified;
- temp->bb = bb;
- temp->fields = fields;
- qMemCopy(temp->key, key, ATTR_CNT);
- qMemCopy(temp->size, size, ATTR_CNT);
- temp->count = count;
- temp->reserved = reserved;
- temp->boxValid = boxValid;
- temp->bufferStrategy = bufferStrategy;
- return temp;
-}
-
-/*!
- \fn quint32 QGL::fieldMask(QGL::VertexAttribute attribute)
- \relates QGeometryData
- Returns an unsigned integer mask from the \a attribute.
-
- \sa QGeometryData::fields()
-*/
-
-/*!
- \enum QGeometryData::BufferStrategyFlags
-
- This enum serves to describe how management of the data is handled
- with respect to vertex buffer objects. The strategies are essentially a
- combination of whether the client data is kept around after it has been
- successfully uploaded to the GPU; and whether an upload is attempted at
- all.
-
- If the data set is very small it may be pointless to use up a VBO, hence
- in this case KeepClientData may be used resulting in no attempt to upload
- the data and client side arrays used instead.
-
- \value InvalidStrategy No valid strategy has been specified.
- \value KeepClientData Keep the client data, even after successful upload to the GPU.
- \value BufferIfPossible Try to upload the data to the GPU.
-*/
-
-/*!
- Construct an empty QGeometryData
-*/
-QGeometryData::QGeometryData()
- : d(0)
-{
-}
-
-/*!
- Construct QGeometryData as a copy of \a other
-*/
-QGeometryData::QGeometryData(const QGeometryData &other)
- : d(other.d)
-{
- if (d)
- d->ref.ref();
-}
-
-/*!
- Construct an empty QGeometryData with the \a fields enabled.
-*/
-QGeometryData::QGeometryData(quint32 fields)
- : d(new QGeometryDataPrivate)
-{
- d->ref.ref();
- const quint32 mask = 0x01;
- for (int field = 0; fields; ++field, fields >>= 1)
- {
- if (!(mask & fields)) continue;
- QGL::VertexAttribute attr = static_cast<QGL::VertexAttribute>(field);
- enableField(attr);
- }
-}
-
-/*!
- Destroys this QGeometryData recovering any resources.
-*/
-QGeometryData::~QGeometryData()
-{
- if (d && !d->ref.deref())
- delete d;
-}
-
-/*!
- Assigns this QGeometryData to be a copy of \a other.
-*/
-QGeometryData &QGeometryData::operator=(const QGeometryData &other)
-{
- if (d != other.d)
- {
- if (d && !d->ref.deref())
- delete d;
- d = other.d;
- if (d)
- d->ref.ref();
- }
- return *this;
-}
-
-/*!
- Appends the geometry in \a data to this. If this is empty, then all
- fields of \a data are appended; otherwise (when this has existing fields)
- only those fields that exist in both are appended.
-
- This does not change the indices - to reference the new geometry add
- indices via the appendIndices() functions.
-*/
-void QGeometryData::appendGeometry(const QGeometryData &data)
-{
- if (data.d && data.count())
- {
- detach();
- d->modified = true;
- d->boxValid = false;
- int cnt = data.d->count;
- const quint32 mask = 0x01;
- quint32 fields = d->fields | data.fields();
- d->fields = fields;
- for (int field = 0; fields; ++field, fields >>= 1)
- {
- if (mask & fields)
- {
- QGL::VertexAttribute attr = static_cast<QGL::VertexAttribute>(field);
- enableField(attr); // might not be enabled if we had NO fields
- if (attr < QGL::TextureCoord0)
- {
- if (attr == QGL::Position)
- d->vertices.append(data.d->vertices);
- else if (attr == QGL::Normal)
- d->normals.append(data.d->normals);
- else // colors
- d->colors.append(data.d->colors);
- }
- else if (attr < QGL::CustomVertex0)
- {
- d->textures[d->key[attr]].append(data.texCoords(attr));
- }
- else
- {
- d->attributes[d->key[attr]].append(data.attributes(attr));
- }
- }
- }
- d->count += cnt;
- }
-}
-
-/*!
- Appends all the data fields in QLogicalVertex \a v to this
- QGeometryData object.
-*/
-int QGeometryData::appendVertex(const QLogicalVertex &v)
-{
- create();
- d->modified = true;
- if (d->boxValid)
- d->bb.unite(v.vertex());
- quint32 fields = v.fields();
- const quint32 mask = 0x01;
- for (int field = 0; fields; ++field, fields >>= 1)
- {
- if (mask & fields)
- {
- QGL::VertexAttribute attr = static_cast<QGL::VertexAttribute>(field);
- if (attr < QGL::TextureCoord0)
- {
- if (attr == QGL::Position)
- appendVertex(v.vertex());
- else if (attr == QGL::Normal)
- appendNormal(v.normal());
- else
- appendColor(v.color());
- }
- else if (attr < QGL::CustomVertex0)
- {
- appendTexCoord(v.texCoord(attr), attr);
- }
- else
- {
- appendAttribute(v.attribute(attr), attr);
- }
- }
- }
- return d->count - 1;
-}
-
-/*!
- Returns a QLogicalVertex that references the \a{i}'th logical vertex
- of this geometry.
-*/
-QLogicalVertex QGeometryData::logicalVertexAt(int i) const
-{
- return QLogicalVertex(*this, i);
-}
-
-/*!
- Normalize all the normal vectors in this geometry to unit length.
-*/
-void QGeometryData::normalizeNormals()
-{
- check();
- if (d) // nothng to do if its null
- {
- create();
- d->modified = true;
- if (hasField(QGL::Normal))
- {
- for (int i = 0; i < d->normals.count(); ++i)
- d->normals[i].normalize();
- }
- }
-}
-
-/*!
- Calculate and return a bounding box for the vertex data in this geometry.
-*/
-QBox3D QGeometryData::boundingBox() const
-{
- QBox3D box;
- if (d)
- {
- if (d->boxValid)
- {
- box = d->bb;
- }
- else
- {
- for (int i = 0; i < d->count; ++i)
- box.unite(d->vertices.at(i));
- d->bb = box;
- }
- }
- return box;
-}
-
-/*!
- Returns the coordinates of the center of the geometry.
-
- The center is calculated as the centroid or geometric barycenter
- of the vertices (the average of the vertices). For a convex hull this
- is guaranteed to be inside the figure.
-*/
-QVector3D QGeometryData::center() const
-{
- QVector3D center;
- for (int i = 0; i < d->vertices.count(); ++i)
- center += d->vertices.at(i);
- return center / (float)d->vertices.count();
-}
-
-/*!
- Returns a copy of this geometry data with elements in reverse order.
-*/
-QGeometryData QGeometryData::reversed() const
-{
- QGeometryData r;
- for (int i = count() - 1; i >= 0; --i)
- r.appendVertex(logicalVertexAt(i));
- return r;
-}
-
-/*!
- Returns a copy of this geometry data with QGL::Position data translated by
- the vector \a t. The other fields are unchanged.
-*/
-QGeometryData QGeometryData::translated(const QVector3D &t) const
-{
- QGeometryData r(*this);
- r.detach();
- for (int i = 0; i < count(); ++i)
- {
- r.vertex(i) = r.vertexAt(i) + t;
- }
- return r;
-}
-
-/*!
- Modifies this geometry data by generating texture data based on QGL::Position
- values. If \a orientation is Qt::Horizontal (the default) then x-coordinate
- values are generated, and y-coordinate values are set to 0.0; otherwise
- y-coordinate values are generated and x-coordinate values are set to 0.0.
- The values are appended to the texture coordinate \a field.
-
- The method of calculation is based on the assumption that the vertex data
- is a list of extents which span across the texture space horizontally, from
- x = 0.0 to x = 1.0, in the case of Qt::Horizontal; or vertically in the
- case of Qt::Vertical. The texture space of 1.0 is divided up proportionately
- by the length of each extent.
-
- \image texture-coords-gen.png
-
- In this diagram the large blue numbers are the lengths of each extent, and
- the texture coordinates generated are shown as \c{t(7/16, 1)} and so on.
-
- Thus the texture coordinate t0 for vertex v0, is 0.0; t1 for vertex v1 is
- \c{(v1 - v0).length() / totalLength} and so on.
-
- The code to produce the texture coordinates for the quads in the image is:
- \code
- QGeometryData top;
-
- // add data to the primitive
- top.appendVertex(QVector3D(0.0, 0.0, 0.0));
- top.appendVertex(QVector3D(6.0, 3.6, 0.0)); // (v1 - v0).length() = 7.0
- top.appendVertex(QVector3D(10.0, 0.6, 0.0)); // (v2 - v1).length() = 5.0
- top.appendVertex(QVector3D(13.0, 3.24, 0.0)); // (v3 - v2).length() = 4.0
-
- // generate x (Qt::Horizontal) texture coordinates over the primitive
- top.generateTextureCoordinates(); // spread over 7 + 5 + 4 = 16
-
- // make a copy translated down, the copy has y texture coordinates all 0
- QGeometryData bottom = top.translated(QVector3D(0, 0, -1));
-
- // now modify the top so its y texture coordinates are all 1
- for (int i = 0; i < top.count(); ++i)
- top.texCoordRef(QGL::TextureCoord0).setY(1.0);
-
- displayList->addQuadsZipped(top, bottom);
- \endcode
-*/
-void QGeometryData::generateTextureCoordinates(Qt::Orientation orientation, QGL::VertexAttribute field)
-{
- QArray<qreal> extents;
- extents.append(0.0);
- qreal totalExtents = 0.0;
- QArray<QVector3D> v = vertices();
- for (int i = 0; i < v.count() - 1; ++i)
- {
- int n = (i + 1) % v.count();
- QVector3D e = v[n] - v[i];
- qreal extent = e.length();
- totalExtents += extent;
- extents.append(totalExtents);
- }
- if (hasField(field))
- clear(field);
- if (orientation == Qt::Horizontal)
- {
- for (int i = 0; i < v.count(); ++i)
- appendTexCoord(QVector2D(extents[i] / totalExtents, 0.0), field);
- }
- else
- {
- for (int i = 0; i < v.count(); ++i)
- appendTexCoord(QVector2D(0.0, extents[i] / totalExtents), field);
- }
-}
-
-/*!
- Returns a QGeometryData instance containing alternating vertices from
- this geometry and \a other. The resulting geometry contains N vertices
- where \c{N == qMin(count(), other.count())}, and has only the fields
- that are in both geometries.
-*/
-QGeometryData QGeometryData::interleavedWith(const QGeometryData &other) const
-{
- QGeometryData res;
- check();
- other.check();
- if (d && other.d)
- {
- int cnt = qMax(d->count, other.d->count);
- const quint32 mask = 0x01;
- quint32 fields = d->fields & other.d->fields;
- for (int field = 0; fields; ++field, fields >>= 1)
- {
- if (mask & fields)
- {
- QGL::VertexAttribute attr = static_cast<QGL::VertexAttribute>(field);
- res.enableField(attr);
- if (attr < QGL::TextureCoord0)
- {
- if (attr == QGL::Position)
- {
- QArray<QVector3D> tmp;
- for (int i = 0; i < cnt; ++i)
- {
- tmp.append(d->vertices.at(i));
- tmp.append(other.d->vertices.at(i));
- }
- res.d->vertices = tmp;
- }
- else if (attr == QGL::Normal)
- {
- QArray<QVector3D> tmp;
- for (int i = 0; i < cnt; ++i)
- {
- tmp.append(d->normals.at(i));
- tmp.append(other.d->normals.at(i));
- }
- res.d->normals = tmp;
- }
- else // colors
- {
- QArray<QColor4ub> tmp;
- for (int i = 0; i < cnt; ++i)
- {
- tmp.append(d->colors.at(i));
- tmp.append(other.d->colors.at(i));
- }
- res.d->colors = tmp;
- }
- }
- else if (attr < QGL::CustomVertex0)
- {
- QArray<QVector2D> tmp;
- const QArray<QVector2D> txa = d->textures.at(d->key[attr]);
- const QArray<QVector2D> txb = other.d->textures.at(other.d->key[attr]);
- for (int i = 0; i < cnt; ++i)
- {
- tmp.append(txa.at(i));
- tmp.append(txb.at(i));
- }
- res.d->textures[d->key[attr]] = tmp;
- }
- else
- {
- QCustomDataArray tmp;
- const QCustomDataArray ata = d->attributes.at(d->key[attr]);
- const QCustomDataArray atb = other.d->attributes.at(other.d->key[attr]);
- for (int i = 0; i < cnt; ++i)
- {
- tmp.append(ata.at(i));
- tmp.append(atb.at(i));
- }
- res.d->attributes[d->key[attr]] = tmp;
- }
- }
- }
- res.d->count = cnt * 2;
- }
- return res;
-}
-
-/*!
- Sets this QGeometryData to contain alternating vertices from
- this geometry and \a other. The resulting geometry contains \c{N * 2} vertices
- where \c{N == qMin(count(), other.count())}, and has only the fields
- that are in both geometries.
-*/
-void QGeometryData::interleaveWith(const QGeometryData &other)
-{
- check();
- other.check();
- if (d && other.d)
- {
- create();
- d->modified = true;
- d->boxValid = false;
- int cnt = qMin(d->count, other.d->count);
- const quint32 mask = 0x01;
- quint32 fields = d->fields & other.d->fields;
- for (int field = 0; fields; ++field, fields >>= 1)
- {
- if (mask & fields)
- {
- QGL::VertexAttribute attr = static_cast<QGL::VertexAttribute>(field);
- if (attr < QGL::TextureCoord0)
- {
- if (attr == QGL::Position)
- {
- QArray<QVector3D> tmp;
- for (int i = 0; i < cnt; ++i)
- {
- tmp.append(d->vertices.at(i));
- tmp.append(other.d->vertices.at(i));
- }
- d->vertices = tmp;
- }
- else if (attr == QGL::Normal)
- {
- QArray<QVector3D> tmp;
- for (int i = 0; i < cnt; ++i)
- {
- tmp.append(d->normals.at(i));
- tmp.append(other.d->normals.at(i));
- }
- d->normals = tmp;
- }
- else // colors
- {
- QArray<QColor4ub> tmp;
- for (int i = 0; i < cnt; ++i)
- {
- tmp.append(d->colors.at(i));
- tmp.append(other.d->colors.at(i));
- }
- d->colors = tmp;
- }
- }
- else if (attr < QGL::CustomVertex0)
- {
- QArray<QVector2D> tmp;
- const QArray<QVector2D> txa = d->textures.at(d->key[attr]);
- const QArray<QVector2D> txb = other.d->textures.at(other.d->key[attr]);
- for (int i = 0; i < cnt; ++i)
- {
- tmp.append(txa.at(i));
- tmp.append(txb.at(i));
- }
- d->textures[d->key[attr]] = tmp;
- }
- else
- {
- QCustomDataArray tmp;
- const QCustomDataArray ata = d->attributes.at(d->key[attr]);
- const QCustomDataArray atb = other.d->attributes.at(other.d->key[attr]);
- for (int i = 0; i < cnt; ++i)
- {
- tmp.append(ata.at(i));
- tmp.append(atb.at(i));
- }
- d->attributes[d->key[attr]] = tmp;
- }
- }
- }
- d->count = cnt * 2;
- }
-}
-
-/*!
- Clear all data structures. The actual fields are retained, but they
- have no contents.
- \code
- QGeometryData data;
- data.appendVertex(a);
- data.appendTexCoord(t);
-
- // prints "1"
- qDebug() << data.count();
-
- // x == a
- QVector3D x = data.vertexAt(0);
-
- quint32 flds = QGL::fieldMask(QGL::Position) | QGL::fieldMask(QGL::TextureCoord0);
- qDebug() << (flds == data.fields()); // prints "true"
-
- data.clear();
- qDebug() << data.count(); // prints "0"
- QVector3D x = data.vertexAt(0); // asserts - no data in vertices
- qDebug() << (flds == data.fields()); // still prints "true"
- \endcode
-
- To clear a specific field and its data use \c{data.clear(field)} below.
-
- To clear all fields and data, simply set this to an empty geometry:
- \code
- data = QGeometryData();
- \endcode
- */
-void QGeometryData::clear()
-{
- if (d)
- {
- create();
- d->modified = true;
- d->bb = QBox3D();
- d->boxValid = true;
- const quint32 mask = 0x01;
- quint32 fields = d->fields;
- for (int field = 0; fields; ++field, fields >>= 1)
- {
- if (mask & fields)
- {
- QGL::VertexAttribute attr = static_cast<QGL::VertexAttribute>(field);
- if (attr < QGL::TextureCoord0)
- {
- if (attr == QGL::Position)
- d->vertices.clear();
- else if (attr == QGL::Normal)
- d->normals.clear();
- else
- d->colors.clear();
- }
- else if (attr < QGL::CustomVertex0)
- {
- d->textures[d->key[field]].clear();
- }
- else
- {
- d->attributes[d->key[field]].clear();
- }
- }
- }
- d->count = 0;
- }
-}
-
-/*!
- Clears the data from \a field, and removes the field. After this call
- hasField() will return false for this field.
-*/
-void QGeometryData::clear(QGL::VertexAttribute field)
-{
- if (d && (QGL::fieldMask(field) & d->fields))
- {
- create();
- d->modified = true;
- if (field == QGL::Position)
- {
- d->bb = QBox3D();
- d->boxValid = true;
- }
- QGL::VertexAttribute attr = static_cast<QGL::VertexAttribute>(field);
- if (attr < QGL::TextureCoord0)
- {
- if (attr == QGL::Position)
- d->vertices.clear();
- else if (attr == QGL::Normal)
- d->normals.clear();
- else
- d->colors.clear();
- }
- else if (attr < QGL::CustomVertex0)
- {
- d->textures[d->key[field]].clear();
- }
- else
- {
- d->attributes[d->key[field]].clear();
- }
- d->key[field] = -1;
- d->fields = d->fields & ~QGL::fieldMask(field);
- }
-}
-
-/*!
- Sets the geometry data to handle an \a amount of data. This is generally
- not required unless its anticipated that a large amount of data will be
- appended and realloc overhead is desired to be avoided. If \a amount is
- less than the amount already reserved, or if this object has
- more than the \a amount of data items, then this function exits without
- doing anything. This function will never delete data.
-*/
-void QGeometryData::reserve(int amount)
-{
- if (d && (d->reserved > amount || d->reserved < d->count))
- return;
- create();
- d->reserved = amount;
- const quint32 mask = 0x01;
- quint32 fields = d->fields;
- for (int field = 0; fields; ++field, fields >>= 1)
- {
- if (mask & fields)
- {
- QGL::VertexAttribute attr = static_cast<QGL::VertexAttribute>(field);
- if (attr < QGL::TextureCoord0)
- {
- if (attr == QGL::Position)
- d->vertices.reserve(amount);
- else if (attr == QGL::Normal)
- d->normals.reserve(amount);
- else
- d->colors.reserve(amount);
- }
- else if (attr < QGL::CustomVertex0)
- {
- d->textures[d->key[field]].reserve(amount);
- }
- else
- {
- d->attributes[d->key[field]].reserve(amount);
- }
- }
- }
-}
-
-/*!
- Draws this geometry on the \a painter, from \a start for \a count elements
- in \a mode. The drawing \a mode is by default QGL::Triangles. This function
- Also calls the upload() method to ensure that the geometry is resident on
- the graphics hardware if appropriate.
-
- If the geometry is a point or line, then the \a drawWidth value specified the
- width/size of the line/point.
-*/
-void QGeometryData::draw(QGLPainter *painter, int start, int count, GLenum mode, qreal drawWidth)
-{
- if (d && d->indices.size() && d->count)
- {
- upload();
- painter->clearAttributes();
- if (mode==QGL::Points) {
-#if !defined(QT_OPENGL_ES_2)
- ::glPointSize(drawWidth);
-#endif
- } else if (mode==QGL::LineStrip || mode == QGL::Lines) {
- ::glLineWidth(drawWidth);
- }
- painter->setVertexBundle(d->vertexBundle);
- if (count == 0)
- count = d->indexBuffer.indexCount();
- painter->draw(QGL::DrawingMode(mode), d->indexBuffer, start, count);
- }
-}
-
-/*!
- Uploads this geometry data to the graphics hardware if appropriate. If the
- data is already uploaded and has not been modified since it was last
- uploaded, then this function does nothing.
-
- If the bufferStrategy() does not specify QGL::BufferIfPossible then this
- function does nothing.
-
- If the data was successfully uploaded, and the bufferStrategy() does not
- specify QGL::KeepClientData then the data will be removed with a call to
- the clear() function.
-
- If the data was successfully uploaded, on this call or previously, then this
- function will return true. Otherwise it returns false.
-*/
-bool QGeometryData::upload()
-{
- bool vboUploaded = false;
- bool iboUploaded = false;
-
- if (!d)
- return false;
- if (!d->modified)
- return d->vertexBundle.isUploaded() && d->indexBuffer.isUploaded();
-
- check();
-
- // Need to recreate the buffers from the modified data.
- d->vertexBundle = QGLVertexBundle();
- d->indexBuffer = QGLIndexBuffer();
-
- // Copy the geometry data to the vertex buffer.
- const quint32 mask = 0x01;
- quint32 fields = d->fields;
- for (int field = 0; fields; ++field, fields >>= 1)
- {
- if (!(mask & fields))
- continue;
- QGL::VertexAttribute attr = static_cast<QGL::VertexAttribute>(field);
- if (attr == QGL::Position)
- d->vertexBundle.addAttribute(attr, d->vertices);
- else if (attr == QGL::Normal)
- d->vertexBundle.addAttribute(attr, d->normals);
- else if (attr == QGL::Color)
- d->vertexBundle.addAttribute(attr, d->colors);
- else if (attr < QGL::CustomVertex0)
- d->vertexBundle.addAttribute(attr, d->textures.at(d->key[field]));
- else
- d->vertexBundle.addAttribute(attr, d->attributes.at(d->key[field]));
- }
-
- // Upload the buffer if requested, otherwise keep it client-side.
- // Note: QGLVertexBundle will act as a client-side buffer if not uploaded.
- if ((d->bufferStrategy & BufferIfPossible) != 0)
- {
- if (d->vertexBundle.upload())
- vboUploaded = true;
- }
-
- // Copy the geometry data to the index buffer and upload if requested.
- d->indexBuffer.setIndexes(d->indices);
- if ((d->bufferStrategy & BufferIfPossible) != 0)
- {
- if (d->indexBuffer.upload())
- iboUploaded = true;
- }
-
- d->modified = false;
-
- if (!(d->bufferStrategy & KeepClientData) && vboUploaded && iboUploaded)
- clear();
-
- return vboUploaded && iboUploaded;
-}
-
-/*!
- Sets the buffer \a strategy for this geometry.
-
- \sa bufferStrategy()
-*/
-void QGeometryData::setBufferStrategy(QGeometryData::BufferStrategy strategy)
-{
- if (!d || d->bufferStrategy != strategy)
- {
- create();
- d->modified = true;
- d->bufferStrategy = strategy;
- }
-}
-
-/*!
- Returns the buffer strategy for this geometry. The default is
- \c{QGL::BufferIfPossible | QGL::KeepClientData}.
-
- \sa setBufferStrategy()
-*/
-QGeometryData::BufferStrategy QGeometryData::bufferStrategy() const
-{
- if (d)
- return d->bufferStrategy;
- return InvalidStrategy;
-}
-
-/*!
- Returns a reference to the vertex buffer for this geometry.
-
- \sa indexBuffer()
-*/
-QGLVertexBundle QGeometryData::vertexBundle() const
-{
- return d->vertexBundle;
-}
-
-/*!
- Returns a reference to the index buffer for this geometry.
-
- \sa vertexBundle()
-*/
-QGLIndexBuffer QGeometryData::indexBuffer() const
-{
- return d->indexBuffer;
-}
-
-/*!
- Appends \a index to the vertex index array.
-
- \sa appendIndices(), indices()
-*/
-void QGeometryData::appendIndex(int index)
-{
- create();
- d->modified = true;
- d->indices.append(index);
-}
-
-/*!
- Appends \a index1, \a index2, and \a index3 to the geometry's
- index array.
-
- \sa appendIndex(), indices()
-*/
-void QGeometryData::appendIndices(int index1, int index2, int index3)
-{
- create();
- d->modified = true;
- d->indices.append(index1, index2, index3);
-}
-
-/*!
- Returns the index array that was created by appendIndex().
-
- \sa appendIndex(), appendIndices()
-*/
-QGL::IndexArray QGeometryData::indices() const
-{
- if (d)
- return d->indices;
- else
- return QGL::IndexArray();
-}
-
-/*!
- Appends the \a indices to the geometry's index array.
-*/
-void QGeometryData::appendIndices(const QGL::IndexArray &indices)
-{
- create();
- d->modified = true;
- d->indices.append(indices);
-}
-
-/*!
- Append the point \a v0 to this geometry data as a position field.
-*/
-void QGeometryData::appendVertex(const QVector3D &v0)
-{
- create();
- d->modified = true;
- enableField(QGL::Position);
- d->vertices.append(v0);
- if (d->boxValid)
- d->bb.unite(v0);
- d->count = qMax(d->count, d->vertices.count());
-}
-
-/*!
- Append the points \a v0 and \a v1 to this geometry data as position fields.
-*/
-void QGeometryData::appendVertex(const QVector3D &v0, const QVector3D &v1)
-{
- create();
- d->modified = true;
- enableField(QGL::Position);
- d->vertices.append(v0, v1);
- if (d->boxValid)
- {
- d->bb.unite(v0);
- d->bb.unite(v1);
- }
- d->count = qMax(d->count, d->vertices.count());
-}
-
-/*!
- Append the points \a v0, \a v1 and \a v2 to this geometry data as position fields.
-*/
-void QGeometryData::appendVertex(const QVector3D &v0, const QVector3D &v1, const QVector3D &v2)
-{
- create();
- d->modified = true;
- enableField(QGL::Position);
- d->vertices.append(v0, v1, v2);
- if (d->boxValid)
- {
- d->bb.unite(v0);
- d->bb.unite(v1);
- d->bb.unite(v2);
- }
- d->count = qMax(d->count, d->vertices.count());
-}
-
-/*!
- Append the points \a v0, \a v1, \a v2 and \a v3 to this geometry data as position fields.
-*/
-void QGeometryData::appendVertex(const QVector3D &v0, const QVector3D &v1, const QVector3D &v2, const QVector3D &v3)
-{
- create();
- d->modified = true;
- enableField(QGL::Position);
- d->vertices.append(v0, v1, v2, v3);
- if (d->boxValid)
- {
- d->bb.unite(v0);
- d->bb.unite(v1);
- d->bb.unite(v2);
- d->bb.unite(v3);
- }
- d->count = qMax(d->count, d->vertices.count());
-}
-
-/*!
- Append the float \a a0 to this geometry data, as an attribute \a field.
-*/
-void QGeometryData::appendAttribute(float a0, QGL::VertexAttribute field)
-{
- create();
- d->modified = true;
- enableField(field);
- d->attributes[d->key[field]].append(a0);
- d->count = qMax(d->count, d->attributes[d->key[field]].count());
-}
-
-/*!
- Append the float \a a0 and \a a1 to this geometry data, as an attribute \a field.
-*/
-void QGeometryData::appendAttribute(float a0, float a1, QGL::VertexAttribute field)
-{
- create();
- d->modified = true;
- enableField(field);
- d->attributes[d->key[field]].append(a0, a1);
- d->count = qMax(d->count, d->attributes[d->key[field]].count());
-}
-
-/*!
- Append the floats \a a0, \a a1 and \a a2 to this geometry data, as attribute \a field.
-*/
-void QGeometryData::appendAttribute(float a0, float a1, float a2, QGL::VertexAttribute field)
-{
- create();
- d->modified = true;
- enableField(field);
- d->attributes[d->key[field]].append(a0, a1, a2);
- d->count = qMax(d->count, d->attributes[d->key[field]].count());
-}
-
-/*!
- Append the floats \a a0, \a a1, \a a2 and \a a3 to this geometry data, as attribute \a field.
-*/
-void QGeometryData::appendAttribute(float a0, float a1, float a2, float a3, QGL::VertexAttribute field)
-{
- create();
- d->modified = true;
- enableField(field);
- d->attributes[d->key[field]].append(a0, a1, a2, a3);
- d->count = qMax(d->count, d->attributes[d->key[field]].count());
-}
-
-/*!
- Append the 2D point \a a to this geometry data, as an attribute \a field.
-*/
-void QGeometryData::appendAttribute(const QVector2D &a, QGL::VertexAttribute field)
-{
- create();
- d->modified = true;
- enableField(field);
- if (d->attributes.at(d->key[field]).isEmpty())
- d->attributes[d->key[field]].setElementType(QCustomDataArray::Vector2D);
- d->attributes[d->key[field]].append(a);
- d->count = qMax(d->count, d->attributes[d->key[field]].count());
-}
-
-/*!
- Append the 3D point \a v to this geometry data, as an attribute \a field.
-*/
-void QGeometryData::appendAttribute(const QVector3D &v, QGL::VertexAttribute field)
-{
- create();
- d->modified = true;
- enableField(field);
- if (d->attributes.at(d->key[field]).isEmpty())
- d->attributes[d->key[field]].setElementType(QCustomDataArray::Vector3D);
- d->attributes[d->key[field]].append(v);
- d->count = qMax(d->count, d->attributes[d->key[field]].count());
-}
-
-/*!
- Append the variant value \a a to this geometry data, as an attribute \a field.
-*/
-void QGeometryData::appendAttribute(const QVariant &a, QGL::VertexAttribute field)
-{
- create();
- d->modified = true;
- enableField(field);
- if (d->attributes.at(d->key[field]).isEmpty())
- {
- // floats and doubles get handled "automatically" - float is default
- if (a.type() == QVariant::Vector2D)
- d->attributes[d->key[field]].setElementType(QCustomDataArray::Vector2D);
- else if (a.type() == QVariant::Vector3D)
- d->attributes[d->key[field]].setElementType(QCustomDataArray::Vector3D);
- else if (a.type() == QVariant::Vector4D)
- d->attributes[d->key[field]].setElementType(QCustomDataArray::Vector4D);
- else if (a.type() == QVariant::Color)
- d->attributes[d->key[field]].setElementType(QCustomDataArray::Color);
- else
- Q_ASSERT_X(false, "QGeometryData::appendAttribute", "bad type");
- }
- d->attributes[d->key[field]].append(a);
- d->count = qMax(d->count, d->attributes[d->key[field]].count());
-}
-
-/*!
- Append the vector \a n0 to this geometry data, as a lighting normal.
-*/
-void QGeometryData::appendNormal(const QVector3D &n0)
-{
- create();
- d->modified = true;
- enableField(QGL::Normal);
- d->normals.append(n0);
- d->count = qMax(d->count, d->normals.count());
-}
-
-/*!
- Append the vectors \a n0 and \a n1 to this geometry data, as lighting normals.
-*/
-void QGeometryData::appendNormal(const QVector3D &n0, const QVector3D &n1)
-{
- create();
- d->modified = true;
- enableField(QGL::Normal);
- d->normals.append(n0, n1);
- d->count = qMax(d->count, d->normals.count());
-}
-
-/*!
- Append the vectors \a n0, \a n1 and \a n2 to this geometry data, as lighting normals.
-*/
-void QGeometryData::appendNormal(const QVector3D &n0, const QVector3D &n1, const QVector3D &n2)
-{
- create();
- d->modified = true;
- enableField(QGL::Normal);
- d->normals.append(n0, n1, n2);
- d->count = qMax(d->count, d->normals.count());
-}
-
-/*!
- Append the vectors \a n0, \a n1, \a n2 and \a n3 to this geometry data, as lighting normals.
-*/
-void QGeometryData::appendNormal(const QVector3D &n0, const QVector3D &n1, const QVector3D &n2, const QVector3D &n3)
-{
- create();
- d->modified = true;
- enableField(QGL::Normal);
- d->normals.append(n0, n1, n2, n3);
- d->count = qMax(d->count, d->normals.count());
-}
-
-/*!
- Append the point \a t0 to this geometry data, as an texture \a field.
-*/
-void QGeometryData::appendTexCoord(const QVector2D &t0, QGL::VertexAttribute field)
-{
- create();
- d->modified = true;
- enableField(field);
- d->textures[d->key[field]].append(t0);
- d->count = qMax(d->count, d->textures[d->key[field]].count());
-}
-
-/*!
- Append the points \a t0 and \a t1 to this geometry data, as texture \a{field}s.
-*/
-void QGeometryData::appendTexCoord(const QVector2D &t0, const QVector2D &t1, QGL::VertexAttribute field)
-{
- create();
- d->modified = true;
- enableField(field);
- d->textures[d->key[field]].append(t0, t1);
- d->count = qMax(d->count, d->textures[d->key[field]].count());
-}
-
-/*!
- Append the points \a t0, \a t1 and \a t2 to this geometry data, as texture \a{field}s.
-*/
-void QGeometryData::appendTexCoord(const QVector2D &t0, const QVector2D &t1, const QVector2D &t2, QGL::VertexAttribute field)
-{
- create();
- d->modified = true;
- enableField(field);
- d->textures[d->key[field]].append(t0, t1, t2);
- d->count = qMax(d->count, d->textures[d->key[field]].count());
-}
-
-/*!
- Append the points \a t0, \a t1, \a t2 and \a t3 to this geometry data, as texture \a{field}s.
-*/
-void QGeometryData::appendTexCoord(const QVector2D &t0, const QVector2D &t1, const QVector2D &t2, const QVector2D &t3, QGL::VertexAttribute field)
-{
- create();
- d->modified = true;
- enableField(field);
- d->textures[d->key[field]].append(t0, t1, t2, t3);
- d->count = qMax(d->count, d->textures[d->key[field]].count());
-}
-
-/*!
- Append the color \a c0 to this geometry data, as an color field.
-*/
-void QGeometryData::appendColor(const QColor4ub &c0)
-{
- create();
- d->modified = true;
- enableField(QGL::Color);
- d->colors.append(c0);
- d->count = qMax(d->count, d->colors.count());
-}
-
-/*!
- Append the color \a c0 and \a c1 to this geometry data, as color fields.
-*/
-void QGeometryData::appendColor(const QColor4ub &c0, const QColor4ub &c1)
-{
- create();
- d->modified = true;
- enableField(QGL::Color);
- d->colors.append(c0, c1);
- d->count = qMax(d->count, d->colors.count());
-}
-
-/*!
- Append the color \a c0, \a c1 and \a c2 to this geometry data, as color fields.
-*/
-void QGeometryData::appendColor(const QColor4ub &c0, const QColor4ub &c1, const QColor4ub &c2)
-{
- create();
- d->modified = true;
- enableField(QGL::Color);
- d->colors.append(c0, c1, c2);
- d->count = qMax(d->count, d->colors.count());
-}
-
-/*!
- Append the color \a c0, \a c1, \a c2 and \a c3 to this geometry data, as color fields.
-*/
-void QGeometryData::appendColor(const QColor4ub &c0, const QColor4ub &c1, const QColor4ub &c2, const QColor4ub &c3)
-{
- create();
- d->modified = true;
- enableField(QGL::Color);
- d->colors.append(c0, c1, c2, c3);
- d->count = qMax(d->count, d->colors.count());
-}
-
-/*!
- Append the points in \a ary to this geometry data as position fields.
-*/
-void QGeometryData::appendVertexArray(const QVector3DArray &ary)
-{
- if (ary.count())
- {
- create();
- d->modified = true;
- d->boxValid = false;
- enableField(QGL::Position);
- d->vertices.append(ary);
- d->count = qMax(d->count, d->vertices.count());
- }
-}
-
-/*!
- Append the points in \a ary to this geometry data, as an attribute \a field entries.
-*/
-void QGeometryData::appendAttributeArray(const QCustomDataArray &ary, QGL::VertexAttribute field)
-{
- if (ary.count())
- {
- create();
- d->modified = true;
- enableField(field);
- d->attributes[d->key[field]].append(ary);
- d->count = qMax(d->count, d->attributes[d->key[field]].count());
- }
-}
-
-/*!
- Append the vectors in \a ary to this geometry data, as lighting normals.
-*/
-void QGeometryData::appendNormalArray(const QVector3DArray &ary)
-{
- if (ary.count())
- {
- create();
- d->modified = true;
- enableField(QGL::Normal);
- d->normals.append(ary);
- d->count = qMax(d->count, d->normals.count());
- }
-}
-
-/*!
- Append the 2D points in \a ary to this geometry data, as texture \a field entries.
-*/
-void QGeometryData::appendTexCoordArray(const QVector2DArray &ary, QGL::VertexAttribute field)
-{
- if (ary.count())
- {
- create();
- d->modified = true;
- enableField(field);
- d->textures[d->key[field]].append(ary);
- d->count = qMax(d->count, d->textures[d->key[field]].count());
- }
-}
-
-/*!
- Append the colors in \a ary to this geometry data, as color fields.
-*/
-void QGeometryData::appendColorArray(const QArray<QColor4ub> &ary)
-{
- if (ary.count())
- {
- create();
- d->modified = true;
- enableField(QGL::Color);
- d->colors.append(ary);
- d->count = qMax(d->count, d->colors.count());
- }
-}
-
-/*!
- Returns a modifiable reference to the vertex data at index \a i.
-*/
-QVector3D &QGeometryData::vertex(int i)
-{
- create();
- d->modified = true;
- d->boxValid = false;
- return d->vertices[i];
-}
-
-/*!
- Returns a copy of the vertex position data.
-*/
-QVector3DArray QGeometryData::vertices() const
-{
- if (d)
- return d->vertices;
- return QArray<QVector3D>();
-}
-
-/*!
- \internal
- Returns a pointer to the vertex data.
-*/
-const QVector3DArray *QGeometryData::vertexData() const
-{
- if (d)
- return &d->vertices;
- return 0;
-}
-
-
-/*!
- Returns a non-modifiable reference to the vertex position data at index \a i.
-*/
-const QVector3D &QGeometryData::vertexAt(int i) const
-{
- Q_ASSERT(hasField(QGL::Position));
- return d->vertices.at(i);
-}
-
-/*!
- Returns a modifiable reference to the normal data at index \a i.
-*/
-QVector3D &QGeometryData::normal(int i)
-{
- create();
- d->modified = true;
- return d->normals[i];
-}
-
-/*!
- Returns a non-modifiable reference to the normal data at index \a i.
-*/
-const QVector3D &QGeometryData::normalAt(int i) const
-{
- Q_ASSERT(hasField(QGL::Normal));
- return d->normals.at(i);
-}
-
-/*!
- Returns a copy of the lighting normal data.
-*/
-QVector3DArray QGeometryData::normals() const
-{
- if (d)
- return d->normals;
- return QArray<QVector3D>();
-}
-
-/*!
- Returns a modifiable reference to the color data at index \a i.
-*/
-QColor4ub &QGeometryData::color(int i)
-{
- create();
- d->modified = true;
- return d->colors[i];
-}
-
-/*!
- Returns a non-modifiable reference to the color data at index \a i.
-*/
-const QColor4ub &QGeometryData::colorAt(int i) const
-{
- Q_ASSERT(hasField(QGL::Color));
- return d->colors.at(i);
-}
-
-/*!
- Returns a copy of the color data.
-*/
-QArray<QColor4ub> QGeometryData::colors() const
-{
- if (d)
- return d->colors;
- return QArray<QColor4ub>();
-}
-
-/*!
- Returns a modifiable reference to the \a field texture coordinate data at index \a i.
-*/
-QVector2D &QGeometryData::texCoord(int i, QGL::VertexAttribute field)
-{
- create();
- d->modified = true;
- return d->textures[d->key[field]][i];
-}
-
-/*!
- Returns a copy of the \a field texture coordinate data.
-*/
-QVector2DArray QGeometryData::texCoords(QGL::VertexAttribute field) const
-{
- return hasField(field) ? d->textures.at(d->key[field]) : QVector2DArray();
-}
-
-/*!
- Returns a non-modifiable reference to the texture coordinate data at index \a i for \a field.
-*/
-const QVector2D &QGeometryData::texCoordAt(int i, QGL::VertexAttribute field) const
-{
- Q_ASSERT(hasField(field));
- return d->textures.at(d->key[field]).at(i);
-}
-
-/*!
- Returns a modifiable reference to the float \a field attribute data at index \a i.
-*/
-float &QGeometryData::floatAttribute(int i, QGL::VertexAttribute field)
-{
- create();
- d->modified = true;
- QCustomDataArray &ary = d->attributes[d->key[field]];
- Q_ASSERT(ary.elementType() == QCustomDataArray::Float);
- return ary.m_array[i];
-}
-
-/*!
- Returns a modifiable reference to the 2D vector \a field attribute data at index \a i.
-*/
-QVector2D &QGeometryData::vector2DAttribute(int i, QGL::VertexAttribute field)
-{
- create();
- d->modified = true;
- QCustomDataArray &ary = d->attributes[d->key[field]];
- Q_ASSERT(ary.elementType() == QCustomDataArray::Vector2D);
- float *data = ary.m_array.data();
- QVector2D *v = reinterpret_cast<QVector2D*>(data + i*2);
- return *v;
-}
-
-/*!
- Returns a modifiable reference to the 3D vector \a field attribute data at index \a i.
-*/
-QVector3D &QGeometryData::vector3DAttribute(int i, QGL::VertexAttribute field)
-{
- create();
- d->modified = true;
- QCustomDataArray &ary = d->attributes[d->key[field]];
- Q_ASSERT(ary.elementType() == QCustomDataArray::Vector3D);
- float *data = ary.m_array.data();
- QVector3D *v = reinterpret_cast<QVector3D*>(data + i*2);
- return *v;
-}
-
-/*!
- Returns a copy of the \a field attribute data.
-*/
-QCustomDataArray QGeometryData::attributes(QGL::VertexAttribute field) const
-{
- return hasField(field) ? d->attributes.at(d->key[field]) : QCustomDataArray();
-}
-
-/*!
- Returns a copy of the float \a field attribute data at index \a i.
-*/
-float QGeometryData::floatAttributeAt(int i, QGL::VertexAttribute field) const
-{
- Q_ASSERT(hasField(field));
- return d->attributes.at(d->key[field]).floatAt(i);
-}
-
-/*!
- Returns a copy of the 2D vector \a field attribute data at index \a i.
-*/
-QVector2D QGeometryData::vector2DAttributeAt(int i, QGL::VertexAttribute field) const
-{
- Q_ASSERT(hasField(field));
- return d->attributes.at(d->key[field]).vector2DAt(i);
-}
-
-/*!
- Returns a copy of the 3D vector \a field attribute data at index \a i.
-*/
-QVector3D QGeometryData::vector3DAttributeAt(int i, QGL::VertexAttribute field) const
-{
- Q_ASSERT(hasField(field));
- return d->attributes.at(d->key[field]).vector3DAt(i);
-}
-
-/*!
- Returns the attribute value for the \a field, suitable for passing
- to QGLPainter.
-
- \sa QGLPainter::setVertexAttribute()
-*/
-QGLAttributeValue QGeometryData::attributeValue(QGL::VertexAttribute field) const
-{
- if (hasField(field))
- {
- if (field < QGL::TextureCoord0)
- {
- if (field == QGL::Position)
- return QGLAttributeValue(d->vertices);
- else if (field == QGL::Normal)
- return QGLAttributeValue(d->normals);
- else if (field == QGL::Color)
- return QGLAttributeValue(d->colors);
- }
- else
- {
- if (field < QGL::CustomVertex0)
- return QGLAttributeValue(d->textures.at(d->key[field]));
- else
- return QGLAttributeValue(d->attributes.at(d->key[field]));
- }
- }
- return QGLAttributeValue();
-}
-
-/*!
- Returns true if this geometry has the field corresponding to \a attr. Note
- that it is still possible for no data to have been added for that field.
-*/
-bool QGeometryData::hasField(QGL::VertexAttribute attr) const
-{
- if (d)
- return d->key[attr] != -1;
- return false;
-}
-
-/*!
- Enables this geometry to contain data of type \a field. Generally it is
- not necessary to call this function since it is called by all the append
- functions.
-*/
-void QGeometryData::enableField(QGL::VertexAttribute field)
-{
- if (d && d->key[field] != -1)
- return;
- create();
- d->modified = true;
- Q_ASSERT(field < d->ATTR_CNT); // don't expand that enum too much
- d->fields |= (1 << field);
- switch (field)
- {
- case QGL::Position:
- d->key[QGL::Position] = 0;
- d->size[QGL::Position] = 3;
- if (d->reserved > 0)
- d->vertices.reserve(d->reserved);
- break;
- case QGL::Normal:
- d->key[QGL::Normal] = 1;
- d->size[QGL::Normal] = 3;
- if (d->reserved > 0)
- d->normals.reserve(d->reserved);
- break;
- case QGL::Color:
- d->key[QGL::Color] = 2;
- d->size[QGL::Color] = 1;
- if (d->reserved > 0)
- d->colors.reserve(d->reserved);
- break;
- case QGL::TextureCoord0:
- case QGL::TextureCoord1:
- case QGL::TextureCoord2:
- d->textures.append(QVector2DArray());
- d->key[field] = d->textures.count() - 1;
- d->size[field] = 2;
- if (d->reserved > 0)
- d->textures[d->key[field]].reserve(d->reserved);
- break;
- default:
- // Custom and User vertex attributes.
- d->attributes.append(QCustomDataArray());
- d->key[field] = d->attributes.count() - 1;
- d->size[field] = d->attributes.at(d->key[field]).elementSize();
- if (d->reserved > 0)
- d->attributes[d->key[field]].reserve(d->reserved);
- break;
- }
-}
-
-/*!
- Return a bit-mask of the supported fields in this geometry. The
- QGL::VertexAttribute enum can be recovered from this bit-mask by
- \code
- quint32 fields = fields();
- QGL::VertexAttribute attr = static_cast<QGL::VertexAttribute>(fields);
- \endcode
-*/
-quint32 QGeometryData::fields() const
-{
- if (d)
- return d->fields;
- return 0;
-}
-
-/*!
- Returns the count of logical vertices stored. This is effectively
- the max() of QArray::count() over all of the enabled data types.
-*/
-int QGeometryData::count() const
-{
- if (d)
- return d->count;
- return 0;
-}
-
-/*!
- Returns the count of data stored in \a field. This will always be at
- most count(), but could be less.
-*/
-int QGeometryData::count(QGL::VertexAttribute field) const
-{
- int result = 0;
- if (d && (QGL::fieldMask(field) & d->fields))
- {
- if (field < QGL::TextureCoord0)
- {
- if (field == QGL::Position)
- result = d->vertices.count();
- else if (field == QGL::Normal)
- result = d->normals.count();
- else
- result = d->colors.count();
- }
- else if (field < QGL::CustomVertex0)
- {
- result = d->textures[d->key[field]].count();
- }
- else
- {
- result = d->attributes[d->key[field]].count();
- }
- }
- return result;
-}
-
-/*!
- Returns true if this geometry is identical to the \a other; and false otherwise.
-*/
-bool QGeometryData::operator==(const QGeometryData &other) const
-{
- bool isEqual = false;
- if (d)
- {
- if (d == other.d)
- {
- isEqual = true;
- }
- else
- {
- if (other.d && d->fields == other.d->fields && d->count == other.d->count)
- {
- const quint32 mask = 0x01;
- quint32 fields = d->fields;
- isEqual = true;
- for (int field = 0; fields && isEqual; ++field, fields >>= 1)
- {
- if (mask & fields)
- {
- QGL::VertexAttribute attr = static_cast<QGL::VertexAttribute>(field);
- if (attr < QGL::TextureCoord0)
- {
- if (attr == QGL::Position)
- isEqual = (d->vertices == other.d->vertices);
- else if (attr == QGL::Normal)
- isEqual = (d->normals == other.d->normals);
- else // colors
- isEqual = (d->colors == other.d->colors);
- }
- else if (attr < QGL::CustomVertex0)
- {
- isEqual = (d->textures.at(d->key[attr]) == other.d->textures.at(d->key[attr]));
- }
- else
- {
- QArray<float> me = d->attributes.at(d->key[attr]).toFloatArray();
- QArray<float> him = other.d->attributes.at(d->key[attr]).toFloatArray();
- isEqual = (me == him);
- }
- }
- }
- }
- }
- }
- else
- {
- isEqual = other.isNull();
- }
- return isEqual;
-}
-
-/*!
- Returns true if this geometry is empty - that is it contains no vertices
- or other data - and returns false otherwise. If an existing geometry has
- been made empty by a call to clear() then this will be true (but isNull()
- will be false).
-
- \sa isNull()
-*/
-bool QGeometryData::isEmpty() const
-{
- bool empty = true;
- if (d)
- empty = d->count == 0;
- return empty;
-}
-
-/*!
- Returns true if this geometry is uninitialized - that is it contains no
- internal data structures. A newly constructed QGeometryData object is
- null until some data is added or changed.
-
- \sa isEmpty()
-*/
-bool QGeometryData::isNull() const
-{
- return d == NULL;
-}
-
-/*!
- Returns the number of index values stored in this geometry data.
-
- This value is exactly the same as indices().size() (but does not
- incur the copy).
-*/
-int QGeometryData::indexCount() const
-{
- if (d)
- return d->indices.size();
- return 0;
-}
-
-void QGeometryData::create()
-{
- if (!d) // lazy creation of data block
- {
- d = new QGeometryDataPrivate;
- d->ref.ref();
- }
-}
-
-/*!
- Force this geometry to ensure it has its own unshared internal data
- block, making a copy in the case that it is currently shared.
-*/
-void QGeometryData::detach()
-{
- create();
- if (d->ref > 1) // being shared, must detach
- {
- QGeometryDataPrivate *temp = d->clone();
- d->ref.deref();
- d = temp;
- d->ref.ref();
- }
-}
-
-/*!
- \fn quint64 QGeometryData::id() const
- Return an opaque value that can be used to identify which data block is
- being used by this QGeometryData instance. See the class documentation
- relating to explicit sharing.
-*/
-
-#ifndef QT_NO_DEBUG
-void QGeometryData::check() const
-{
- if (!d)
- return;
- const quint32 mask = 0x01;
- quint32 fields = d->fields;
- for (int field = 0; fields; ++field, fields >>= 1)
- {
- if (mask & fields)
- {
- QGL::VertexAttribute attr = static_cast<QGL::VertexAttribute>(field);
- if (attr < QGL::TextureCoord0)
- {
- if (attr == QGL::Position)
- {
- if (d->vertices.count() < d->count)
- qWarning("QGeometryData - expected %d vertices, only %d found!",
- d->count, d->vertices.count());
- }
- else if (attr == QGL::Normal)
- {
- if (d->normals.count() < d->count)
- qWarning("QGeometryData - expected %d normals, only %d found!",
- d->count, d->normals.count());
- }
- else
- {
- if (d->colors.count() < d->count)
- qWarning("QGeometryData - expected %d colors, only %d found!",
- d->count, d->colors.count());
- }
- }
- else if (attr < QGL::CustomVertex0)
- {
- if (d->textures.at(d->key[field]).count() < d->count)
- qWarning("QGeometryData - expected %d texture coordinates for"
- "QGL::TextureCoord%d, only %d found!",
- d->count, field - QGL::TextureCoord0, d->textures.at(d->key[field]).count());
- }
- else
- {
- if (d->attributes.at(d->key[field]).count() < d->count)
- qWarning("QGeometryData - expected %d attributes for"
- "QGL::CustomVertex%d, only %d found!",
- d->count, field - QGL::CustomVertex0, d->attributes.at(d->key[field]).count());
- }
- }
- }
-}
-#endif
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QGeometryData &vertices)
-{
- dbg << "QGeometryData" << &vertices << " size:" << vertices.count()
-#ifndef QT_NO_DEBUG
- << "data block id:" << vertices.id()
-#endif
- ;
- quint32 fields = vertices.fields();
- const quint32 mask = 0x01;
- for (int field = 0; fields; ++field, fields >>= 1)
- {
- if (mask & fields)
- {
- QGL::VertexAttribute attr = static_cast<QGL::VertexAttribute>(field);
- if (attr < QGL::TextureCoord0)
- {
- if (attr == QGL::Position)
- {
- dbg << " vertices:" << vertices.count(attr);
- dbg << vertices.vertices();
- }
- else if (attr == QGL::Normal)
- {
- dbg << " normals:" << vertices.count(attr);
- dbg << vertices.normals();
- }
- else
- {
- dbg << " colors:" << vertices.count(attr);
- dbg << vertices.colors();
- }
- }
- else if (attr < QGL::CustomVertex0)
- {
- dbg << " textures:" << (attr - QGL::TextureCoord0) << vertices.count(attr);
- dbg << vertices.texCoords(attr);
- }
- else
- {
- dbg << " custom:" << (attr - QGL::CustomVertex0) << vertices.count(attr);
- dbg << vertices.texCoords(attr);
- }
- }
- }
- if (vertices.indexCount() > 0)
- {
- dbg << " indices:" << vertices.indices();
- }
- return dbg;
-}
-
-QT_END_NAMESPACE
-
-#endif