summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2016-09-30 14:34:00 +0100
committerJani Heikkinen <jani.heikkinen@qt.io>2016-10-10 05:41:44 +0000
commit7fbbcaf280618c03da22cebac690b088d2b3ba03 (patch)
tree9f773fee553d9dba52d8b75b19a7f26f8083cd12 /src
parent387eebab1ea3b10d777b1c92d04804afb215c52c (diff)
Add unit test for QTorusGeometry
Also fix up some more problems with the torus. We were drawing some triangles more than once due to problems in the indexing. Fixed this by factoring out the calculations of number of vertices and triangles and takign care about needing more vertices to handle the texture coordinate wrapping at the seams but not more indices. Also renamed some members in the functors to be more consistent. Now the torus geometry should be perfect. Change-Id: I1198469531a5fd5e4ec8b86d47c9e66850fe50c7 Reviewed-by: Kevin Ottens <kevin.ottens@kdab.com>
Diffstat (limited to 'src')
-rw-r--r--src/extras/geometries/qtorusgeometry.cpp99
1 files changed, 58 insertions, 41 deletions
diff --git a/src/extras/geometries/qtorusgeometry.cpp b/src/extras/geometries/qtorusgeometry.cpp
index aab466b13..c088b3b67 100644
--- a/src/extras/geometries/qtorusgeometry.cpp
+++ b/src/extras/geometries/qtorusgeometry.cpp
@@ -54,10 +54,27 @@ namespace Qt3DExtras {
namespace {
+int vertexCount(int requestedRings, int requestedSlices)
+{
+ return (requestedRings + 1) * (requestedSlices + 1);
+}
+
+int triangleCount(int requestedRings, int requestedSlices)
+{
+ return 2 * requestedRings * requestedSlices;
+}
+
QByteArray createTorusVertexData(double radius, double minorRadius,
- int rings, int sides)
+ int rings, int slices)
{
- const int nVerts = sides * (rings + 1);
+ // The additional side and ring compared to what the user asked
+ // for is because we also need to ensure proper texture coordinate
+ // wrapping at the seams. Without this the last ring and side would
+ // interpolate the texture coordinates from ~0.9x back down to 0
+ // (the starting value at the first ring). So we insert an extra
+ // ring and side with the same positions as the first ring and side
+ // but with texture coordinates of 1 (compared to 0).
+ const int nVerts = vertexCount(rings, slices);
QByteArray bufferBytes;
// vec3 pos, vec2 texCoord, vec3 normal, vec4 tangent
const quint32 elementSize = 3 + 2 + 3 + 4;
@@ -66,18 +83,18 @@ QByteArray createTorusVertexData(double radius, double minorRadius,
float* fptr = reinterpret_cast<float*>(bufferBytes.data());
- const float ringFactor = (M_PI * 2) / static_cast<float>( rings );
- const float sideFactor = (M_PI * 2) / static_cast<float>( sides - 1 );
+ const float ringFactor = (M_PI * 2) / static_cast<float>(rings);
+ const float sliceFactor = (M_PI * 2) / static_cast<float>(slices);
for (int ring = 0; ring <= rings; ++ring) {
const float u = ring * ringFactor;
- const float cu = qCos( u );
- const float su = qSin( u );
+ const float cu = qCos(u);
+ const float su = qSin(u);
- for (int side = 0; side < sides; ++side) {
- const float v = side * sideFactor;
- const float cv = qCos( v + M_PI );
- const float sv = qSin( v );
+ for (int slice = 0; slice <= slices; ++slice) {
+ const float v = slice * sliceFactor;
+ const float cv = qCos(v + M_PI);
+ const float sv = qSin(v);
const float r = (radius + minorRadius * cv);
*fptr++ = r * cu;
@@ -87,7 +104,7 @@ QByteArray createTorusVertexData(double radius, double minorRadius,
*fptr++ = u / (M_PI * 2);
*fptr++ = v / (M_PI * 2);
- QVector3D n(cv * cu * r, cv * su * r, sv * r);
+ QVector3D n(cv * cu, cv * su, sv);
n.normalize();
*fptr++ = n.x();
*fptr++ = n.y();
@@ -105,26 +122,27 @@ QByteArray createTorusVertexData(double radius, double minorRadius,
return bufferBytes;
}
-QByteArray createTorusIndexData(int rings, int sides)
+QByteArray createTorusIndexData(int requestedRings, int requestedSlices)
{
- QByteArray indexBytes;
- int faces = (sides * 2) * rings; // two tris per side, for all rings
- int indices = faces * 3;
+ const int slices = requestedSlices + 1;
+ int triangles = triangleCount(requestedRings, requestedSlices);
+ int indices = triangles * 3;
Q_ASSERT(indices < 65536);
+ QByteArray indexBytes;
indexBytes.resize(indices * sizeof(quint16));
quint16* indexPtr = reinterpret_cast<quint16*>(indexBytes.data());
- for (int ring = 0; ring < rings; ++ring) {
- const int ringStart = ring * sides;
- const int nextRingStart = (ring + 1) * sides;
- for (int side = 0; side < sides; ++side) {
- const int nextSide = (side + 1) % sides;
- *indexPtr++ = ringStart + side;
- *indexPtr++ = ringStart + nextSide;
- *indexPtr++ = nextRingStart + side;
- *indexPtr++ = ringStart + nextSide;
- *indexPtr++ = nextRingStart + nextSide;
- *indexPtr++ = nextRingStart + side;
+ for (int ring = 0; ring < requestedRings; ++ring) {
+ const int ringStart = ring * slices;
+ const int nextRingStart = (ring + 1) * slices;
+ for (int slice = 0; slice < requestedSlices; ++slice) {
+ const int nextSlice = (slice + 1) % slices;
+ *indexPtr++ = ringStart + slice;
+ *indexPtr++ = ringStart + nextSlice;
+ *indexPtr++ = nextRingStart + slice;
+ *indexPtr++ = ringStart + nextSlice;
+ *indexPtr++ = nextRingStart + nextSlice;
+ *indexPtr++ = nextRingStart + slice;
}
}
@@ -138,7 +156,7 @@ class TorusVertexDataFunctor : public QBufferDataGenerator
public:
TorusVertexDataFunctor(int rings, int slices, float radius, float minorRadius)
: m_rings(rings)
- , m_sides(slices)
+ , m_slices(slices)
, m_radius(radius)
, m_minorRadius(minorRadius)
{
@@ -146,7 +164,7 @@ public:
QByteArray operator ()() Q_DECL_OVERRIDE
{
- return createTorusVertexData(m_radius, m_minorRadius, m_rings, m_sides);
+ return createTorusVertexData(m_radius, m_minorRadius, m_rings, m_slices);
}
bool operator ==(const QBufferDataGenerator &other) const Q_DECL_OVERRIDE
@@ -154,7 +172,7 @@ public:
const TorusVertexDataFunctor *otherFunctor = functor_cast<TorusVertexDataFunctor>(&other);
if (otherFunctor != nullptr)
return (otherFunctor->m_rings == m_rings &&
- otherFunctor->m_sides == m_sides &&
+ otherFunctor->m_slices == m_slices &&
otherFunctor->m_radius == m_radius &&
otherFunctor->m_minorRadius == m_minorRadius);
return false;
@@ -164,7 +182,7 @@ public:
private:
int m_rings;
- int m_sides;
+ int m_slices;
float m_radius;
float m_minorRadius;
};
@@ -174,13 +192,13 @@ class TorusIndexDataFunctor : public QBufferDataGenerator
public:
TorusIndexDataFunctor(int rings, int slices)
: m_rings(rings)
- , m_sides(slices)
+ , m_slices(slices)
{
}
QByteArray operator ()() Q_DECL_OVERRIDE
{
- return createTorusIndexData(m_rings, m_sides);
+ return createTorusIndexData(m_rings, m_slices);
}
bool operator ==(const QBufferDataGenerator &other) const Q_DECL_OVERRIDE
@@ -188,7 +206,7 @@ public:
const TorusIndexDataFunctor *otherFunctor = functor_cast<TorusIndexDataFunctor>(&other);
if (otherFunctor != nullptr)
return (otherFunctor->m_rings == m_rings &&
- otherFunctor->m_sides == m_sides);
+ otherFunctor->m_slices == m_slices);
return false;
}
@@ -196,7 +214,7 @@ public:
private:
int m_rings;
- int m_sides;
+ int m_slices;
};
QTorusGeometryPrivate::QTorusGeometryPrivate()
@@ -228,8 +246,8 @@ void QTorusGeometryPrivate::init()
// vec3 pos, vec2 tex, vec3 normal, vec4 tangent
const quint32 elementSize = 3 + 2 + 3 + 4;
const quint32 stride = elementSize * sizeof(float);
- const int nVerts = (m_slices + 1) * (m_rings + 1);
- const int faces = (m_slices * 2) * m_rings;
+ const int nVerts = vertexCount(m_rings, m_slices);
+ const int triangles = triangleCount(m_rings, m_slices);
m_positionAttribute->setName(QAttribute::defaultPositionAttributeName());
m_positionAttribute->setDataType(QAttribute::Float);
@@ -270,7 +288,7 @@ void QTorusGeometryPrivate::init()
m_indexAttribute->setDataType(QAttribute::UnsignedShort);
m_indexAttribute->setBuffer(m_indexBuffer);
- m_indexAttribute->setCount(faces * 3);
+ m_indexAttribute->setCount(triangles * 3);
m_vertexBuffer->setDataGenerator(QSharedPointer<TorusVertexDataFunctor>::create(m_rings, m_slices, m_radius, m_minorRadius));
m_indexBuffer->setDataGenerator(QSharedPointer<TorusIndexDataFunctor>::create(m_rings, m_slices));
@@ -385,7 +403,7 @@ QTorusGeometry::~QTorusGeometry()
void QTorusGeometry::updateVertices()
{
Q_D(QTorusGeometry);
- const int nVerts = d->m_slices * (d->m_rings + 1);
+ const int nVerts = vertexCount(d->m_rings, d->m_slices);
d->m_positionAttribute->setCount(nVerts);
d->m_texCoordAttribute->setCount(nVerts);
d->m_normalAttribute->setCount(nVerts);
@@ -398,10 +416,9 @@ void QTorusGeometry::updateVertices()
void QTorusGeometry::updateIndices()
{
Q_D(QTorusGeometry);
- const int faces = (d->m_slices * 2) * d->m_rings;
- d->m_indexAttribute->setCount(faces * 3);
+ const int triangles = triangleCount(d->m_rings, d->m_slices);
+ d->m_indexAttribute->setCount(triangles * 3);
d->m_indexBuffer->setDataGenerator(QSharedPointer<TorusIndexDataFunctor>::create(d->m_rings, d->m_slices));
-
}
void QTorusGeometry::setRings(int rings)