diff options
Diffstat (limited to 'src/threed/geometry/qglbezierpatches.cpp')
-rw-r--r-- | src/threed/geometry/qglbezierpatches.cpp | 815 |
1 files changed, 0 insertions, 815 deletions
diff --git a/src/threed/geometry/qglbezierpatches.cpp b/src/threed/geometry/qglbezierpatches.cpp deleted file mode 100644 index 6d97bc88..00000000 --- a/src/threed/geometry/qglbezierpatches.cpp +++ /dev/null @@ -1,815 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** 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 "qglbezierpatches.h" -#include "qglbuilder.h" -#include "qray3d.h" -#include "qtriangle3d.h" -#include <QtCore/qnumeric.h> - -QT_BEGIN_NAMESPACE - -/*! - \class QGLBezierPatches - \brief The QGLBezierPatches class represents 3D geometry as a set of Bezier bicubic patches. - \since 4.8 - \ingroup qt3d - \ingroup qt3d::geometry - - Bezier bicubic patches represent a curved 3D surface by four fixed - control points at indices 0, 3, 12, and 15, together with twelve - additional floating control points that define the surface - curvature. Bezier geometry objects are made up of one or more - such patches to define the surface of an object. - - The application specifies the vertex position data to the - constructor, and can optionally provide an index array. - The class interprets groups of 16 vertices as the control - points for successive patches. - - A mesh defined by QGLBezierPatches is subdivided into flat - triangles for rendering when the \c{<<} operator is used - to add the patches to a QGLBuilder. - - Many curved 3D objects can be defined as being made up of Bezier - bicubic patches, stitched together into a mesh. The most famous - Bezier bicubic object is probably the classic 3D "Utah Teapot", - first rendered in 1975. The QGLTeapot class provides a built-in - implementation of this object for testing purposes. - - If texture co-ordinates are supplied via setTextureCoords(), - then patch texture co-ordinates will be derived from the - specified values as the patches are subdivided. Otherwise, - QGLBezierPatches will generate texture co-ordinates for each - patch based on the default square from (0, 0) to (1, 1). - The first vertex in the patch corresponds to (0, 0), - and the opposite vertex in the patch corresponds to (1, 1). - - \sa QGLBuilder, QGLTeapot -*/ - -class QGLBezierPatchesPrivate -{ -public: - QGLBezierPatchesPrivate() - : subdivisionDepth(4) {} - QGLBezierPatchesPrivate(const QGLBezierPatchesPrivate *other) - : positions(other->positions) - , textureCoords(other->textureCoords) - , subdivisionDepth(other->subdivisionDepth) {} - - void copy(const QGLBezierPatchesPrivate *other) - { - positions = other->positions; - textureCoords = other->textureCoords; - subdivisionDepth = other->subdivisionDepth; - } - - void subdivide(QGLBuilder *list) const; - qreal intersection - (const QRay3D &ray, bool anyIntersection, QVector2D *texCoord, int *patch) const; - - QVector3DArray positions; - QVector2DArray textureCoords; - int subdivisionDepth; -}; - -// Temporary patch data for performing sub-divisions. -class QGLBezierPatch -{ -public: - // Control points for this mesh. - QVector3D points[16]; - - // Triangle mesh indices of the control points at each corner. - int indices[4]; - - QVector3D normal(qreal s, qreal t) const; - void convertToTriangles - (QGeometryData *prim, - qreal xtex, qreal ytex, qreal wtex, qreal htex); - void subDivide(QGLBezierPatch &patch1, QGLBezierPatch &patch2, - QGLBezierPatch &patch3, QGLBezierPatch &patch4); - void createNewCorners(QGLBezierPatch &patch1, QGLBezierPatch &patch2, - QGLBezierPatch &patch3, QGLBezierPatch &patch4, - QGeometryData *prim, - qreal xtex, qreal ytex, qreal wtex, qreal htex); - void recursiveSubDivide - (QGeometryData *prim, - int depth, qreal xtex, qreal ytex, qreal wtex, qreal htex); - qreal intersection - (qreal result, int depth, const QRay3D &ray, bool anyIntersection, - qreal xtex, qreal ytex, qreal wtex, qreal htex, QVector2D *tc); -}; - -static int const cornerOffsets[] = {0, 3, 12, 15}; -static qreal const cornerS[] = {0.0f, 1.0f, 0.0f, 1.0f}; -static qreal const cornerT[] = {0.0f, 0.0f, 1.0f, 1.0f}; - -// Helper functions for calculating the components of the Bernstein -// polynomial and its derivative that make up the surface. -static inline qreal b0(qreal v) -{ - return (1.0f - v) * (1.0f - v) * (1.0f - v); -} -static inline qreal b1(qreal v) -{ - return 3.0f * v * (1.0f - v) * (1.0f - v); -} -static inline qreal b2(qreal v) -{ - return 2.0f * v * v * (1.0f - v); -} -static inline qreal b3(qreal v) -{ - return v * v * v; -} -static inline qreal db0(qreal v) -{ - return -3.0f * (1.0f - v) * (1.0f - v); -} -static inline qreal db1(qreal v) -{ - return -6.0f * v * (1.0f - v) + 3.0f * (1.0f - v) * (1.0f - v); -} -static inline qreal db2(qreal v) -{ - return -3.0f * v * v + 6.0f * v * (1.0f - v); -} -static inline qreal db3(qreal v) -{ - return 3.0f * v * v; -} - -// Compute the normal at a specific point in the patch. -// The s and t values vary between 0 and 1. -QVector3D QGLBezierPatch::normal(qreal s, qreal t) const -{ - qreal a[4]; - qreal b[4]; - qreal tx, ty, tz; - qreal sx, sy, sz; - - // Compute the derivative of the surface in t. - a[0] = b0(s); - a[1] = b1(s); - a[2] = b2(s); - a[3] = b3(s); - b[0] = db0(t); - b[1] = db1(t); - b[2] = db2(t); - b[3] = db3(t); - tx = 0.0f; - ty = 0.0f; - tz = 0.0f; - for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 4; ++j) { - tx += a[i] * points[j * 4 + i].x() * b[j]; - ty += a[i] * points[j * 4 + i].y() * b[j]; - tz += a[i] * points[j * 4 + i].z() * b[j]; - } - } - - // Compute the derivative of the surface in s. - a[0] = db0(s); - a[1] = db1(s); - a[2] = db2(s); - a[3] = db3(s); - b[0] = b0(t); - b[1] = b1(t); - b[2] = b2(t); - b[3] = b3(t); - sx = 0.0f; - sy = 0.0f; - sz = 0.0f; - for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 4; ++j) { - sx += a[i] * points[j * 4 + i].x() * b[j]; - sy += a[i] * points[j * 4 + i].y() * b[j]; - sz += a[i] * points[j * 4 + i].z() * b[j]; - } - } - - // The normal is the cross-product of the two derivatives, - // normalized to a unit vector. - QVector3D n = QVector3D::normal(QVector3D(sx, sy, sz), QVector3D(tx, ty, tz)); - if (n.isNull()) { - // A zero normal may occur if one of the patch edges is zero-length. - // We correct for this by substituting an overall patch normal that - // we compute from two of the sides that are not zero in length. - QVector3D sides[4]; - QVector3D vectors[2]; - sides[0] = points[3] - points[0]; - sides[1] = points[15] - points[3]; - sides[2] = points[12] - points[15]; - sides[3] = points[0] - points[12]; - int i = 0; - int j = 0; - vectors[0] = QVector3D(1.0f, 0.0f, 0.0f); - vectors[1] = QVector3D(0.0f, 1.0f, 0.0f); - while (i < 2 && j < 4) { - if (sides[j].isNull()) - ++j; - else - vectors[i++] = sides[j++]; - } - n = QVector3D::normal(vectors[0], vectors[1]); - } - return n; -} - -// Convert this patch into flat triangles. -void QGLBezierPatch::convertToTriangles - (QGeometryData *prim, - qreal xtex, qreal ytex, qreal wtex, qreal htex) -{ - // The edges are considered ok if they have a non-zero length. - // Zero-length edges can occur in triangular-shaped patches. - // There is no point generating triangles along such edges. - bool edge1ok = (points[0] != points[3]); - bool edge2ok = (points[0] != points[12]); - bool edge3ok = (points[12] != points[15]); - bool edge4ok = (points[15] != points[3]); - - // Find the mid-point on the patch by averaging the corners. - QVector3D mid = (points[0] + points[3] + points[12] + points[15]) / 4.0f; - - // Allocate a triangle mesh vertex for the mid-point. - int midIndex = prim->count(); - prim->appendVertex(mid); - prim->appendNormal(normal(0.5f, 0.5f)); - prim->appendTexCoord - (QVector2D(xtex + wtex / 2.0f, ytex + htex / 2.0f)); - - // Divide the patch into 4 triangles pointing at the center. - if (edge1ok) - prim->appendIndices(indices[0], indices[1], midIndex); - if (edge2ok) - prim->appendIndices(indices[2], indices[0], midIndex); - if (edge3ok) - prim->appendIndices(indices[3], indices[2], midIndex); - if (edge4ok) - prim->appendIndices(indices[1], indices[3], midIndex); -} - -// Sub-divide a Bezier curve (p1, p2, p3, p4) into two new -// Bezier curves (l1, l2, l3, l4) and (r1, r2, r3, r4). -static void subDivideBezierCurve - (const QVector3D &p1, const QVector3D &p2, - const QVector3D &p3, const QVector3D &p4, - QVector3D &l1, QVector3D &l2, QVector3D &l3, QVector3D &l4, - QVector3D &r1, QVector3D &r2, QVector3D &r3, QVector3D &r4) -{ - l1 = p1; - l2 = (p1 + p2) / 2.0f; - QVector3D h = (p2 + p3) / 2.0f; - l3 = (l2 + h) / 2.0f; - r3 = (p3 + p4) / 2.0f; - r2 = (h + r3) / 2.0f; - l4 = r1 = (l3 + r2) / 2.0f; - r4 = p4; -} - -// Sub-divide this patch into four new patches. The triangle mesh -// is used to allocate vertices for the corners of the new patches. -void QGLBezierPatch::subDivide - (QGLBezierPatch &patch1, QGLBezierPatch &patch2, - QGLBezierPatch &patch3, QGLBezierPatch &patch4) -{ - // Sub-divide the Bezier curves for the control rows to create - // four rows of 8 control points. These define the left and - // right halves of the patch. - QVector3D row1[8]; - QVector3D row2[8]; - QVector3D row3[8]; - QVector3D row4[8]; - subDivideBezierCurve - (points[0], points[1], points[2], points[3], - row1[0], row1[1], row1[2], row1[3], row1[4], row1[5], row1[6], row1[7]); - subDivideBezierCurve - (points[4], points[5], points[6], points[7], - row2[0], row2[1], row2[2], row2[3], row2[4], row2[5], row2[6], row2[7]); - subDivideBezierCurve - (points[8], points[9], points[10], points[11], - row3[0], row3[1], row3[2], row3[3], row3[4], row3[5], row3[6], row3[7]); - subDivideBezierCurve - (points[12], points[13], points[14], points[15], - row4[0], row4[1], row4[2], row4[3], row4[4], row4[5], row4[6], row4[7]); - - // Now sub-divide the 8 columns to create the four new patches. - subDivideBezierCurve - (row1[0], row2[0], row3[0], row4[0], - patch1.points[0], patch1.points[4], patch1.points[8], patch1.points[12], - patch3.points[0], patch3.points[4], patch3.points[8], patch3.points[12]); - subDivideBezierCurve - (row1[1], row2[1], row3[1], row4[1], - patch1.points[1], patch1.points[5], patch1.points[9], patch1.points[13], - patch3.points[1], patch3.points[5], patch3.points[9], patch3.points[13]); - subDivideBezierCurve - (row1[2], row2[2], row3[2], row4[2], - patch1.points[2], patch1.points[6], patch1.points[10], patch1.points[14], - patch3.points[2], patch3.points[6], patch3.points[10], patch3.points[14]); - subDivideBezierCurve - (row1[3], row2[3], row3[3], row4[3], - patch1.points[3], patch1.points[7], patch1.points[11], patch1.points[15], - patch3.points[3], patch3.points[7], patch3.points[11], patch3.points[15]); - subDivideBezierCurve - (row1[4], row2[4], row3[4], row4[4], - patch2.points[0], patch2.points[4], patch2.points[8], patch2.points[12], - patch4.points[0], patch4.points[4], patch4.points[8], patch4.points[12]); - subDivideBezierCurve - (row1[5], row2[5], row3[5], row4[5], - patch2.points[1], patch2.points[5], patch2.points[9], patch2.points[13], - patch4.points[1], patch4.points[5], patch4.points[9], patch4.points[13]); - subDivideBezierCurve - (row1[6], row2[6], row3[6], row4[6], - patch2.points[2], patch2.points[6], patch2.points[10], patch2.points[14], - patch4.points[2], patch4.points[6], patch4.points[10], patch4.points[14]); - subDivideBezierCurve - (row1[7], row2[7], row3[7], row4[7], - patch2.points[3], patch2.points[7], patch2.points[11], patch2.points[15], - patch4.points[3], patch4.points[7], patch4.points[11], patch4.points[15]); -} - -void QGLBezierPatch::createNewCorners - (QGLBezierPatch &patch1, QGLBezierPatch &patch2, - QGLBezierPatch &patch3, QGLBezierPatch &patch4, - QGeometryData *prim, - qreal xtex, qreal ytex, qreal wtex, qreal htex) -{ - // Add vertices for the new patch corners we have created. - qreal hwtex = wtex / 2.0f; - qreal hhtex = htex / 2.0f; - int topPointIndex = prim->count(); - int leftPointIndex = topPointIndex + 1; - int midPointIndex = topPointIndex + 2; - int rightPointIndex = topPointIndex + 3; - int bottomPointIndex = topPointIndex + 4; - - prim->appendVertex(patch1.points[3]); - prim->appendNormal(normal(0.5f, 0.0f)); - prim->appendTexCoord(QVector2D(xtex + hwtex, ytex)); - - prim->appendVertex(patch1.points[12]); - prim->appendNormal(normal(0.0f, 0.5f)); - prim->appendTexCoord(QVector2D(xtex, ytex + hhtex)); - - prim->appendVertex(patch1.points[15]); - prim->appendNormal(normal(0.5f, 0.5f)); - prim->appendTexCoord(QVector2D(xtex + hwtex, ytex + hhtex)); - - prim->appendVertex(patch2.points[15]); - prim->appendNormal(normal(1.0f, 0.5f)); - prim->appendTexCoord(QVector2D(xtex + wtex, ytex + hhtex)); - - prim->appendVertex(patch3.points[15]); - prim->appendNormal(normal(0.5f, 1.0f)); - prim->appendTexCoord(QVector2D(xtex + hwtex, ytex + htex)); - - // Copy the indices for the corners of the new patches. - patch1.indices[0] = indices[0]; - patch1.indices[1] = topPointIndex; - patch1.indices[2] = leftPointIndex; - patch1.indices[3] = midPointIndex; - patch2.indices[0] = topPointIndex; - patch2.indices[1] = indices[1]; - patch2.indices[2] = midPointIndex; - patch2.indices[3] = rightPointIndex; - patch3.indices[0] = leftPointIndex; - patch3.indices[1] = midPointIndex; - patch3.indices[2] = indices[2]; - patch3.indices[3] = bottomPointIndex; - patch4.indices[0] = midPointIndex; - patch4.indices[1] = rightPointIndex; - patch4.indices[2] = bottomPointIndex; - patch4.indices[3] = indices[3]; -} - -// Recursively sub-divide a patch into triangles. -void QGLBezierPatch::recursiveSubDivide - (QGeometryData *prim, - int depth, qreal xtex, qreal ytex, qreal wtex, qreal htex) -{ - if (depth <= 1) { - convertToTriangles(prim, xtex, ytex, wtex, htex); - } else { - QGLBezierPatch patch1, patch2, patch3, patch4; - subDivide(patch1, patch2, patch3, patch4); - createNewCorners(patch1, patch2, patch3, patch4, prim, xtex, ytex, wtex, htex); - --depth; - qreal hwtex = wtex / 2.0f; - qreal hhtex = htex / 2.0f; - patch1.recursiveSubDivide(prim, depth, xtex, ytex, hwtex, hhtex); - patch2.recursiveSubDivide(prim, depth, xtex + hwtex, ytex, hwtex, hhtex); - patch3.recursiveSubDivide(prim, depth, xtex, ytex + hhtex, hwtex, hhtex); - patch4.recursiveSubDivide(prim, depth, xtex + hwtex, ytex + hhtex, hwtex, hhtex); - } -} - -void QGLBezierPatchesPrivate::subdivide(QGLBuilder *list) const -{ - QGeometryData prim; - int count = positions.size(); - for (int posn = 0; (posn + 15) < count; posn += 16) { - // Construct a QGLBezierPatch object from the next high-level patch. - QGLBezierPatch patch; - int vertex; - for (int vertex = 0; vertex < 16; ++vertex) - patch.points[vertex] = positions[posn + vertex]; - QVector2D tex1, tex2; - if (!textureCoords.isEmpty()) { - tex1 = textureCoords[(posn / 16) * 2]; - tex2 = textureCoords[(posn / 16) * 2 + 1]; - } else { - tex1 = QVector2D(0.0f, 0.0f); - tex2 = QVector2D(1.0f, 1.0f); - } - qreal xtex = tex1.x(); - qreal ytex = tex1.y(); - qreal wtex = tex2.x() - xtex; - qreal htex = tex2.y() - ytex; - for (int corner = 0; corner < 4; ++corner) { - vertex = posn + cornerOffsets[corner]; - QVector3D n = patch.normal(cornerS[corner], cornerT[corner]); - patch.indices[corner] = prim.count(); - prim.appendVertex(patch.points[cornerOffsets[corner]]); - prim.appendNormal(n); - prim.appendTexCoord - (QVector2D(xtex + wtex * cornerS[corner], - ytex + htex * cornerT[corner])); - } - - // Subdivide the patch and generate the final triangles. - patch.recursiveSubDivide(&prim, subdivisionDepth, - xtex, ytex, wtex, htex); - } - list->addTriangles(prim); -} - -static inline qreal combineResults(qreal result, qreal t) -{ - if (qIsNaN(result)) - return t; - if (t >= 0.0f) - return result < 0.0f ? t : qMin(result, t); - else - return result >= 0.0f ? result : qMax(result, t); -} - -qreal QGLBezierPatch::intersection - (qreal result, int depth, const QRay3D& ray, bool anyIntersection, - qreal xtex, qreal ytex, qreal wtex, qreal htex, QVector2D *tc) -{ - // Check the convex hull of the patch for an intersection. - // If no intersection with the convex hull, then there is - // no point subdividing this patch further. - QBox3D box; - for (int point = 0; point < 16; ++point) - box.unite(points[point]); - if (!box.intersects(ray)) - return result; - - // Are we at the lowest point of subdivision yet? - if (depth <= 1) { - // Divide the patch into two triangles and intersect with those. - QTriangle3D triangle1(points[0], points[3], points[12]); - qreal t = triangle1.intersection(ray); - if (!qIsNaN(t)) { - result = combineResults(result, t); - if (result == t) { - QVector2D uv = triangle1.uv(ray.point(t)); - QVector2D tp(xtex, ytex); - QVector2D tq(xtex + wtex, ytex); - QVector2D tr(xtex, ytex + htex); - *tc = uv.x() * tp + uv.y() * tq + (1 - uv.x() - uv.y()) * tr; - } - } else { - QTriangle3D triangle2(points[3], points[15], points[12]); - qreal t = triangle2.intersection(ray); - if (!qIsNaN(t)) { - result = combineResults(result, t); - if (result == t) { - QVector2D uv = triangle2.uv(ray.point(t)); - QVector2D tp(xtex + wtex, ytex); - QVector2D tq(xtex + wtex, ytex + htex); - QVector2D tr(xtex, ytex + htex); - *tc = uv.x() * tp + uv.y() * tq + (1 - uv.x() - uv.y()) * tr; - } - } - } - } else { - // Subdivide the patch to find the point of intersection. - QGLBezierPatch patch1, patch2, patch3, patch4; - subDivide(patch1, patch2, patch3, patch4); - --depth; - qreal hwtex = wtex / 2.0f; - qreal hhtex = htex / 2.0f; - result = patch1.intersection - (result, depth, ray, anyIntersection, - xtex, ytex, hwtex, hhtex, tc); - if (anyIntersection && !qIsNaN(result)) - return result; - result = patch2.intersection - (result, depth, ray, anyIntersection, - xtex + hwtex, ytex, hwtex, hhtex, tc); - if (anyIntersection && !qIsNaN(result)) - return result; - result = patch3.intersection - (result, depth, ray, anyIntersection, - xtex, ytex + hhtex, hwtex, hhtex, tc); - if (anyIntersection && !qIsNaN(result)) - return result; - result = patch4.intersection - (result, depth, ray, anyIntersection, - xtex + hwtex, ytex + hhtex, hwtex, hhtex, tc); - } - return result; -} - -qreal QGLBezierPatchesPrivate::intersection - (const QRay3D &ray, bool anyIntersection, QVector2D *texCoord, int *bestPatch) const -{ - int count = positions.size(); - qreal result = qSNaN(); - QVector2D tc; - if (bestPatch) - *bestPatch = -1; - for (int posn = 0; (posn + 15) < count; posn += 16) { - QGLBezierPatch patch; - for (int vertex = 0; vertex < 16; ++vertex) - patch.points[vertex] = positions[posn + vertex]; - QVector2D tex1, tex2; - if (!textureCoords.isEmpty()) { - tex1 = textureCoords[(posn / 16) * 2]; - tex2 = textureCoords[(posn / 16) * 2 + 1]; - } else { - tex1 = QVector2D(0.0f, 0.0f); - tex2 = QVector2D(1.0f, 1.0f); - } - qreal xtex = tex1.x(); - qreal ytex = tex1.y(); - qreal wtex = tex2.x() - xtex; - qreal htex = tex2.y() - ytex; - qreal prev = result; - result = patch.intersection - (result, subdivisionDepth, ray, anyIntersection, - xtex, ytex, wtex, htex, &tc); - if (bestPatch && result != prev) - *bestPatch = posn / 16; - if (anyIntersection && !qIsNaN(result)) - break; - } - if (texCoord && !qIsNaN(result)) - *texCoord = tc; - return result; -} - -/*! - Constructs an empty Bezier patch list. - - \sa setPositions() -*/ -QGLBezierPatches::QGLBezierPatches() - : d_ptr(new QGLBezierPatchesPrivate()) -{ -} - -/*! - Constructs a copy of \a other. - - \sa operator=() -*/ -QGLBezierPatches::QGLBezierPatches(const QGLBezierPatches &other) - : d_ptr(new QGLBezierPatchesPrivate(other.d_ptr.data())) -{ -} - -/*! - Destroys this Bezier patch list. -*/ -QGLBezierPatches::~QGLBezierPatches() -{ -} - -/*! - Assigns \a other to this Bezier patch list. -*/ -QGLBezierPatches &QGLBezierPatches::operator= - (const QGLBezierPatches &other) -{ - if (this != &other) - d_ptr->copy(other.d_ptr.data()); - return *this; -} - -/*! - Returns the positions of the vertices in the Bezier patches. - - \sa setPositions(), textureCoords() -*/ -QVector3DArray QGLBezierPatches::positions() const -{ - Q_D(const QGLBezierPatches); - return d->positions; -} - -/*! - Sets the \a positions of the vertices in the Bezier patches. - - \sa positions(), setTextureCoords() -*/ -void QGLBezierPatches::setPositions(const QVector3DArray &positions) -{ - Q_D(QGLBezierPatches); - d->positions = positions; -} - -/*! - Returns the texture co-ordinates for the Bezier patches. - Each patch consumes two elements from the texture - co-ordinate array, defining the opposite corners. - - The default is an empty array, which indicates that each - patch will generate texture co-ordinates in the range - (0, 0) to (1, 1). - - \sa setTextureCoords(), positions() -*/ -QVector2DArray QGLBezierPatches::textureCoords() const -{ - Q_D(const QGLBezierPatches); - return d->textureCoords; -} - -/*! - Sets the texture co-ordinates for the Bezier patches to - the elements of \a textureCoords. Each patch consumes - two elements from \a textureCoords, defining the opposite - corners. - - If \a textureCoords is empty, then each patch will generate - texture co-ordinates in the range (0, 0) to (1, 1). - - \sa textureCoords(), setPositions() -*/ -void QGLBezierPatches::setTextureCoords(const QVector2DArray &textureCoords) -{ - Q_D(QGLBezierPatches); - d->textureCoords = textureCoords; -} - -/*! - Returns the depth of subdivision to use when converting the - Bezier geometry into triangles. The default value is 4. - - \sa setSubdivisionDepth() -*/ -int QGLBezierPatches::subdivisionDepth() const -{ - Q_D(const QGLBezierPatches); - return d->subdivisionDepth; -} - -/*! - Sets the depth of subdivision to use when converting the - Bezier geometry into triangles to \a value. - - \sa subdivisionDepth() -*/ -void QGLBezierPatches::setSubdivisionDepth(int value) -{ - Q_D(QGLBezierPatches); - d->subdivisionDepth = value; -} - -/*! - Transforms the positions() in this Bezier geometry object - according to \a matrix. - - \sa transformed() -*/ -void QGLBezierPatches::transform(const QMatrix4x4 &matrix) -{ - Q_D(QGLBezierPatches); - d->positions.transform(matrix); -} - -/*! - Returns a new Bezier geometry object that results from transforming - this object's positions() according to \a matrix. - - \sa transform() -*/ -QGLBezierPatches QGLBezierPatches::transformed(const QMatrix4x4 &matrix) const -{ - QGLBezierPatches result(*this); - result.d_ptr->positions.transform(matrix); - return result; -} - -/*! - Returns true if \a ray intersects this Bezier geometry object; - false otherwise. - - \sa intersection() -*/ -bool QGLBezierPatches::intersects(const QRay3D &ray) const -{ - Q_D(const QGLBezierPatches); - return !qIsNaN(d->intersection(ray, true, 0, 0)); -} - -/*! - Returns the t value at which \a ray intersects this Bezier - geometry object, or not-a-number if there is no intersection. - - When the \a ray intersects this object, the return value is a - parametric value that can be passed to QRay3D::point() to determine - the actual intersection point, as shown in the following example: - - \code - qreal t = patches.intersection(ray); - QVector3D pt; - if (qIsNaN(t)) { - qWarning("no intersection occurred"); - else - pt = ray.point(t); - \endcode - - If \a ray intersects the object multiple times, the returned - t will be the smallest t value, corresponding to the first - intersection of the \a ray with the object. The t value may - be negative if the first intersection occurs in the reverse - direction of \a ray. - - The intersection is determined by subdividing the patches into - triangles and intersecting with those triangles. A pruning - algorithm is used to discard patches whose convex hull do not - intersect with \a ray. - - If \a texCoord is not null, then it will return the texture - co-ordinate of the intersection point. - - If \a patch is not null, then it will return the index of the - patch that contains the intersection, or -1 if there is no - intersection. - - \sa intersects() -*/ -qreal QGLBezierPatches::intersection(const QRay3D &ray, QVector2D *texCoord, int *patch) const -{ - Q_D(const QGLBezierPatches); - return d->intersection(ray, false, texCoord, patch); -} - -/*! - \relates QGLBezierPatches - - Subdivides the Bezier patch data in \a patches into triangles - and adds them to the specified display \a list. -*/ -QGLBuilder &operator<<(QGLBuilder &list, const QGLBezierPatches &patches) -{ - patches.d_ptr->subdivide(&list); - return list; -} - -QT_END_NAMESPACE |